code style
This commit is contained in:
@@ -26,4 +26,4 @@ bool libebus_contrib_register() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
@@ -32,6 +32,6 @@ namespace ebusd {
|
||||
*/
|
||||
bool libebus_contrib_register();
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_CONTRIB_CONTRIB_H_
|
||||
#endif // LIB_EBUS_CONTRIB_CONTRIB_H_
|
||||
|
||||
@@ -73,11 +73,11 @@ result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
}
|
||||
int grp = 0, num = 0;
|
||||
if (isMaster) {
|
||||
grp = (value & 0x1f); // grp in bits 0...5
|
||||
num = ((value >> 8) & 0x7f); // num in bits 8...13
|
||||
grp = (value & 0x1f); // grp in bits 0...5
|
||||
num = ((value >> 8) & 0x7f); // num in bits 8...13
|
||||
} else {
|
||||
grp = ((value >> 7) & 0x1f); // grp in bits 7...11
|
||||
num = (value & 0x7f); // num in bits 0...6
|
||||
grp = ((value >> 7) & 0x1f); // grp in bits 7...11
|
||||
num = (value & 0x7f); // num in bits 0...6
|
||||
}
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
@@ -86,7 +86,7 @@ result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
if (outputFormat & OF_JSON) {
|
||||
output << '"';
|
||||
}
|
||||
output << setfill(' ') << setw(0); // reset
|
||||
output << setfill(' ') << setw(0); // reset
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -99,45 +99,45 @@ result_t TemParamDataType::writeSymbols(istringstream& input,
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
if (strcasecmp(str, NULL_VALUE) == 0) {
|
||||
value = m_replacement; // replacement value
|
||||
value = m_replacement; // replacement value
|
||||
} else {
|
||||
if (input.eof() || !getline(input, token, '-')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
str = token.c_str();
|
||||
if (str == NULL || *str == 0) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
char* strEnd = NULL;
|
||||
grp = (unsigned int)strtoul(str, &strEnd, 10);
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (input.eof() || !getline(input, token, '-')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
str = token.c_str();
|
||||
if (str == NULL || *str == 0) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
strEnd = NULL;
|
||||
num = (unsigned int)strtoul(str, &strEnd, 10);
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (grp < 0 || grp > 0x1f || num < 0 || num > 0x7f) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
if (isMaster) {
|
||||
value = grp | (num << 8); // grp in bits 0...5, num in bits 8...13
|
||||
value = grp | (num << 8); // grp in bits 0...5, num in bits 8...13
|
||||
} else {
|
||||
value = (grp << 7) | num; // grp in bits 7...11, num in bits 0...6
|
||||
value = (grp << 7) | num; // grp in bits 7...11, num in bits 0...6
|
||||
}
|
||||
}
|
||||
if (value < getMinValue() || value > getMaxValue()) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
return writeRawValue(value, offset, length, output, usedLength);
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace ebusd {
|
||||
* data.
|
||||
*/
|
||||
class TemParamDataType : public NumberDataType {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param id the type identifier.
|
||||
@@ -68,6 +68,6 @@ class TemParamDataType : public NumberDataType {
|
||||
*/
|
||||
void contrib_tem_register();
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_CONTRIB_TEM_H_
|
||||
#endif // LIB_EBUS_CONTRIB_TEM_H_
|
||||
|
||||
@@ -108,7 +108,8 @@ int main() {
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false, (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false,
|
||||
(mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
@@ -132,13 +133,15 @@ int main() {
|
||||
SymbolString writeMstr(false);
|
||||
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
SymbolString writeSstr(false);
|
||||
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(pt_masterData, mstr, 0, output, 0, -1, false);
|
||||
@@ -183,7 +186,8 @@ int main() {
|
||||
error = true;
|
||||
} else {
|
||||
bool match = mstr == writeMstr && sstr == writeSstr;
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " " + sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
|
||||
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
}
|
||||
delete fields;
|
||||
fields = NULL;
|
||||
|
||||
+72
-64
@@ -60,7 +60,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
|
||||
// template: name,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
|
||||
// std: name,part,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
|
||||
const string name = *it++; // name
|
||||
const string name = *it++; // name
|
||||
if (it == end) {
|
||||
if (!name.empty()) {
|
||||
result = RESULT_ERR_MISSING_TYPE;
|
||||
@@ -71,7 +71,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
if (isTemplate) {
|
||||
partType = pt_any;
|
||||
} else {
|
||||
const char* partStr = (*it++).c_str(); // part
|
||||
const char* partStr = (*it++).c_str(); // part
|
||||
hasPartStr = partStr[0] != 0;
|
||||
if (it == end) {
|
||||
if (!name.empty() || hasPartStr) {
|
||||
@@ -81,10 +81,10 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
if (isBroadcastOrMasterDestination
|
||||
|| (isWriteMessage && !hasPartStr)
|
||||
|| strcasecmp(partStr, "M") == 0) { // master data
|
||||
|| strcasecmp(partStr, "M") == 0) { // master data
|
||||
partType = pt_masterData;
|
||||
} else if ((!isWriteMessage && !hasPartStr)
|
||||
|| strcasecmp(partStr, "S") == 0) { // slave data
|
||||
|| strcasecmp(partStr, "S") == 0) { // slave data
|
||||
partType = pt_slaveData;
|
||||
} else {
|
||||
result = RESULT_ERR_INVALID_PART;
|
||||
@@ -97,7 +97,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
firstComment = comment;
|
||||
}
|
||||
|
||||
const string typeStr = *it++; // basetype[:len]|template[:name]
|
||||
const string typeStr = *it++; // basetype[:len]|template[:name]
|
||||
vector<string>::iterator typePos = it;
|
||||
if (typeStr.empty()) {
|
||||
if (!name.empty() || hasPartStr) {
|
||||
@@ -110,13 +110,13 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
string constantValue;
|
||||
bool verifyValue = false;
|
||||
if (it != end) {
|
||||
const string divisorStr = *it++; // [divisor|values]
|
||||
const string divisorStr = *it++; // [divisor|values]
|
||||
if (!divisorStr.empty()) {
|
||||
size_t equalPos = divisorStr.find('=');
|
||||
if (equalPos == string::npos) {
|
||||
divisor = parseSignedInt(divisorStr.c_str(), 10, -MAX_DIVISOR, MAX_DIVISOR, result);
|
||||
} else if (equalPos == 0 && divisorStr.length() > 1) {
|
||||
verifyValue = divisorStr[1] == '='; // == forced verification of constant value
|
||||
verifyValue = divisorStr[1] == '='; // == forced verification of constant value
|
||||
if (verifyValue && divisorStr.length() == 1) {
|
||||
result = RESULT_ERR_INVALID_LIST;
|
||||
break;
|
||||
@@ -131,9 +131,9 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
unsigned long id;
|
||||
if (strncasecmp(str, "0x", 2) == 0) {
|
||||
str += 2;
|
||||
id = strtoul(str, &strEnd, 16); // hexadecimal
|
||||
id = strtoul(str, &strEnd, 16); // hexadecimal
|
||||
} else {
|
||||
id = strtoul(str, &strEnd, 10); // decimal
|
||||
id = strtoul(str, &strEnd, 10); // decimal
|
||||
}
|
||||
if (strEnd == NULL || strEnd == str || id > MAX_VALUE) {
|
||||
result = RESULT_ERR_INVALID_LIST;
|
||||
@@ -159,7 +159,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
if (it == end) {
|
||||
unit = "";
|
||||
} else {
|
||||
const string str = *it++; // [unit]
|
||||
const string str = *it++; // [unit]
|
||||
if (strcasecmp(str.c_str(), NULL_VALUE) == 0) {
|
||||
unit = "";
|
||||
} else {
|
||||
@@ -170,7 +170,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
if (it == end) {
|
||||
comment = "";
|
||||
} else {
|
||||
const string str = *it++; // [comment]
|
||||
const string str = *it++; // [comment]
|
||||
if (strcasecmp(str.c_str(), NULL_VALUE) == 0) {
|
||||
comment = "";
|
||||
} else {
|
||||
@@ -187,11 +187,11 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
if (templ == NULL && pos != string::npos) {
|
||||
templ = templates->get(token.substr(0, pos));
|
||||
}
|
||||
if (templ == NULL) { // basetype[:len]
|
||||
if (templ == NULL) { // basetype[:len]
|
||||
unsigned char length;
|
||||
string typeName;
|
||||
if (pos == string::npos) {
|
||||
length = 0; // no length specified
|
||||
length = 0; // no length specified
|
||||
typeName = token;
|
||||
} else {
|
||||
if (pos+2 == token.length() && token[pos+1] == '*') {
|
||||
@@ -206,29 +206,31 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper);
|
||||
SingleDataField* add = NULL;
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, constantValue, verifyValue, add);
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "",
|
||||
firstType ? unit : "", partType, divisor, values, constantValue, verifyValue, add);
|
||||
if (add != NULL) {
|
||||
fields.push_back(add);
|
||||
} else {
|
||||
it = typePos; // back to type
|
||||
it = typePos; // back to type
|
||||
if (result == RESULT_OK) {
|
||||
result = RESULT_ERR_NOTFOUND; // type not found
|
||||
result = RESULT_ERR_NOTFOUND; // type not found
|
||||
}
|
||||
}
|
||||
} else if (!constantValue.empty()) {
|
||||
it = typePos; // back to type
|
||||
result = RESULT_ERR_INVALID_ARG; // invalid value list
|
||||
} else { // template[:name]
|
||||
it = typePos; // back to type
|
||||
result = RESULT_ERR_INVALID_ARG; // invalid value list
|
||||
} else { // template[:name]
|
||||
string fieldName;
|
||||
bool lastType = stream.eof();
|
||||
if (pos != string::npos) { // replacement name specified
|
||||
if (pos != string::npos) { // replacement name specified
|
||||
fieldName = token.substr(pos+1);
|
||||
} else {
|
||||
fieldName = (firstType && lastType) ? name : "";
|
||||
}
|
||||
result = templ->derive(fieldName, firstType ? comment : "", firstType ? unit : "", partType, divisor, values, fields);
|
||||
result = templ->derive(fieldName, firstType ? comment : "", firstType ? unit : "", partType, divisor, values,
|
||||
fields);
|
||||
if (result != RESULT_OK) {
|
||||
it = typePos; // back to type
|
||||
it = typePos; // back to type
|
||||
}
|
||||
}
|
||||
firstType = false;
|
||||
@@ -236,7 +238,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
|
||||
if (result != RESULT_OK) {
|
||||
while (!fields.empty()) { // cleanup already created fields
|
||||
while (!fields.empty()) { // cleanup already created fields
|
||||
delete fields.back();
|
||||
fields.pop_back();
|
||||
}
|
||||
@@ -276,19 +278,19 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
// check length
|
||||
if ((bitCount % 8) != 0) {
|
||||
if (length == 0) {
|
||||
bitCount = 1; // default bit count: 1 bit
|
||||
bitCount = 1; // default bit count: 1 bit
|
||||
} else if (length <= bitCount) {
|
||||
bitCount = length;
|
||||
} else {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||
}
|
||||
byteCount = (unsigned char)((bitCount + 7) / 8);
|
||||
} else if (length == 0) {
|
||||
byteCount = 1; //default byte count: 1 byte
|
||||
byteCount = 1; //default byte count: 1 byte
|
||||
} else if (length <= byteCount || length == REMAIN_LEN) {
|
||||
byteCount = length;
|
||||
} else {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||
}
|
||||
}
|
||||
if (!constantValue.empty()) {
|
||||
@@ -316,14 +318,14 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (divisor != 0 || !values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field
|
||||
}
|
||||
returnField = new SingleDataField(name, comment, unit, dataType, partType, byteCount);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void SingleDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData) {
|
||||
@@ -346,10 +348,10 @@ result_t SingleDataField::read(const PartType partType,
|
||||
}
|
||||
switch (m_partType) {
|
||||
case pt_masterData:
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
break;
|
||||
case pt_slaveData:
|
||||
offset++; // skip NN
|
||||
offset++; // skip NN
|
||||
break;
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
@@ -373,10 +375,10 @@ result_t SingleDataField::read(const PartType partType,
|
||||
}
|
||||
switch (m_partType) {
|
||||
case pt_masterData:
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
break;
|
||||
case pt_slaveData:
|
||||
offset++; // skip NN
|
||||
offset++; // skip NN
|
||||
break;
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
@@ -394,7 +396,8 @@ result_t SingleDataField::read(const PartType partType,
|
||||
output << ",";
|
||||
}
|
||||
if (outputIndex >= 0 || m_name.empty() || !(outputFormat & OF_NAMES)) {
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\": {\"name\": \"" << m_name << "\"" << ", \"value\": ";
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\": {\"name\": \""
|
||||
<< m_name << "\"" << ", \"value\": ";
|
||||
} else {
|
||||
output << "\n \"" << m_name << "\": {\"value\": ";
|
||||
}
|
||||
@@ -439,10 +442,10 @@ result_t SingleDataField::write(istringstream& input,
|
||||
}
|
||||
switch (m_partType) {
|
||||
case pt_masterData:
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN
|
||||
break;
|
||||
case pt_slaveData:
|
||||
offset++; // skip NN
|
||||
offset++; // skip NN
|
||||
break;
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
@@ -471,11 +474,11 @@ result_t SingleDataField::derive(string name, string comment,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
}
|
||||
bool numeric = m_dataType->isNumeric();
|
||||
if (!numeric && (divisor != 0 || !values.empty())) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for non-numeric field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for non-numeric field
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
@@ -498,7 +501,8 @@ result_t SingleDataField::derive(string name, string comment,
|
||||
if (values.empty()) {
|
||||
fields.push_back(new SingleDataField(name, comment, unit, dataType, partType, m_length));
|
||||
} else if (numeric) {
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(dataType), partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(dataType),
|
||||
partType, m_length, values));
|
||||
} else {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -537,7 +541,7 @@ result_t ValueListDataField::derive(string name, string comment,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
@@ -549,7 +553,7 @@ result_t ValueListDataField::derive(string name, string comment,
|
||||
unit = m_unit;
|
||||
}
|
||||
if (divisor != 0 && divisor != 1) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
}
|
||||
if (!m_dataType->isNumeric()) {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
@@ -557,17 +561,18 @@ result_t ValueListDataField::derive(string name, string comment,
|
||||
if (!values.empty()) {
|
||||
NumberDataType* num = reinterpret_cast<NumberDataType*>(m_dataType);
|
||||
if (values.begin()->first < num->getMinValue() || values.rbegin()->first > num->getMaxValue()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
}
|
||||
} else {
|
||||
values = m_values;
|
||||
}
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(m_dataType), partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(m_dataType),
|
||||
partType, m_length, values));
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ValueListDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData) {
|
||||
@@ -576,14 +581,14 @@ void ValueListDataField::dump(ostream& output) {
|
||||
output << "s";
|
||||
}
|
||||
output << FIELD_SEPARATOR;
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) {
|
||||
if (it != m_values.begin()) {
|
||||
output << VALUE_SEPARATOR;
|
||||
}
|
||||
output << static_cast<unsigned>(it->first) << "=" << it->second;
|
||||
}
|
||||
} // else: impossible since divisor is not allowed for ValueListDataField
|
||||
} // else: impossible since divisor is not allowed for ValueListDataField
|
||||
dumpString(output, m_unit);
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
@@ -624,7 +629,8 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
NumberDataType* numType = reinterpret_cast<NumberDataType*>(m_dataType);
|
||||
if (isIgnored()) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
// replacement value
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength);
|
||||
}
|
||||
const char* str = input.str().c_str();
|
||||
|
||||
@@ -634,18 +640,19 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
}
|
||||
}
|
||||
if (strcasecmp(str, NULL_VALUE) == 0) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
// replacement value
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength);
|
||||
}
|
||||
char* strEnd = NULL; // fall back to raw value in input
|
||||
char* strEnd = NULL; // fall back to raw value in input
|
||||
unsigned int value;
|
||||
value = (unsigned int)strtoul(str, &strEnd, 10);
|
||||
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (m_values.find(value) != m_values.end()) {
|
||||
return numType->writeRawValue(value, offset, m_length, output, usedLength);
|
||||
}
|
||||
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||
}
|
||||
|
||||
|
||||
@@ -658,7 +665,7 @@ result_t ConstantDataField::derive(string name, string comment,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (m_partType != pt_any && partType == pt_any) {
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
}
|
||||
if (name.empty()) {
|
||||
name = m_name;
|
||||
@@ -670,17 +677,17 @@ result_t ConstantDataField::derive(string name, string comment,
|
||||
unit = m_unit;
|
||||
}
|
||||
if (divisor != 0) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field
|
||||
}
|
||||
if (!values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field
|
||||
}
|
||||
fields.push_back(new ConstantDataField(name, comment, unit, m_dataType, partType, m_length, m_value, m_verify));
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ConstantDataField::dump(ostream& output) {
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData) {
|
||||
@@ -689,9 +696,9 @@ void ConstantDataField::dump(ostream& output) {
|
||||
output << "s";
|
||||
}
|
||||
output << FIELD_SEPARATOR;
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
output << (m_verify?"==":"=") << m_value;
|
||||
} // else: impossible since divisor is not allowed for ConstantDataField
|
||||
} // else: impossible since divisor is not allowed for ConstantDataField
|
||||
dumpString(output, m_unit);
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
@@ -825,7 +832,7 @@ result_t DataFieldSet::derive(string name, string comment,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields) {
|
||||
if (!values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
|
||||
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
|
||||
}
|
||||
bool first = true;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
@@ -919,7 +926,8 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
||||
offset--;
|
||||
}
|
||||
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator,
|
||||
fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1021,7 +1029,7 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace) {
|
||||
map<string, DataField*>::iterator it = m_fieldsByName.find(name);
|
||||
if (it != m_fieldsByName.end()) {
|
||||
if (!replace) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
}
|
||||
delete it->second;
|
||||
it->second = field;
|
||||
@@ -1033,8 +1041,8 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace) {
|
||||
}
|
||||
|
||||
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) {
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) {
|
||||
vector<string>::iterator restart = begin;
|
||||
DataField* field = NULL;
|
||||
string name;
|
||||
@@ -1051,7 +1059,7 @@ result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const
|
||||
}
|
||||
result = add(field, name, true);
|
||||
if (result == RESULT_ERR_DUPLICATE_NAME) {
|
||||
begin = restart+1; // mark name as invalid
|
||||
begin = restart+1; // mark name as invalid
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
delete field;
|
||||
@@ -1067,4 +1075,4 @@ DataField* DataFieldTemplates::get(const string name) {
|
||||
return ref->second;
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
+30
-20
@@ -55,7 +55,7 @@ class SingleDataField;
|
||||
* Base class for all kinds of data fields.
|
||||
*/
|
||||
class DataField {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param name the field name.
|
||||
@@ -205,7 +205,7 @@ class DataField {
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** the field name. */
|
||||
const string m_name;
|
||||
|
||||
@@ -218,7 +218,7 @@ class DataField {
|
||||
* A single @a DataField holding a value.
|
||||
*/
|
||||
class SingleDataField : public DataField {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param name the field name.
|
||||
@@ -322,7 +322,7 @@ class SingleDataField : public DataField {
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* Internal method for reading the field from a @a SymbolString.
|
||||
* @param input the unescaped @a SymbolString to read the binary value from.
|
||||
@@ -367,7 +367,7 @@ class SingleDataField : public DataField {
|
||||
* A numeric data field with a list of value=text assignments and a string representation.
|
||||
*/
|
||||
class ValueListDataField : public SingleDataField {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param name the field name.
|
||||
@@ -402,7 +402,7 @@ class ValueListDataField : public SingleDataField {
|
||||
virtual void dump(ostream& output);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
@@ -414,7 +414,7 @@ class ValueListDataField : public SingleDataField {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the value=text assignments. */
|
||||
map<unsigned int, string> m_values;
|
||||
};
|
||||
@@ -424,7 +424,7 @@ class ValueListDataField : public SingleDataField {
|
||||
* A data field with a constant value.
|
||||
*/
|
||||
class ConstantDataField : public SingleDataField {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param name the field name.
|
||||
@@ -460,7 +460,7 @@ class ConstantDataField : public SingleDataField {
|
||||
virtual void dump(ostream& output);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
@@ -472,7 +472,7 @@ class ConstantDataField : public SingleDataField {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the constant value. */
|
||||
const string m_value;
|
||||
|
||||
@@ -485,7 +485,7 @@ class ConstantDataField : public SingleDataField {
|
||||
* A set of @a DataField instances.
|
||||
*/
|
||||
class DataFieldSet : public DataField {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Get the @a DataFieldSet for parsing the identification message (service 0x07 0x04).
|
||||
* @return the @a DataFieldSet for parsing the identification message. This is:<ul>
|
||||
@@ -550,14 +550,24 @@ class DataFieldSet : public DataField {
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
SingleDataField* operator[](const size_t index) {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_fields[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @a SingleDataField at the specified index.
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
const SingleDataField* operator[](const size_t index) const {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_fields[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of @a SingleDataFields instances in this set.
|
||||
@@ -588,7 +598,7 @@ class DataFieldSet : public DataField {
|
||||
unsigned char offset, char separator = UI_FIELD_SEPARATOR, unsigned char* length = NULL);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the @a DataFieldSet containing the ident message @a SingleDataField instances, or NULL. */
|
||||
static DataFieldSet* s_identFields;
|
||||
|
||||
@@ -604,7 +614,7 @@ class DataFieldSet : public DataField {
|
||||
* A map of template @a DataField instances.
|
||||
*/
|
||||
class DataFieldTemplates : public FileReader {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*/
|
||||
@@ -640,8 +650,8 @@ class DataFieldTemplates : public FileReader {
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo);
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo);
|
||||
|
||||
/**
|
||||
* Gets the template @a DataField instance with the specified name.
|
||||
@@ -652,11 +662,11 @@ class DataFieldTemplates : public FileReader {
|
||||
DataField* get(string name);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the known template @a DataField instances by name. */
|
||||
map<string, DataField*> m_fieldsByName;
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_DATA_H_
|
||||
#endif // LIB_EBUS_DATA_H_
|
||||
|
||||
+198
-153
@@ -40,18 +40,19 @@ using std::setfill;
|
||||
using std::setprecision;
|
||||
using std::setw;
|
||||
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length) {
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
unsigned long ret = strtoul(str, &strEnd, base);
|
||||
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (minValue > ret || ret > maxValue) {
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
return 0;
|
||||
}
|
||||
if (length != NULL) {
|
||||
@@ -61,18 +62,19 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
return (unsigned int)ret;
|
||||
}
|
||||
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length) {
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
unsigned int* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
long ret = strtol(str, &strEnd, base);
|
||||
|
||||
if (strEnd == NULL || *strEnd != 0) {
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (minValue > ret || ret > maxValue) {
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
return 0;
|
||||
}
|
||||
if (length != NULL) {
|
||||
@@ -82,11 +84,14 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
|
||||
if (pos > begin) {
|
||||
pos--;
|
||||
}
|
||||
out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo) << " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl;
|
||||
out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo)
|
||||
<< " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": "
|
||||
<< getResultCode(result) << endl;
|
||||
out << "Erroneous item is here:" << endl;
|
||||
bool first = true;
|
||||
int cnt = 0;
|
||||
@@ -161,7 +166,7 @@ result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
} else if (baseOffset + count > input.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -187,7 +192,7 @@ result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
ch = '?';
|
||||
} else if (outputFormat & OF_JSON) {
|
||||
if (ch == '"' || ch == '\\') {
|
||||
output << '\\'; // escape
|
||||
output << '\\'; // escape
|
||||
}
|
||||
}
|
||||
output << static_cast<char>(ch);
|
||||
@@ -209,7 +214,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
unsigned int value = 0;
|
||||
string token;
|
||||
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -218,7 +223,7 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
count = 1;
|
||||
}
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)count;
|
||||
@@ -232,21 +237,21 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
while (!input.eof() && input.peek() == ' ') {
|
||||
input.get();
|
||||
}
|
||||
if (input.eof()) { // no more digits
|
||||
value = m_replacement; // fill up with replacement
|
||||
if (input.eof()) { // no more digits
|
||||
value = m_replacement; // fill up with replacement
|
||||
} else {
|
||||
token.clear();
|
||||
token.push_back((unsigned char)input.get());
|
||||
if (input.eof()) {
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
}
|
||||
token.push_back((unsigned char)input.get());
|
||||
if (input.eof()) {
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||
}
|
||||
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid hex value
|
||||
return result; // invalid hex value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -267,13 +272,13 @@ result_t StringDataType::writeSymbols(istringstream& input,
|
||||
break;
|
||||
}
|
||||
if (value > 0xff) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
output[baseOffset + offset] = (unsigned char)value;
|
||||
}
|
||||
|
||||
if (!remainder && i < count) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)((offset-start)*incr);
|
||||
@@ -298,7 +303,7 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
} else if (baseOffset + count > input.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -309,34 +314,34 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
int type = (m_hasDate?2:0) | (m_hasTime?1:0);
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
if (length == 4 && i == 2 && m_hasDate) {
|
||||
continue; // skip weekday in between
|
||||
continue; // skip weekday in between
|
||||
}
|
||||
ch = input[baseOffset + offset];
|
||||
if (hasFlag(BCD) && (hasFlag(REQ) || ch != m_replacement)) {
|
||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
}
|
||||
ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f));
|
||||
}
|
||||
switch (type) {
|
||||
case 2: // date only
|
||||
case 2: // date only
|
||||
if (!hasFlag(REQ) && ch == m_replacement) {
|
||||
if (i + 1 != length) {
|
||||
output << NULL_VALUE << ".";
|
||||
break;
|
||||
} else if (last == m_replacement) {
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
output << NULL_VALUE << ".";
|
||||
}
|
||||
output << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
if (i == 0) {
|
||||
break;
|
||||
}
|
||||
int mjd = last + ch*256 + 15020; // 01.01.1900
|
||||
int mjd = last + ch*256 + 15020; // 01.01.1900
|
||||
int y = static_cast<int>((mjd-15078.2)/365.25);
|
||||
int m = static_cast<int>((mjd-14956.1-static_cast<int>(y*365.25))/30.6001);
|
||||
int d = mjd-14956-static_cast<int>(y*365.25)-static_cast<int>(m*30.6001);
|
||||
@@ -352,15 +357,15 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
if (i + 1 == length) {
|
||||
output << (2000 + ch);
|
||||
} else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12)) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid date
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid date
|
||||
} else {
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(ch) << ".";
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // time only
|
||||
case 1: // time only
|
||||
if (!hasFlag(REQ) && ch == m_replacement) {
|
||||
if (length == 1) { // truncated time
|
||||
if (length == 1) { // truncated time
|
||||
output << NULL_VALUE << ":" << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
@@ -370,37 +375,37 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
output << NULL_VALUE;
|
||||
break;
|
||||
}
|
||||
if (hasFlag(SPE)) { // minutes since midnight
|
||||
if (hasFlag(SPE)) { // minutes since midnight
|
||||
if (i == 0) {
|
||||
last = ch;
|
||||
continue;
|
||||
}
|
||||
int minutes = ch*256 + last;
|
||||
if (minutes > 24*60) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||
}
|
||||
int hour = minutes / 60;
|
||||
if (hour > 24) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
}
|
||||
output << setw(2) << dec << setfill('0') << static_cast<unsigned>(hour);
|
||||
ch = (unsigned char)(minutes % 60);
|
||||
} else if (length == 1) { // truncated time
|
||||
} else if (length == 1) { // truncated time
|
||||
if (i == 0) {
|
||||
ch = (unsigned char)(ch/(60/m_resolution)); // convert to hours
|
||||
offset -= incr; // repeat for minutes
|
||||
ch = (unsigned char)(ch/(60/m_resolution)); // convert to hours
|
||||
offset -= incr; // repeat for minutes
|
||||
count++;
|
||||
} else {
|
||||
ch = (unsigned char)((ch % (60/m_resolution)) * m_resolution); // convert to minutes
|
||||
ch = (unsigned char)((ch % (60/m_resolution)) * m_resolution); // convert to minutes
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
if (ch > 24) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid hour
|
||||
}
|
||||
hour = ch;
|
||||
} else if (ch > 59 || (hour == 24 && ch > 0)) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
}
|
||||
if (i > 0) {
|
||||
output << ":";
|
||||
@@ -425,7 +430,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
unsigned int value = 0, last = 0, lastLast = 0;
|
||||
string token;
|
||||
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -434,7 +439,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
count = 1;
|
||||
}
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
output[baseOffset + offset] = (unsigned char)m_replacement; // fill up with replacement
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)count;
|
||||
@@ -448,12 +453,12 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
for (offset = start; i < count; offset += skip ? 0 : incr, i++) {
|
||||
skip = false;
|
||||
switch (type) {
|
||||
case 2: // date only
|
||||
case 2: // date only
|
||||
if (length == 4 && i == 2) {
|
||||
continue; // skip weekday in between
|
||||
continue; // skip weekday in between
|
||||
}
|
||||
if (input.eof() || !getline(input, token, '.')) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
|
||||
value = m_replacement;
|
||||
@@ -461,9 +466,9 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
value = parseInt(token.c_str(), 10, 0, 2099, result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid date part
|
||||
return result; // invalid date part
|
||||
}
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
if (length == 2) { // number of days since 01.01.1900
|
||||
skip = true;
|
||||
if (i == 0) {
|
||||
count++;
|
||||
@@ -471,7 +476,7 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
int y = (value < 100 ? value + 2000 : value) - 1900;
|
||||
int l = last <= 2 ? 1 : 0;
|
||||
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
|
||||
value = mjd - 15020; // 01.01.1900
|
||||
value = mjd - 15020; // 01.01.1900
|
||||
output[baseOffset + offset] = (unsigned char)(value&0xff);
|
||||
value >>= 8;
|
||||
offset += incr;
|
||||
@@ -485,67 +490,68 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
int y = (value < 100 ? value + 2000 : value) - 1900;
|
||||
int l = last <= 2 ? 1 : 0;
|
||||
int mjd = 14956 + lastLast + static_cast<int>((y-l)*365.25) + static_cast<int>((last+1+l*12)*30.6001);
|
||||
int daysSinceSunday = (mjd+3) % 7; // Sun=0
|
||||
int daysSinceSunday = (mjd+3) % 7; // Sun=0
|
||||
if (hasFlag(BCD)) {
|
||||
output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
} else {
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday == 0 ? 7 : daysSinceSunday); // Sun=0x07
|
||||
// Sun=0x07
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
|
||||
}
|
||||
}
|
||||
if (value >= 2000) {
|
||||
value -= 2000;
|
||||
}
|
||||
if (value > 99) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid year
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid year
|
||||
}
|
||||
} else if (value < 1 || (i == 0 && value > 31) || (i == 1 && value > 12)) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid date part
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid date part
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // time only
|
||||
case 1: // time only
|
||||
if (input.eof() || !getline(input, token, LENGTH_SEPARATOR)) {
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
return RESULT_ERR_EOF; // incomplete
|
||||
}
|
||||
if (!hasFlag(REQ) && strcmp(token.c_str(), NULL_VALUE) == 0) {
|
||||
value = m_replacement;
|
||||
if (length == 1) { // truncated time
|
||||
if (length == 1) { // truncated time
|
||||
if (i == 0) {
|
||||
skip = true; // repeat for minutes
|
||||
skip = true; // repeat for minutes
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
if (last != m_replacement) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid truncated time minutes
|
||||
return RESULT_ERR_INVALID_NUM; // invalid truncated time minutes
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
value = parseInt(token.c_str(), 10, 0, 59, result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid time part
|
||||
return result; // invalid time part
|
||||
}
|
||||
if ((i == 0 && value > 24) || (i > 0 && (last == 24 && value > 0) )) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time part
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time part
|
||||
}
|
||||
if (hasFlag(SPE)) { // minutes since midnight
|
||||
if (hasFlag(SPE)) { // minutes since midnight
|
||||
if (i == 0) {
|
||||
skip = true; // repeat for minutes
|
||||
skip = true; // repeat for minutes
|
||||
break;
|
||||
}
|
||||
value += last*60;
|
||||
output[baseOffset + offset] = (unsigned char)(value&0xff);
|
||||
value >>= 8;
|
||||
offset += incr;
|
||||
} else if (length == 1) { // truncated time
|
||||
} else if (length == 1) { // truncated time
|
||||
if (i == 0) {
|
||||
skip = true; // repeat for minutes
|
||||
skip = true; // repeat for minutes
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
value = (last * 60 + value + m_resolution/2)/m_resolution;
|
||||
if (value > 24 * 6) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -555,19 +561,19 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (!skip) {
|
||||
if (hasFlag(BCD) && (hasFlag(REQ) || value != m_replacement)) {
|
||||
if (value > 99) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
}
|
||||
value = ((value / 10) << 4) | (value % 10);
|
||||
}
|
||||
if (value > 0xff) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
output[baseOffset + offset] = (unsigned char)value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!remainder && i < count) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
}
|
||||
if (usedLength != NULL) {
|
||||
*usedLength = (unsigned char)((offset-start)*incr);
|
||||
@@ -667,9 +673,9 @@ result_t NumberDataType::readRawValue(SymbolString& input,
|
||||
unsigned char ch;
|
||||
|
||||
if (baseOffset + length > input.size()) {
|
||||
return RESULT_ERR_INVALID_POS; // not enough data available
|
||||
return RESULT_ERR_INVALID_POS; // not enough data available
|
||||
}
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -685,11 +691,11 @@ result_t NumberDataType::readRawValue(SymbolString& input,
|
||||
}
|
||||
if (!hasFlag(HCD)) {
|
||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||
}
|
||||
ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f));
|
||||
} else if (ch > 0x63) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
|
||||
}
|
||||
value += ch * exp;
|
||||
exp *= 100;
|
||||
@@ -717,7 +723,7 @@ result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
output << setw(0) << dec; // initialize output
|
||||
output << setw(0) << dec; // initialize output
|
||||
|
||||
if (!hasFlag(REQ) && value == m_replacement) {
|
||||
if (outputFormat & OF_JSON) {
|
||||
@@ -739,7 +745,7 @@ result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
unsigned char* pval = (unsigned char*)&value;
|
||||
val = *reinterpret_cast<float*>(pval);
|
||||
#else
|
||||
int exp = (value >> 23) & 0xff; // 8 bits, signed
|
||||
int exp = (value >> 23) & 0xff; // 8 bits, signed
|
||||
if (exp == 0) {
|
||||
val = 0.0;
|
||||
} else {
|
||||
@@ -777,8 +783,8 @@ result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
signedValue = static_cast<int>(value); // negative signed value
|
||||
} else if (negative) { // negative signed value
|
||||
signedValue = static_cast<int>(value); // negative signed value
|
||||
} else if (negative) { // negative signed value
|
||||
signedValue = static_cast<int>(value) - (1 << m_bitCount);
|
||||
} else {
|
||||
signedValue = static_cast<int>(value);
|
||||
@@ -819,7 +825,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
|
||||
value <<= m_firstBit;
|
||||
}
|
||||
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
if (hasFlag(REV)) { // reverted binary representation (most significant byte first)
|
||||
start = length - 1;
|
||||
incr = -1;
|
||||
}
|
||||
@@ -858,14 +864,14 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
if (!hasFlag(REQ) && (isIgnored() || strcasecmp(str, NULL_VALUE) == 0)) {
|
||||
value = m_replacement; // replacement value
|
||||
value = m_replacement; // replacement value
|
||||
} else if (str == NULL || *str == 0) {
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
} else if (hasFlag(EXP)) { // IEEE 754 binary32
|
||||
return RESULT_ERR_EOF; // input too short
|
||||
} else if (hasFlag(EXP)) { // IEEE 754 binary32
|
||||
char* strEnd = NULL;
|
||||
double dvalue = strtod(str, &strEnd);
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (m_divisor < 0) {
|
||||
dvalue /= -m_divisor;
|
||||
@@ -888,7 +894,7 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
int exp = ilogb(dvalue);
|
||||
if (exp < -126 || exp > 127) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
dvalue = scalbln(dvalue, -exp) - 1.0;
|
||||
unsigned int sig = (unsigned int)(dvalue * exp2(23));
|
||||
@@ -913,13 +919,13 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
value = (unsigned int)strtoul(str, &strEnd, 10);
|
||||
}
|
||||
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
} else {
|
||||
char* strEnd = NULL;
|
||||
double dvalue = strtod(str, &strEnd);
|
||||
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
if (m_divisor < 0) {
|
||||
dvalue = round(dvalue / -m_divisor);
|
||||
@@ -928,7 +934,7 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
if (hasFlag(SIG)) {
|
||||
if (dvalue < -(1LL << (8 * length)) || dvalue >= (1LL << (8 * length))) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
if (dvalue < 0 && m_bitCount != 32) {
|
||||
value = static_cast<int>(dvalue + (1 << m_bitCount));
|
||||
@@ -937,22 +943,22 @@ result_t NumberDataType::writeSymbols(istringstream& input,
|
||||
}
|
||||
} else {
|
||||
if (dvalue < 0.0 || dvalue >= (1LL << (8 * length))) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
value = (unsigned int)dvalue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFlag(SIG)) { // signed value
|
||||
if ((value & (1 << (m_bitCount - 1))) != 0) { // negative signed value
|
||||
if (hasFlag(SIG)) { // signed value
|
||||
if ((value & (1 << (m_bitCount - 1))) != 0) { // negative signed value
|
||||
if (value < m_minValue) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
} else if (value > m_maxValue) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
} else if (value < m_minValue || value > m_maxValue) {
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,66 +974,105 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
|
||||
|
||||
|
||||
DataTypeList::DataTypeList() {
|
||||
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
|
||||
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); // unsigned decimal in BCD, 0000 - 9999 (fixed length)
|
||||
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
|
||||
add(new StringDataType("IGN", MAX_LEN*8, IGN|ADJ, 0)); // >= 1 byte ignored data
|
||||
add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0)); // >= 1 byte character string filled up with 0x00 (null terminated string)
|
||||
add(new StringDataType("HEX", MAX_LEN*8, ADJ, 0, true)); // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
|
||||
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0)); // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday Mon=0x00 - Sun=0x06, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 24, BCD, 0xff, true, false, 0)); // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0)); // date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63, WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 24, 0, 0xff, true, false, 0)); // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
|
||||
add(new DateTimeDataType("DAY", 16, 0, 0xff, true, false, 0)); // date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
|
||||
add(new DateTimeDataType("BTI", 24, BCD|REV, 0xff, false, true, 0)); // time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23)
|
||||
add(new DateTimeDataType("HTI", 24, 0, 0xff, false, true, 0)); // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b)
|
||||
add(new DateTimeDataType("VTI", 24, REV, 0x63, false, true, 0)); // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x3b,0x3b,0x17, replacement 0x63) [Vaillant type]
|
||||
add(new DateTimeDataType("BTM", 16, BCD|REV, 0xff, false, true, 0)); // time as hh:mm in BCD, 00:00 - 23:59 (0x00,0x00 - 0x59,0x23, replacement 0xff)
|
||||
add(new DateTimeDataType("HTM", 16, 0, 0xff, false, true, 0)); // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b)
|
||||
add(new DateTimeDataType("VTM", 16, REV, 0xff, false, true, 0)); // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x3b,0x17, replacement 0xff) [Vaillant type]
|
||||
add(new DateTimeDataType("MIN", 16, SPE, 0xff, false, true, 0)); // time, minutes since last midnight, 00:00 - 24:00 (minutes + hour * 60 as integer)
|
||||
add(new DateTimeDataType("TTM", 8, 0, 0x90, false, true, 10)); // truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer)
|
||||
add(new DateTimeDataType("TTH", 8, 0, 0, false, true, 30)); // truncated time (only multiple of 30 minutes), 00:00 - 24:00 (minutes div 30 + hour * 2 as integer)
|
||||
add(new DateTimeDataType("TTQ", 8, 0, 0, false, true, 15)); // truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer)
|
||||
add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type]
|
||||
add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
|
||||
add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
|
||||
add(new NumberDataType("BCD", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999
|
||||
add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999
|
||||
add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999
|
||||
add(new NumberDataType("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999
|
||||
add(new NumberDataType("HCD", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99
|
||||
add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999
|
||||
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999
|
||||
add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2)); // unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
|
||||
add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256)); // signed number (fraction 1/256), -127.99 - +127.99
|
||||
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16)); // signed number (fraction 1/16), -2047.9 - +2047.9
|
||||
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, little endian
|
||||
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, big endian
|
||||
add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian
|
||||
add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian
|
||||
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, little endian
|
||||
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, big endian
|
||||
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, little endian
|
||||
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, big endian
|
||||
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, little endian
|
||||
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, big endian
|
||||
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, little endian
|
||||
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, big endian
|
||||
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, little endian
|
||||
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, big endian
|
||||
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, little endian
|
||||
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, big endian
|
||||
add(new NumberDataType("BI0", 7, ADJ|REQ, 0, 0, 1)); // bit 0 (up to 7 bits until bit 6)
|
||||
add(new NumberDataType("BI1", 7, ADJ|REQ, 0, 1, 1)); // bit 1 (up to 7 bits until bit 7)
|
||||
add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7)
|
||||
add(new NumberDataType("BI3", 5, ADJ|REQ, 0, 3, 1)); // bit 3 (up to 5 bits until bit 7)
|
||||
add(new NumberDataType("BI4", 4, ADJ|REQ, 0, 4, 1)); // bit 4 (up to 4 bits until bit 7)
|
||||
add(new NumberDataType("BI5", 3, ADJ|REQ, 0, 5, 1)); // bit 5 (up to 3 bits until bit 7)
|
||||
add(new NumberDataType("BI6", 2, ADJ|REQ, 0, 6, 1)); // bit 6 (up to 2 bits until bit 7)
|
||||
add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7
|
||||
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
|
||||
// unsigned decimal in BCD, 0000 - 9999 (fixed length)
|
||||
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1));
|
||||
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
|
||||
add(new StringDataType("IGN", MAX_LEN*8, IGN|ADJ, 0)); // >= 1 byte ignored data
|
||||
// >= 1 byte character string filled up with 0x00 (null terminated string)
|
||||
add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0));
|
||||
// >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
|
||||
add(new StringDataType("HEX", MAX_LEN*8, ADJ, 0, true));
|
||||
// date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99,
|
||||
// WW is weekday Mon=0x00 - Sun=0x06, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0));
|
||||
// date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 24, BCD, 0xff, true, false, 0));
|
||||
// date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63,
|
||||
// WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0));
|
||||
// date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 24, 0, 0xff, true, false, 0));
|
||||
// date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
|
||||
add(new DateTimeDataType("DAY", 16, 0, 0xff, true, false, 0));
|
||||
// time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23)
|
||||
add(new DateTimeDataType("BTI", 24, BCD|REV, 0xff, false, true, 0));
|
||||
// time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b)
|
||||
add(new DateTimeDataType("HTI", 24, 0, 0xff, false, true, 0));
|
||||
// time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x3b,0x3b,0x17, replacement 0x63) [Vaillant type]
|
||||
add(new DateTimeDataType("VTI", 24, REV, 0x63, false, true, 0));
|
||||
// time as hh:mm in BCD, 00:00 - 23:59 (0x00,0x00 - 0x59,0x23, replacement 0xff)
|
||||
add(new DateTimeDataType("BTM", 16, BCD|REV, 0xff, false, true, 0));
|
||||
// time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b)
|
||||
add(new DateTimeDataType("HTM", 16, 0, 0xff, false, true, 0));
|
||||
// time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x3b,0x17, replacement 0xff) [Vaillant type]
|
||||
add(new DateTimeDataType("VTM", 16, REV, 0xff, false, true, 0));
|
||||
// time, minutes since last midnight, 00:00 - 24:00 (minutes + hour * 60 as integer)
|
||||
add(new DateTimeDataType("MIN", 16, SPE, 0xff, false, true, 0));
|
||||
// truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer)
|
||||
add(new DateTimeDataType("TTM", 8, 0, 0x90, false, true, 10));
|
||||
// truncated time (only multiple of 30 minutes), 00:00 - 24:00 (minutes div 30 + hour * 2 as integer)
|
||||
add(new DateTimeDataType("TTH", 8, 0, 0, false, true, 30));
|
||||
// truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer)
|
||||
add(new DateTimeDataType("TTQ", 8, 0, 0, false, true, 15));
|
||||
add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type]
|
||||
add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
|
||||
add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
|
||||
add(new NumberDataType("BCD", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999
|
||||
add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999
|
||||
add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999
|
||||
add(new NumberDataType("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999
|
||||
add(new NumberDataType("HCD", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99
|
||||
add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999
|
||||
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999
|
||||
add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
// unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
|
||||
add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2));
|
||||
// signed number (fraction 1/256), -127.99 - +127.99
|
||||
add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256));
|
||||
// signed number (fraction 1/16), -2047.9 - +2047.9
|
||||
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16));
|
||||
// signed number (fraction 1/1000), -32.767 - +32.767, little endian
|
||||
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000));
|
||||
// signed number (fraction 1/1000), -32.767 - +32.767, big endian
|
||||
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000));
|
||||
// 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));
|
||||
// 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));
|
||||
// unsigned integer, 0 - 65534, little endian
|
||||
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1));
|
||||
// unsigned integer, 0 - 65534, big endian
|
||||
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1));
|
||||
// signed integer, -32767 - +32767, little endian
|
||||
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1));
|
||||
// signed integer, -32767 - +32767, big endian
|
||||
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1));
|
||||
// unsigned 3 bytes int, 0 - 16777214, little endian
|
||||
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1));
|
||||
// unsigned 3 bytes int, 0 - 16777214, big endian
|
||||
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1));
|
||||
// signed 3 bytes int, -8388607 - +8388607, little endian
|
||||
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1));
|
||||
// signed 3 bytes int, -8388607 - +8388607, big endian
|
||||
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1));
|
||||
// unsigned integer, 0 - 4294967294, little endian
|
||||
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1));
|
||||
// unsigned integer, 0 - 4294967294, big endian
|
||||
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1));
|
||||
// signed integer, -2147483647 - +2147483647, little endian
|
||||
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1));
|
||||
// signed integer, -2147483647 - +2147483647, big endian
|
||||
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1));
|
||||
add(new NumberDataType("BI0", 7, ADJ|REQ, 0, 0, 1)); // bit 0 (up to 7 bits until bit 6)
|
||||
add(new NumberDataType("BI1", 7, ADJ|REQ, 0, 1, 1)); // bit 1 (up to 7 bits until bit 7)
|
||||
add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7)
|
||||
add(new NumberDataType("BI3", 5, ADJ|REQ, 0, 3, 1)); // bit 3 (up to 5 bits until bit 7)
|
||||
add(new NumberDataType("BI4", 4, ADJ|REQ, 0, 4, 1)); // bit 4 (up to 4 bits until bit 7)
|
||||
add(new NumberDataType("BI5", 3, ADJ|REQ, 0, 5, 1)); // bit 5 (up to 3 bits until bit 7)
|
||||
add(new NumberDataType("BI6", 2, ADJ|REQ, 0, 6, 1)); // bit 6 (up to 2 bits until bit 7)
|
||||
add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7
|
||||
}
|
||||
|
||||
DataTypeList* DataTypeList::getInstance() {
|
||||
@@ -1050,15 +1095,15 @@ result_t DataTypeList::add(DataType* dataType) {
|
||||
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount);
|
||||
map<string, DataType*>::iterator it = m_typesByIdLength.find(str.str());
|
||||
if (it != m_typesByIdLength.end()) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
}
|
||||
m_typesByIdLength[str.str()] = dataType;
|
||||
if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
|
||||
m_cleanupTypes.push_back(dataType);
|
||||
return RESULT_OK; // only store first one as default
|
||||
return RESULT_OK; // only store first one as default
|
||||
}
|
||||
} else if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
}
|
||||
m_typesById[dataType->getId()] = dataType;
|
||||
m_cleanupTypes.push_back(dataType);
|
||||
@@ -1081,4 +1126,4 @@ DataType* DataTypeList::get(const string id, const unsigned char length) {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
+43
-34
@@ -83,7 +83,7 @@ typedef int OutputFormat;
|
||||
/* the bit flags for @a OutputFormat. */
|
||||
static const unsigned int OF_NAMES = 0x01; //!< include names.
|
||||
static const unsigned int OF_UNITS = 0x02; //!< include units.
|
||||
static const unsigned int OF_COMMENTS = 0x04; //!< include comments.
|
||||
static const unsigned int OF_COMMENTS = 0x04; //!< include comments.
|
||||
static const unsigned int OF_NUMERIC = 0x08; //!< numeric format (keep numeric value of value=name pairs).
|
||||
static const unsigned int OF_JSON = 0x10; //!< JSON format.
|
||||
|
||||
@@ -95,19 +95,20 @@ enum PartType {
|
||||
};
|
||||
|
||||
/* flags for @a DataType. */
|
||||
static const unsigned int ADJ = 0x01; //!< adjustable length, bitCount is maximum length
|
||||
static const unsigned int BCD = 0x02; //!< binary representation is BCD
|
||||
static const unsigned int REV = 0x04; //!< reverted binary representation (most significant byte first)
|
||||
static const unsigned int SIG = 0x08; //!< signed value
|
||||
static const unsigned int IGN = 0x10; //!< ignore value during read and write
|
||||
static const unsigned int FIX = 0x20; //!< fixed width formatting
|
||||
static const unsigned int REQ = 0x40; //!< value may not be NULL
|
||||
static const unsigned int HCD = 0x80; //!< binary representation is hex converted to decimal and interpreted as 2 digits (also requires #BCD)
|
||||
static const unsigned int EXP = 0x100; //!< exponential numeric representation
|
||||
static const unsigned int DAY = 0x200; //!< forced value list defaulting to week days
|
||||
static const unsigned int NUM = 0x400; //!< numeric type with base class @a NumberDataType
|
||||
static const unsigned int SPE = 0x800; //!< special marker for certain types
|
||||
static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
static const unsigned int ADJ = 0x01; //!< adjustable length, bitCount is maximum length
|
||||
static const unsigned int BCD = 0x02; //!< binary representation is BCD
|
||||
static const unsigned int REV = 0x04; //!< reverted binary representation (most significant byte first)
|
||||
static const unsigned int SIG = 0x08; //!< signed value
|
||||
static const unsigned int IGN = 0x10; //!< ignore value during read and write
|
||||
static const unsigned int FIX = 0x20; //!< fixed width formatting
|
||||
static const unsigned int REQ = 0x40; //!< value may not be NULL
|
||||
/** binary representation is hex converted to decimal and interpreted as 2 digits (also requires #BCD). */
|
||||
static const unsigned int HCD = 0x80;
|
||||
static const unsigned int EXP = 0x100; //!< exponential numeric representation
|
||||
static const unsigned int DAY = 0x200; //!< forced value list defaulting to week days
|
||||
static const unsigned int NUM = 0x400; //!< numeric type with base class @a NumberDataType
|
||||
static const unsigned int SPE = 0x800; //!< special marker for certain types
|
||||
static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
|
||||
|
||||
/**
|
||||
@@ -120,7 +121,8 @@ static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Parse a signed int value.
|
||||
@@ -132,7 +134,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Print the error position of the iterator.
|
||||
@@ -144,20 +147,22 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
||||
* @param lineNo the current line number in the file being read.
|
||||
* @param result the result code.
|
||||
*/
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
|
||||
|
||||
/**
|
||||
* Base class for all kinds of data types.
|
||||
*/
|
||||
class DataType {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param id the type identifier.
|
||||
* @param bitCount the number of bits (maximum length if #ADJ flag is set, must be multiple of 8 with flag #BCD).
|
||||
* @param flags the combination of flags (like #BCD).
|
||||
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue).
|
||||
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue).
|
||||
*/
|
||||
DataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement)
|
||||
: m_id(id), m_bitCount(bitCount), m_flags(flags), m_replacement(replacement) {}
|
||||
@@ -200,7 +205,8 @@ class DataType {
|
||||
bool isNumeric() const { return hasFlag(NUM); }
|
||||
|
||||
/**
|
||||
* @return the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue).
|
||||
* @return the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue).
|
||||
*/
|
||||
unsigned int getReplacement() const { return m_replacement; }
|
||||
|
||||
@@ -254,7 +260,7 @@ class DataType {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** the type identifier. */
|
||||
const string m_id;
|
||||
|
||||
@@ -264,7 +270,8 @@ class DataType {
|
||||
/** the combination of flags (like #BCD). */
|
||||
const uint16_t m_flags;
|
||||
|
||||
/** the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue). */
|
||||
/** the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue). */
|
||||
const unsigned int m_replacement;
|
||||
};
|
||||
|
||||
@@ -273,7 +280,7 @@ class DataType {
|
||||
* A string based @a DataType.
|
||||
*/
|
||||
class StringDataType : public DataType {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param id the type identifier.
|
||||
@@ -307,7 +314,7 @@ class StringDataType : public DataType {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** true for hex digits instead of characters. */
|
||||
const bool m_isHex;
|
||||
};
|
||||
@@ -317,7 +324,7 @@ class StringDataType : public DataType {
|
||||
* A date/time based @a DataType.
|
||||
*/
|
||||
class DateTimeDataType : public DataType {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param id the type identifier.
|
||||
@@ -368,7 +375,7 @@ class DateTimeDataType : public DataType {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** true if date part is present. */
|
||||
const bool m_hasDate;
|
||||
|
||||
@@ -384,7 +391,7 @@ class DateTimeDataType : public DataType {
|
||||
* A number based @a DataType.
|
||||
*/
|
||||
class NumberDataType : public DataType {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance for multiple of 8 bits.
|
||||
* @param id the type identifier.
|
||||
@@ -397,7 +404,8 @@ class NumberDataType : public DataType {
|
||||
*/
|
||||
NumberDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const unsigned int minValue, const unsigned int maxValue, const int 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) {}
|
||||
: 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) {}
|
||||
|
||||
/**
|
||||
* Constructs a new instance for less than 8 bits.
|
||||
@@ -410,7 +418,8 @@ class NumberDataType : public DataType {
|
||||
*/
|
||||
NumberDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const int16_t firstBit, const int 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) {}
|
||||
: 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) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -495,7 +504,7 @@ class NumberDataType : public DataType {
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the minimum raw value. */
|
||||
const unsigned int m_minValue;
|
||||
|
||||
@@ -520,7 +529,7 @@ class NumberDataType : public DataType {
|
||||
* A map of base @a DataType instances.
|
||||
*/
|
||||
class DataTypeList {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructs a new instance and registers the known base data types.
|
||||
*/
|
||||
@@ -568,7 +577,7 @@ class DataTypeList {
|
||||
DataType* get(const string id, const unsigned char length = 0);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the known @a DataType instances by ID only. */
|
||||
map<string, DataType*> m_typesById;
|
||||
|
||||
@@ -588,6 +597,6 @@ class DataTypeList {
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_DATATYPE_H_
|
||||
#endif // LIB_EBUS_DATATYPE_H_
|
||||
|
||||
@@ -54,13 +54,13 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
|
||||
}
|
||||
if (portpos == NULL) {
|
||||
free(in);
|
||||
return NULL; // invalid protocol or missing port
|
||||
return NULL; // invalid protocol or missing port
|
||||
}
|
||||
result_t result = RESULT_OK;
|
||||
unsigned int port = parseInt(portpos+1, 10, 1, 65535, result);
|
||||
if (result != RESULT_OK) {
|
||||
free(in);
|
||||
return NULL; // invalid port
|
||||
return NULL; // invalid port
|
||||
}
|
||||
struct sockaddr_in address;
|
||||
memset(reinterpret_cast<char*>(&address), 0, sizeof(address));
|
||||
@@ -69,7 +69,7 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
|
||||
struct hostent* h = gethostbyname(addrpos);
|
||||
if (h == NULL) {
|
||||
free(in);
|
||||
return NULL; // invalid host
|
||||
return NULL; // invalid host
|
||||
}
|
||||
memcpy(&address.sin_addr, h->h_addr_list[0], h->h_length);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ result_t Device::recv(const unsigned int timeout, unsigned char& value) {
|
||||
|
||||
ret = pselect(m_fd + 1, &readfds, NULL, NULL, &tdiff, NULL);
|
||||
#else
|
||||
ret = 1; // ignore timeout if neither ppoll nor pselect are available
|
||||
ret = 1; // ignore timeout if neither ppoll nor pselect are available
|
||||
#endif
|
||||
#endif
|
||||
if (ret == -1) {
|
||||
@@ -197,8 +197,8 @@ result_t SerialDevice::open() {
|
||||
memset(&newSettings, '\0', sizeof(newSettings));
|
||||
|
||||
newSettings.c_cflag |= (B2400 | CS8 | CLOCAL | CREAD);
|
||||
newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // non-canonical mode
|
||||
newSettings.c_iflag |= IGNPAR; // ignore parity errors
|
||||
newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // non-canonical mode
|
||||
newSettings.c_iflag |= IGNPAR; // ignore parity errors
|
||||
newSettings.c_oflag &= ~OPOST;
|
||||
|
||||
// non-canonical mode: read() blocks until at least one byte is available
|
||||
@@ -290,7 +290,7 @@ void NetworkDevice::checkDevice() {
|
||||
unsigned char value;
|
||||
ssize_t c = ::recv(m_fd, &value, 1, MSG_PEEK | MSG_DONTWAIT);
|
||||
if (c == 0 || (c < 0 && errno != EAGAIN)) {
|
||||
m_bufLen = 0; // flush read buffer
|
||||
m_bufLen = 0; // flush read buffer
|
||||
close();
|
||||
}
|
||||
}
|
||||
@@ -300,7 +300,7 @@ bool NetworkDevice::available() {
|
||||
}
|
||||
|
||||
ssize_t NetworkDevice::write(const unsigned char value) {
|
||||
m_bufLen = 0; // flush read buffer
|
||||
m_bufLen = 0; // flush read buffer
|
||||
return Device::write(value);
|
||||
}
|
||||
|
||||
@@ -324,4 +324,4 @@ ssize_t NetworkDevice::read(unsigned char& value) {
|
||||
return Device::read(value);
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
+17
-16
@@ -42,7 +42,7 @@ namespace ebusd {
|
||||
* Interface for listening to data received on/sent to a device.
|
||||
*/
|
||||
class DeviceListener {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@@ -53,7 +53,7 @@ class DeviceListener {
|
||||
* @param byte the data byte received/sent.
|
||||
* @param received @a true on reception, @a false on sending.
|
||||
*/
|
||||
virtual void notifyDeviceData(const unsigned char byte, bool received) = 0; // abstract
|
||||
virtual void notifyDeviceData(const unsigned char byte, bool received) = 0; // abstract
|
||||
};
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class DeviceListener {
|
||||
* The base class for accessing an eBUS.
|
||||
*/
|
||||
class Device {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
@@ -87,7 +87,8 @@ class Device {
|
||||
* @return the new @a Device, or NULL on error.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false, const bool initialSend = false);
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false,
|
||||
const bool initialSend = false);
|
||||
|
||||
/**
|
||||
* Get the transfer latency of this device.
|
||||
@@ -99,7 +100,7 @@ class Device {
|
||||
* Open the file descriptor.
|
||||
* @return the @a result_t code.
|
||||
*/
|
||||
virtual result_t open() = 0; // abstract
|
||||
virtual result_t open() = 0; // abstract
|
||||
|
||||
/**
|
||||
* Close the file descriptor if opened.
|
||||
@@ -146,11 +147,11 @@ class Device {
|
||||
void setListener(DeviceListener* listener) { m_listener = listener; }
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* Check if the device is still available and close it if not.
|
||||
*/
|
||||
virtual void checkDevice() = 0; // abstract
|
||||
virtual void checkDevice() = 0; // abstract
|
||||
|
||||
/**
|
||||
* Check whether a byte is available immediately (without waiting).
|
||||
@@ -188,7 +189,7 @@ class Device {
|
||||
int m_fd;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the @a DeviceListener, or NULL. */
|
||||
DeviceListener* m_listener;
|
||||
};
|
||||
@@ -197,7 +198,7 @@ class Device {
|
||||
* The @a Device for directly connected serial interfaces (tty).
|
||||
*/
|
||||
class SerialDevice : public Device {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
@@ -215,12 +216,12 @@ class SerialDevice : public Device {
|
||||
virtual void close();
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual void checkDevice();
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the previous settings of the device for restoring. */
|
||||
termios m_oldSettings;
|
||||
};
|
||||
@@ -229,7 +230,7 @@ class SerialDevice : public Device {
|
||||
* The @a Device for remote network interfaces.
|
||||
*/
|
||||
class NetworkDevice : public Device {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
@@ -250,7 +251,7 @@ class NetworkDevice : public Device {
|
||||
virtual result_t open();
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual void checkDevice();
|
||||
|
||||
@@ -264,7 +265,7 @@ class NetworkDevice : public Device {
|
||||
virtual ssize_t read(unsigned char& value);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the socket address of the device. */
|
||||
const struct sockaddr_in m_address;
|
||||
|
||||
@@ -284,6 +285,6 @@ class NetworkDevice : public Device {
|
||||
unsigned char m_bufPos;
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_DEVICE_H_
|
||||
#endif // LIB_EBUS_DEVICE_H_
|
||||
|
||||
+29
-25
@@ -62,15 +62,17 @@ using std::endl;
|
||||
/** the separator character used between multiple values (in CSV only). */
|
||||
#define VALUE_SEPARATOR ';'
|
||||
|
||||
extern void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
extern void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
|
||||
extern unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length);
|
||||
extern unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length);
|
||||
|
||||
/**
|
||||
* An abstract class that support reading definitions from a file.
|
||||
*/
|
||||
class FileReader {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
*/
|
||||
@@ -100,13 +102,14 @@ class FileReader {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
size_t lastSep = filename.find_last_of('/');
|
||||
if (lastSep != string::npos) { // potential destination address, matches "^ZZ."
|
||||
if (lastSep != string::npos) { // potential destination address, matches "^ZZ."
|
||||
// extract defaultDest, defaultCircuit, defaultSuffix from filename:
|
||||
// ZZ.IDENT[.CIRCUIT][.SUFFIX].*csv
|
||||
unsigned char checkDest;
|
||||
string checkIdent, useCircuit, useSuffix;
|
||||
unsigned int checkSw, checkHw;
|
||||
if (extractDefaultsFromFilename(filename.substr(lastSep+1), checkDest, checkIdent, useCircuit, useSuffix, checkSw, checkHw)) {
|
||||
if (extractDefaultsFromFilename(filename.substr(lastSep+1), checkDest, checkIdent, useCircuit, useSuffix,
|
||||
checkSw, checkHw)) {
|
||||
defaultDest = filename.substr(lastSep+1, 2);
|
||||
if (!useCircuit.empty()) {
|
||||
defaultCircuit = useCircuit;
|
||||
@@ -202,8 +205,8 @@ class FileReader {
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) = 0;
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) = 0;
|
||||
|
||||
/**
|
||||
* Left and right trim the string.
|
||||
@@ -249,7 +252,7 @@ class FileReader {
|
||||
|
||||
size_t length = line.length();
|
||||
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
|
||||
continue; // skip empty lines and comments
|
||||
continue; // skip empty lines and comments
|
||||
}
|
||||
for (size_t pos = 0; pos < length; pos++) {
|
||||
char ch = line[pos];
|
||||
@@ -267,7 +270,7 @@ class FileReader {
|
||||
}
|
||||
break;
|
||||
case TEXT_SEPARATOR:
|
||||
if (prev == TEXT_SEPARATOR && !quotedText) { // double dquote
|
||||
if (prev == TEXT_SEPARATOR && !quotedText) { // double dquote
|
||||
field << ch;
|
||||
quotedText = true;
|
||||
} else if (quotedText) {
|
||||
@@ -282,7 +285,7 @@ class FileReader {
|
||||
break;
|
||||
default:
|
||||
if (prev == TEXT_SEPARATOR && !quotedText && wasQuoted) {
|
||||
field << TEXT_SEPARATOR; // single dquote in the middle of formerly quoted text
|
||||
field << TEXT_SEPARATOR; // single dquote in the middle of formerly quoted text
|
||||
quotedText = true;
|
||||
} else if (quotedText && pos == 0 && field.tellp() > 0 && *(field.str().end()-1) != VALUE_SEPARATOR) {
|
||||
field << VALUE_SEPARATOR;
|
||||
@@ -322,48 +325,49 @@ class FileReader {
|
||||
ident = circuit = suffix = "";
|
||||
software = hardware = UINT_MAX;
|
||||
if (name.length() > 4 && name.substr(name.length()-4) == ".csv") {
|
||||
name = name.substr(0, name.length()-3); // including trailing "."
|
||||
name = name.substr(0, name.length()-3); // including trailing "."
|
||||
}
|
||||
size_t pos = name.find('.');
|
||||
if (pos != 2) {
|
||||
return false; // missing "ZZ."
|
||||
return false; // missing "ZZ."
|
||||
}
|
||||
result_t result = RESULT_OK;
|
||||
dest = (unsigned char)parseInt(name.substr(0, pos).c_str(), 16, 0, 0xff, result, NULL);
|
||||
if (result != RESULT_OK || !isValidAddress(dest)) {
|
||||
return false; // invalid "ZZ"
|
||||
return false; // invalid "ZZ"
|
||||
}
|
||||
name.erase(0, pos);
|
||||
if (name.length() > 1) {
|
||||
pos = name.rfind(".SW"); // check for ".SWxxxx."
|
||||
pos = name.rfind(".SW"); // check for ".SWxxxx."
|
||||
if (pos != string::npos && name.find(".", pos+1) == pos+7) {
|
||||
software = parseInt(name.substr(pos+3, 4).c_str(), 10, 0, 9999, result, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
return false; // invalid "SWxxxx"
|
||||
return false; // invalid "SWxxxx"
|
||||
}
|
||||
name.erase(pos, 7);
|
||||
}
|
||||
}
|
||||
if (name.length() > 1) {
|
||||
pos = name.rfind(".HW"); // check for ".HWxxxx."
|
||||
pos = name.rfind(".HW"); // check for ".HWxxxx."
|
||||
if (pos != string::npos && name.find(".", pos+1) == pos+7) {
|
||||
hardware = parseInt(name.substr(pos+3, 4).c_str(), 10, 0, 9999, result, NULL);
|
||||
if (result != RESULT_OK) {
|
||||
return false; // invalid "HWxxxx"
|
||||
return false; // invalid "HWxxxx"
|
||||
}
|
||||
name.erase(pos, 7);
|
||||
}
|
||||
}
|
||||
if (name.length() > 1) {
|
||||
pos = name.find('.', 1); // check for ".IDENT."
|
||||
if (pos != string::npos && pos >= 1 && pos <= 6) { // up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
pos = name.find('.', 1); // check for ".IDENT."
|
||||
if (pos != string::npos && pos >= 1 && pos <= 6) {
|
||||
// up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
ident = circuit = name.substr(1, pos-1);
|
||||
name.erase(0, pos);
|
||||
pos = name.find('.', 1); // check for ".CIRCUIT."
|
||||
pos = name.find('.', 1); // check for ".CIRCUIT."
|
||||
if (pos != string::npos && (pos>2 || name[1]<'0' || name[1]>'9')) {
|
||||
circuit = name.substr(1, pos-1);
|
||||
name.erase(0, pos);
|
||||
pos = name.find('.', 1); // check for ".SUFFIX."
|
||||
pos = name.find('.', 1); // check for ".SUFFIX."
|
||||
}
|
||||
if (pos != string::npos && pos == 2 && name[1] >= '0' && name[1] <= '9') {
|
||||
suffix = name.substr(0, 2);
|
||||
@@ -375,16 +379,16 @@ class FileReader {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** whether this instance supports rows with defaults (starting with a star). */
|
||||
bool m_supportsDefaults;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** a @a string describing the last error position. */
|
||||
string m_lastError;
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_FILEREADER_H_
|
||||
#endif // LIB_EBUS_FILEREADER_H_
|
||||
|
||||
+148
-125
@@ -83,18 +83,15 @@ Message::Message(const string circuit, const string name,
|
||||
const bool isWrite, const bool isPassive,
|
||||
const unsigned char pb, const unsigned char sb,
|
||||
DataField* data, const bool deleteData)
|
||||
: m_circuit(circuit), m_name(name), m_isWrite(isWrite),
|
||||
m_isPassive(isPassive), m_comment(),
|
||||
m_srcAddress(SYN), m_dstAddress(SYN),
|
||||
m_data(data), m_deleteData(true),
|
||||
m_pollPriority(0),
|
||||
m_usedByCondition(false), m_isScanMessage(false), m_condition(NULL),
|
||||
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
|
||||
: m_circuit(circuit), m_name(name), m_isWrite(isWrite), m_isPassive(isPassive), m_comment(), m_srcAddress(SYN),
|
||||
m_dstAddress(SYN), m_data(data), m_deleteData(true), m_pollPriority(0), m_usedByCondition(false),
|
||||
m_isScanMessage(false), m_condition(NULL), m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0),
|
||||
m_lastPollTime(0) {
|
||||
m_id.push_back(pb);
|
||||
m_id.push_back(sb);
|
||||
uint64_t key = 0;
|
||||
if (!isPassive) {
|
||||
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
|
||||
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
|
||||
}
|
||||
key |= (uint64_t)SYN << (8 * 6);
|
||||
key |= (uint64_t)pb << (8 * 5);
|
||||
@@ -116,7 +113,8 @@ Message::Message(const string circuit, const string name,
|
||||
* empty and @p replaceStar is @p true.
|
||||
* @return the default if available and value is empty, or the value.
|
||||
*/
|
||||
string getDefault(const string value, vector<string>* defaults, size_t pos, bool replaceStar = false, bool required = false) {
|
||||
string getDefault(const string value, vector<string>* defaults, size_t pos, bool replaceStar = false,
|
||||
bool required = false) {
|
||||
if (defaults == NULL || pos >= defaults->size()) {
|
||||
return value;
|
||||
}
|
||||
@@ -139,9 +137,9 @@ uint64_t Message::createKey(const vector<unsigned char> id,
|
||||
const unsigned char srcAddress, const unsigned char dstAddress) {
|
||||
uint64_t key = (uint64_t)(id.size()-2) << (8 * 7 + 5);
|
||||
if (isPassive) {
|
||||
key |= (uint64_t)getMasterNumber(srcAddress) << (8 * 7); // 0..25
|
||||
key |= (uint64_t)getMasterNumber(srcAddress) << (8 * 7); // 0..25
|
||||
} else {
|
||||
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
|
||||
key |= (isWrite ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
|
||||
}
|
||||
key |= (uint64_t)dstAddress << (8 * 6);
|
||||
int exp = 5;
|
||||
@@ -166,10 +164,10 @@ uint64_t Message::createKey(SymbolString& master, unsigned char maxIdLength, boo
|
||||
return INVALID_KEY;
|
||||
}
|
||||
uint64_t key = (uint64_t)idLength << (8 * 7 + 5);
|
||||
key |= (uint64_t)getMasterNumber(master[0]) << (8 * 7); // QQ address for passive message
|
||||
key |= (uint64_t)(anyDestination ? SYN : master[1]) << (8 * 6); // ZZ address
|
||||
key |= (uint64_t)master[2] << (8 * 5); // PB
|
||||
key |= (uint64_t)master[3] << (8 * 4); // SB
|
||||
key |= (uint64_t)getMasterNumber(master[0]) << (8 * 7); // QQ address for passive message
|
||||
key |= (uint64_t)(anyDestination ? SYN : master[1]) << (8 * 6); // ZZ address
|
||||
key |= (uint64_t)master[2] << (8 * 5); // PB
|
||||
key |= (uint64_t)master[3] << (8 * 4); // SB
|
||||
int exp = 3;
|
||||
for (unsigned char i = 0; i < idLength; i++) {
|
||||
key ^= (uint64_t)master[5 + i] << (8 * exp--);
|
||||
@@ -186,20 +184,20 @@ result_t Message::parseId(string input, vector<unsigned char>& id) {
|
||||
while (in.peek() == ' ') {
|
||||
in.get();
|
||||
}
|
||||
if (in.eof()) { // no more digits
|
||||
if (in.eof()) { // no more digits
|
||||
break;
|
||||
}
|
||||
input.clear();
|
||||
input.push_back(static_cast<char>(in.get()));
|
||||
if (in.eof()) {
|
||||
return RESULT_ERR_INVALID_ARG; // too short hex
|
||||
return RESULT_ERR_INVALID_ARG; // too short hex
|
||||
}
|
||||
input.push_back(static_cast<char>(in.get()));
|
||||
|
||||
result_t result;
|
||||
unsigned char value = (unsigned char)parseInt(input.c_str(), 16, 0, 0xff, result);
|
||||
if (result != RESULT_OK) {
|
||||
return result; // invalid hex value
|
||||
return result; // invalid hex value
|
||||
}
|
||||
id.push_back(value);
|
||||
}
|
||||
@@ -219,28 +217,28 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
string typeStr = *it++;
|
||||
const char* str = typeStr.c_str(); // [type]
|
||||
const char* str = typeStr.c_str(); // [type]
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
size_t len = strlen(str);
|
||||
if (len == 0) { // default: active read
|
||||
if (len == 0) { // default: active read
|
||||
defaultName = "r";
|
||||
} else {
|
||||
defaultName = str;
|
||||
char type = str[0];
|
||||
if (type == 'r' || type == 'R') { // active read
|
||||
if (type == 'r' || type == 'R') { // active read
|
||||
char poll = str[1];
|
||||
if (poll >= '0' && poll <= '9') { // poll priority (=active read)
|
||||
if (poll >= '0' && poll <= '9') { // poll priority (=active read)
|
||||
pollPriority = (unsigned char)(poll - '0');
|
||||
defaultName.erase(1, 1); // cut off priority digit
|
||||
defaultName.erase(1, 1); // cut off priority digit
|
||||
}
|
||||
} else if (type == 'w' || type == 'W') { // active write
|
||||
} else if (type == 'w' || type == 'W') { // active write
|
||||
isWrite = true;
|
||||
} else { // any other: passive read/write
|
||||
} else { // any other: passive read/write
|
||||
isPassive = true;
|
||||
type = str[1];
|
||||
isWrite = type == 'w' || type == 'W'; // if type continues with "w" it is treated as passive write
|
||||
isWrite = type == 'w' || type == 'W'; // if type continues with "w" it is treated as passive write
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,28 +253,28 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
}
|
||||
|
||||
string circuit = getDefault(*it++, defaults, defaultPos++, true); // [circuit]
|
||||
string circuit = getDefault(*it++, defaults, defaultPos++, true); // [circuit]
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
string name = getDefault(*it++, defaults, defaultPos++, true, true); // name
|
||||
string name = getDefault(*it++, defaults, defaultPos++, true, true); // name
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
if (name.length() == 0) {
|
||||
return RESULT_ERR_INVALID_ARG; // empty name
|
||||
return RESULT_ERR_INVALID_ARG; // empty name
|
||||
}
|
||||
string comment = getDefault(*it++, defaults, defaultPos++, true); // [comment]
|
||||
string comment = getDefault(*it++, defaults, defaultPos++, true); // [comment]
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [QQ[;QQ]*]
|
||||
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [QQ[;QQ]*]
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
unsigned char srcAddress;
|
||||
if (*str == 0) {
|
||||
srcAddress = SYN; // no specific source
|
||||
srcAddress = SYN; // no specific source
|
||||
} else {
|
||||
srcAddress = (unsigned char)parseInt(str, 16, 0, 0xff, result);
|
||||
if (result != RESULT_OK) {
|
||||
@@ -287,14 +285,14 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
}
|
||||
|
||||
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [ZZ]
|
||||
str = getDefault(*it++, defaults, defaultPos++).c_str(); // [ZZ]
|
||||
if (it == end) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
vector<unsigned char> dstAddresses;
|
||||
bool isBroadcastOrMasterDestination = false;
|
||||
if (*str == 0) {
|
||||
dstAddresses.push_back(SYN); // no specific destination
|
||||
dstAddresses.push_back(SYN); // no specific destination
|
||||
} else {
|
||||
istringstream stream(str);
|
||||
string token;
|
||||
@@ -320,7 +318,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
|
||||
vector<unsigned char> id;
|
||||
string token = *it++; // [PBSB]
|
||||
string token = *it++; // [PBSB]
|
||||
bool useDefaults = token.empty();
|
||||
if (useDefaults) {
|
||||
token = getDefault(token, defaults, defaultPos);
|
||||
@@ -331,12 +329,12 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
return result;
|
||||
}
|
||||
if (id.size() != 2) {
|
||||
return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB
|
||||
return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB
|
||||
}
|
||||
if (it == end) {
|
||||
token = "";
|
||||
} else {
|
||||
token = *it++;// [ID] (optional master data)
|
||||
token = *it++; // [ID] (optional master data)
|
||||
}
|
||||
string defaultIdPrefix;
|
||||
if (useDefaults) {
|
||||
@@ -406,7 +404,8 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
vector<string>::iterator realEnd = end;
|
||||
vector<string> newTypes;
|
||||
if (defaults != NULL && defaults->size() > defaultPos + 2) { // need at least "[name];[part];type" (optional: "[divisor|values][;[unit][;[comment]]]]")
|
||||
if (defaults != NULL && defaults->size() > defaultPos + 2) {
|
||||
// need at least "[name];[part];type" (optional: "[divisor|values][;[unit][;[comment]]]]")
|
||||
while (defaults->size() > defaultPos + 2 && defaults->at(defaultPos + 2).size() > 0) {
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
if (defaults->size() > defaultPos) {
|
||||
@@ -430,12 +429,14 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
vector<SingleDataField*> fields;
|
||||
data = new DataFieldSet("", "", fields);
|
||||
} else {
|
||||
result = DataField::create(it, realEnd, templates, data, isWrite, false, isBroadcastOrMasterDestination, (unsigned char)maxLength);
|
||||
result = DataField::create(it, realEnd, templates, data, isWrite, false, isBroadcastOrMasterDestination,
|
||||
(unsigned char)maxLength);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength || data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) {
|
||||
if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength
|
||||
|| data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) {
|
||||
// max NN exceeded
|
||||
delete data;
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
@@ -452,9 +453,11 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
Message* message;
|
||||
if (chainIds.size() > 1) {
|
||||
message = new ChainedMessage(useCircuit, name, isWrite, comment, srcAddress, dstAddress, id, chainIds, chainLengths, data, index == 0, pollPriority, condition);
|
||||
message = new ChainedMessage(useCircuit, name, isWrite, comment, srcAddress, dstAddress, id, chainIds,
|
||||
chainLengths, data, index == 0, pollPriority, condition);
|
||||
} else {
|
||||
message = new Message(useCircuit, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, index == 0, pollPriority, condition);
|
||||
message = new Message(useCircuit, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data,
|
||||
index == 0, pollPriority, condition);
|
||||
}
|
||||
messages.push_back(message);
|
||||
}
|
||||
@@ -500,7 +503,7 @@ bool Message::checkIdPrefix(vector<unsigned char>& id) {
|
||||
|
||||
bool Message::checkId(SymbolString& master, unsigned char* index) {
|
||||
unsigned char idLen = getIdLength();
|
||||
if (master.size() < 5+idLen) { // QQ, ZZ, PB, SB, NN
|
||||
if (master.size() < 5+idLen) { // QQ, ZZ, PB, SB, NN
|
||||
return false;
|
||||
}
|
||||
for (unsigned char pos = 0; pos < idLen; pos++) {
|
||||
@@ -516,7 +519,7 @@ bool Message::checkId(SymbolString& master, unsigned char* index) {
|
||||
|
||||
bool Message::checkId(Message& other) {
|
||||
unsigned char 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 other.checkIdPrefix(m_id);
|
||||
@@ -560,7 +563,7 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma
|
||||
istringstream& input, char separator,
|
||||
const unsigned char dstAddress, unsigned char index) {
|
||||
if (m_isPassive) {
|
||||
return RESULT_ERR_INVALID_ARG; // prepare not possible
|
||||
return RESULT_ERR_INVALID_ARG; // prepare not possible
|
||||
}
|
||||
SymbolString master(false);
|
||||
result_t result = master.push_back(srcAddress, false, false);
|
||||
@@ -604,7 +607,7 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
unsigned char pos = master.size();
|
||||
result_t result = master.push_back(0, false, false); // length, will be set later
|
||||
result_t result = master.push_back(0, false, false); // length, will be set later
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -624,10 +627,10 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
|
||||
|
||||
result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) {
|
||||
if (m_isWrite) {
|
||||
return RESULT_ERR_INVALID_ARG; // prepare not possible
|
||||
return RESULT_ERR_INVALID_ARG; // prepare not possible
|
||||
}
|
||||
SymbolString slave(false);
|
||||
result_t result = slave.push_back(0, false, false); // length, will be set later
|
||||
result_t result = slave.push_back(0, false, false); // length, will be set later
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -661,11 +664,11 @@ result_t Message::storeLastData(const PartType partType, SymbolString& data, uns
|
||||
}
|
||||
if (partType == pt_masterData) {
|
||||
switch (data.compareMaster(m_lastMasterData)) {
|
||||
case 1: // completely different
|
||||
case 1: // completely different
|
||||
m_lastChangeTime = m_lastUpdateTime;
|
||||
m_lastMasterData = data;
|
||||
break;
|
||||
case 2: // only master address is different
|
||||
case 2: // only master address is different
|
||||
m_lastMasterData = data;
|
||||
break;
|
||||
}
|
||||
@@ -687,7 +690,8 @@ result_t Message::decodeLastData(const PartType partType,
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
result_t result = m_data->read(partType, partType == pt_masterData ? m_lastMasterData : m_lastSlaveData, offset, output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = m_data->read(partType, partType == pt_masterData ? m_lastMasterData : m_lastSlaveData, offset,
|
||||
output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -700,18 +704,20 @@ result_t Message::decodeLastData(const PartType partType,
|
||||
result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat,
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
|
||||
size_t startPos = output.str().length();
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, getIdLength(), output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, getIdLength(), output, outputFormat, -1,
|
||||
leadingSeparator, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
bool empty = result == RESULT_EMPTY;
|
||||
leadingSeparator |= output.str().length() > startPos;
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, 0, output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, 0, output, outputFormat, -1, leadingSeparator, fieldName,
|
||||
fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (result == RESULT_EMPTY && !empty) {
|
||||
result = RESULT_OK; // OK if at least one part was non-empty
|
||||
result = RESULT_OK; // OK if at least one part was non-empty
|
||||
} else if (result == RESULT_EMPTY && fieldName != NULL) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
@@ -774,7 +780,7 @@ void Message::dump(ostream& output, vector<size_t>* columns, bool withConditions
|
||||
|
||||
void Message::dumpColumn(ostream& output, size_t column, bool withConditions) {
|
||||
switch (column) {
|
||||
case COLUMN_TYPE: // type
|
||||
case COLUMN_TYPE: // type
|
||||
if (withConditions && m_condition != NULL) {
|
||||
m_condition->dump(output);
|
||||
}
|
||||
@@ -792,36 +798,36 @@ void Message::dumpColumn(ostream& output, size_t column, bool withConditions) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COLUMN_CIRCUIT: // circuit
|
||||
case COLUMN_CIRCUIT: // circuit
|
||||
DataField::dumpString(output, m_circuit, false);
|
||||
break;
|
||||
case COLUMN_NAME: // name
|
||||
case COLUMN_NAME: // name
|
||||
DataField::dumpString(output, m_name, false);
|
||||
break;
|
||||
case COLUMN_COMMENT: // comment
|
||||
case COLUMN_COMMENT: // comment
|
||||
DataField::dumpString(output, m_comment, false);
|
||||
break;
|
||||
case COLUMN_QQ: // QQ
|
||||
case COLUMN_QQ: // QQ
|
||||
if (m_srcAddress != SYN) {
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_srcAddress);
|
||||
}
|
||||
break;
|
||||
case COLUMN_ZZ: // ZZ
|
||||
case COLUMN_ZZ: // ZZ
|
||||
if (m_dstAddress != SYN) {
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress);
|
||||
}
|
||||
break;
|
||||
case COLUMN_PBSB: // PBSB
|
||||
case COLUMN_PBSB: // PBSB
|
||||
for (vector<unsigned char>::const_iterator it = m_id.begin(); it < m_id.begin()+2 && it < m_id.end(); it++) {
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it);
|
||||
}
|
||||
break;
|
||||
case COLUMN_ID: // ID
|
||||
case COLUMN_ID: // ID
|
||||
for (vector<unsigned char>::const_iterator it = m_id.begin()+2; it < m_id.end(); it++) {
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it);
|
||||
}
|
||||
break;
|
||||
case COLUMN_FIELDS: // fields
|
||||
case COLUMN_FIELDS: // fields
|
||||
m_data->dump(output);
|
||||
break;
|
||||
}
|
||||
@@ -840,7 +846,7 @@ ChainedMessage::ChainedMessage(const string circuit, const string name,
|
||||
srcAddress, dstAddress, id,
|
||||
data, deleteData, pollPriority, condition),
|
||||
m_ids(ids), m_lengths(lengths),
|
||||
m_maxTimeDiff(m_ids.size()*15) { // 15 seconds per message
|
||||
m_maxTimeDiff(m_ids.size()*15) { // 15 seconds per message
|
||||
size_t cnt = ids.size();
|
||||
m_lastMasterDatas = reinterpret_cast<SymbolString**>(calloc(cnt, sizeof(SymbolString*)));
|
||||
m_lastSlaveDatas = reinterpret_cast<SymbolString**>(calloc(cnt, sizeof(SymbolString*)));
|
||||
@@ -879,16 +885,16 @@ Message* ChainedMessage::derive(const unsigned char dstAddress, const unsigned c
|
||||
|
||||
bool ChainedMessage::checkId(SymbolString& master, unsigned char* index) {
|
||||
unsigned char idLen = getIdLength();
|
||||
if (master.size() < 5+idLen) { // QQ, ZZ, PB, SB, NN
|
||||
if (master.size() < 5+idLen) { // QQ, ZZ, PB, SB, NN
|
||||
return false;
|
||||
}
|
||||
unsigned char chainPrefixLength = Message::getIdLength();
|
||||
for (unsigned char pos = 0; pos < chainPrefixLength; pos++) {
|
||||
if (m_id[2+pos] != master[5+pos]) {
|
||||
return false; // chain prefix mismatch
|
||||
return false; // chain prefix mismatch
|
||||
}
|
||||
}
|
||||
for (unsigned char checkIndex = 0; checkIndex < m_ids.size(); checkIndex++) { // check suffix for each part
|
||||
for (unsigned char checkIndex = 0; checkIndex < m_ids.size(); checkIndex++) { // check suffix for each part
|
||||
vector<unsigned char> id = m_ids[checkIndex];
|
||||
bool found = false;
|
||||
for (unsigned char pos = chainPrefixLength; pos < idLen; pos++) {
|
||||
@@ -910,15 +916,15 @@ bool ChainedMessage::checkId(SymbolString& master, unsigned char* index) {
|
||||
|
||||
bool ChainedMessage::checkId(Message& other) {
|
||||
unsigned char 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;
|
||||
}
|
||||
if (!other.checkIdPrefix(m_id)) {
|
||||
return false; // chain prefix mismatch
|
||||
return false; // chain prefix mismatch
|
||||
}
|
||||
vector< vector<unsigned char> > otherIds = ((ChainedMessage&)other).m_ids;
|
||||
unsigned char chainPrefixLength = Message::getIdLength();
|
||||
for (unsigned char checkIndex = 0; checkIndex < m_ids.size(); checkIndex++) { // check suffix for each part
|
||||
for (unsigned char checkIndex = 0; checkIndex < m_ids.size(); checkIndex++) { // check suffix for each part
|
||||
vector<unsigned char> id = m_ids[checkIndex];
|
||||
for (unsigned char otherIndex = 0; otherIndex < otherIds.size(); otherIndex++) {
|
||||
vector<unsigned char> otherId = otherIds[otherIndex];
|
||||
@@ -938,7 +944,8 @@ bool ChainedMessage::checkId(Message& other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream& input, char separator, unsigned char index) {
|
||||
result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream& input, char separator,
|
||||
unsigned char index) {
|
||||
size_t cnt = getCount();
|
||||
if (index >= cnt) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
@@ -960,7 +967,7 @@ result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream&
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
vector<unsigned char> id = m_ids[index];
|
||||
result = master.push_back((unsigned char)(id.size()-2+addData), false, false); // NN
|
||||
result = master.push_back((unsigned char)(id.size()-2+addData), false, false); // NN
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1003,10 +1010,10 @@ result_t ChainedMessage::storeLastData(const PartType partType, SymbolString& da
|
||||
}
|
||||
if (partType == pt_masterData) {
|
||||
switch (data.compareMaster(*m_lastMasterDatas[index])) {
|
||||
case 1: // completely different
|
||||
case 1: // completely different
|
||||
*m_lastMasterDatas[index] = data;
|
||||
break;
|
||||
case 2: // only master address is different
|
||||
case 2: // only master address is different
|
||||
*m_lastMasterDatas[index] = data;
|
||||
break;
|
||||
}
|
||||
@@ -1043,7 +1050,7 @@ result_t ChainedMessage::storeLastData(const PartType partType, SymbolString& da
|
||||
// everything was completely retrieved in short time
|
||||
SymbolString master(false);
|
||||
SymbolString slave(false);
|
||||
size_t offset = 5+(m_ids[0].size()-2); // skip QQ, ZZ, PB, SB, NN
|
||||
size_t offset = 5+(m_ids[0].size()-2); // skip QQ, ZZ, PB, SB, NN
|
||||
for (index = 0; index < m_ids.size(); index++) {
|
||||
SymbolString* add = m_lastMasterDatas[index];
|
||||
size_t end = 5+(*add)[4];
|
||||
@@ -1166,7 +1173,8 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
|
||||
valueRanges.push_back(0);
|
||||
}
|
||||
bool inclusive = str[1] == '=';
|
||||
unsigned int val = parseInt(str.substr(inclusive?2:1).c_str(), 10, inclusive?0:1, inclusive?UINT_MAX:(UINT_MAX-1), result);
|
||||
unsigned int val = parseInt(str.substr(inclusive?2:1).c_str(), 10, inclusive?0:1,
|
||||
inclusive?UINT_MAX:(UINT_MAX-1), result);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1176,14 +1184,14 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
|
||||
}
|
||||
} else {
|
||||
size_t pos = str.find('-');
|
||||
if (pos != string::npos && pos > 0) { // range
|
||||
if (pos != string::npos && pos > 0) { // range
|
||||
unsigned int val = parseInt(str.substr(0, pos).c_str(), 10, 0, UINT_MAX, result);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
valueRanges.push_back(val);
|
||||
pos++;
|
||||
} else { // single value
|
||||
} else { // single value
|
||||
pos = 0;
|
||||
}
|
||||
unsigned int val = parseInt(str.substr(pos).c_str(), 10, 0, UINT_MAX, result);
|
||||
@@ -1192,22 +1200,23 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
|
||||
}
|
||||
valueRanges.push_back(val);
|
||||
if (pos == 0) {
|
||||
valueRanges.push_back(val); // single value
|
||||
valueRanges.push_back(val); // single value
|
||||
}
|
||||
}
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end, string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) {
|
||||
result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end,
|
||||
string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) {
|
||||
// name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller)
|
||||
string circuit = it == end ? "" : *(it++); // circuit
|
||||
string name = it == end ? "" : *(it++); // messagename
|
||||
string circuit = it == end ? "" : *(it++); // circuit
|
||||
string name = it == end ? "" : *(it++); // messagename
|
||||
if (it < end) {
|
||||
it++; // comment
|
||||
it++; // comment
|
||||
}
|
||||
string field = it == end ? "" : *(it++); // fieldname
|
||||
string zz = it == end ? "" : *(it++); // ZZ
|
||||
string field = it == end ? "" : *(it++); // fieldname
|
||||
string zz = it == end ? "" : *(it++); // ZZ
|
||||
unsigned char dstAddress = SYN;
|
||||
result_t result = RESULT_OK;
|
||||
if (zz.length() == 0) {
|
||||
@@ -1304,12 +1313,14 @@ CombinedCondition* SimpleCondition::combineAnd(Condition* other) {
|
||||
return ret->combineAnd(this)->combineAnd(other);
|
||||
}
|
||||
|
||||
result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)) {
|
||||
result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message)) {
|
||||
if (m_message == NULL) {
|
||||
Message* message;
|
||||
if (m_name.length() == 0) {
|
||||
message = messages->getScanMessage(m_dstAddress);
|
||||
errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0') << static_cast<unsigned>(m_dstAddress);
|
||||
errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0')
|
||||
<< static_cast<unsigned>(m_dstAddress);
|
||||
} else {
|
||||
message = messages->find(m_circuit, m_name, false);
|
||||
if (!message) {
|
||||
@@ -1339,7 +1350,8 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
|
||||
} else {
|
||||
Message* first = getFirstAvailable(*derived, message);
|
||||
if (first == NULL) {
|
||||
errorMessage << ": conditional derived message " << message->getCircuit() << "." << message->getName() << " for " << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress) << " not found";
|
||||
errorMessage << ": conditional derived message " << message->getCircuit() << "." << message->getName()
|
||||
<< " for " << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress) << " not found";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
message = first;
|
||||
@@ -1369,7 +1381,7 @@ bool SimpleCondition::isTrue() {
|
||||
return false;
|
||||
}
|
||||
if (m_message->getLastChangeTime() > m_lastCheckTime) {
|
||||
bool isTrue = !m_hasValues; // for message seen check
|
||||
bool isTrue = !m_hasValues; // for message seen check
|
||||
if (!isTrue) {
|
||||
isTrue = checkValue(m_message, m_field);
|
||||
}
|
||||
@@ -1420,7 +1432,8 @@ void CombinedCondition::dump(ostream& output, bool matched) {
|
||||
}
|
||||
}
|
||||
|
||||
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)) {
|
||||
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message)) {
|
||||
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
|
||||
Condition* condition = *it;
|
||||
ostringstream dummy;
|
||||
@@ -1443,8 +1456,9 @@ bool CombinedCondition::isTrue() {
|
||||
}
|
||||
|
||||
|
||||
result_t Instruction::create(const string contextPath, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue) {
|
||||
result_t Instruction::create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, Condition* condition, const string type, vector<string>::iterator& it,
|
||||
const vector<string>::iterator end, Instruction*& returnValue) {
|
||||
// type[,argument]* (type already skipped by caller)
|
||||
bool singleton = false;
|
||||
if ((singleton=(type == "load")) || type == "include") {
|
||||
@@ -1494,7 +1508,8 @@ result_t LoadInstruction::execute(MessageMap* messages, ostringstream& log, Cond
|
||||
log << ", ";
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
log << "error " << (isSingleton() ? "loading \"" : "including \"") << m_filename << "\" for \"" << getDestination() << "\": " << getResultCode(result);
|
||||
log << "error " << (isSingleton() ? "loading \"" : "including \"") << m_filename << "\" for \""
|
||||
<< getDestination() << "\": " << getResultCode(result);
|
||||
return result;
|
||||
}
|
||||
log << (isSingleton() ? "loaded \"" : "included \"") << m_filename << "\" for \"" << getDestination() << "\"";
|
||||
@@ -1532,10 +1547,10 @@ result_t MessageMap::add(Message* message, bool storeByName) {
|
||||
Message* other = getFirstAvailable(keyIt->second, message);
|
||||
if (other != NULL) {
|
||||
if (!conditional) {
|
||||
return RESULT_ERR_DUPLICATE; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE; // duplicate key
|
||||
}
|
||||
if (!other->isConditional()) {
|
||||
return RESULT_ERR_DUPLICATE; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE; // duplicate key
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1553,23 +1568,26 @@ result_t MessageMap::add(Message* message, bool storeByName) {
|
||||
if (nameIt != m_messagesByName.end()) {
|
||||
vector<Message*>* messages = &nameIt->second;
|
||||
if (!message->isConditional() || !messages->front()->isConditional()) {
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (nameIt == m_messagesByName.end()) {
|
||||
m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name)
|
||||
// always store first message without circuit (in order of circuit name)
|
||||
m_messagesByName[nameKey].push_back(message);
|
||||
} else {
|
||||
vector<Message*>* messages = &nameIt->second;
|
||||
Message* first = messages->front();
|
||||
if (circuit < first->getCircuit()) {
|
||||
m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name)
|
||||
// always store first message without circuit (in order of circuit name)
|
||||
m_messagesByName[nameKey].at(0) = message;
|
||||
} else if (m_addAll || (conditional && first->isConditional())) {
|
||||
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything
|
||||
// store further messages only if both are conditional or if storing everything
|
||||
m_messagesByName[nameKey].push_back(message);
|
||||
}
|
||||
}
|
||||
m_messageCount++;
|
||||
@@ -1618,22 +1636,26 @@ result_t MessageMap::addDefaultFromFile(vector< vector<string> >& defaults, vect
|
||||
}
|
||||
if (row.size() > 1 && defaultCircuit.length() > 0) {
|
||||
if (row[1].length() == 0) {
|
||||
row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
|
||||
row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
|
||||
} else if (row[1][0] == '#') {
|
||||
row[1] = defaultCircuit+defaultSuffix+row[1]; // move security suffix behind default circuit and suffix: "circuit[.suffix]#security"
|
||||
} else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) { // circuit suffix not yet present
|
||||
// move security suffix behind default circuit and suffix: "circuit[.suffix]#security"
|
||||
row[1] = defaultCircuit+defaultSuffix+row[1];
|
||||
} else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) {
|
||||
// circuit suffix not yet present
|
||||
size_t pos = row[1].find_first_of('#');
|
||||
if (pos == string::npos) {
|
||||
row[1] += defaultSuffix; // append default suffix: "circuit.suffix"
|
||||
row[1] += defaultSuffix; // append default suffix: "circuit.suffix"
|
||||
} else {
|
||||
row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos); // insert default suffix: "circuit.suffix#security"
|
||||
// insert default suffix: "circuit.suffix#security"
|
||||
row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row.size() > 5 && defaultDest.length() > 0 && row[5].length() == 0) {
|
||||
row[5] = defaultDest; // set default destination
|
||||
row[5] = defaultDest; // set default destination
|
||||
}
|
||||
return FileReader::addDefaultFromFile(defaults, row, begin, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
|
||||
return FileReader::addDefaultFromFile(defaults, row, begin, defaultDest, defaultCircuit, defaultSuffix, filename,
|
||||
lineNo);
|
||||
}
|
||||
|
||||
result_t MessageMap::readConditions(string& types, const string& filename, Condition*& condition) {
|
||||
@@ -1665,7 +1687,7 @@ result_t MessageMap::readConditions(string& types, const string& filename, Condi
|
||||
m_lastError = "derive condition with values "+key.substr(pos)+" failed";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
m_conditions[key] = add; // store derived condition
|
||||
m_conditions[key] = add; // store derived condition
|
||||
}
|
||||
}
|
||||
if (add == NULL) {
|
||||
@@ -1688,7 +1710,7 @@ result_t MessageMap::readConditions(string& types, const string& filename, Condi
|
||||
}
|
||||
}
|
||||
if (store) {
|
||||
m_conditions[combinedkey] = condition; // store combined condition
|
||||
m_conditions[combinedkey] = condition; // store combined condition
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1696,8 +1718,8 @@ result_t MessageMap::readConditions(string& types, const string& filename, Condi
|
||||
}
|
||||
|
||||
result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) {
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) {
|
||||
vector<string>::iterator restart = begin;
|
||||
string types = *restart;
|
||||
Condition* condition = NULL;
|
||||
@@ -1709,7 +1731,8 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
|
||||
// instruction
|
||||
types = types.substr(1);
|
||||
Instruction* instruction = NULL;
|
||||
result_t result = Instruction::create(filename, defaultDest, defaultCircuit, defaultSuffix, condition, types, ++begin, end, instruction);
|
||||
result_t result = Instruction::create(filename, defaultDest, defaultCircuit, defaultSuffix, condition, types,
|
||||
++begin, end, instruction);
|
||||
if (instruction == NULL || result != RESULT_OK) {
|
||||
m_lastError = "invalid instruction";
|
||||
return result;
|
||||
@@ -1745,13 +1768,13 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
|
||||
if (result == RESULT_OK) {
|
||||
result = add(message);
|
||||
if (result == RESULT_ERR_DUPLICATE_NAME) {
|
||||
begin = restart+3; // mark name as invalid
|
||||
begin = restart+3; // mark name as invalid
|
||||
} else if (result == RESULT_ERR_DUPLICATE) {
|
||||
begin = restart+8; // mark ID as invalid
|
||||
begin = restart+8; // mark ID as invalid
|
||||
}
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
delete message; // delete all remaining messages on error
|
||||
delete message; // delete all remaining messages on error
|
||||
}
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
@@ -1906,9 +1929,9 @@ Message* MessageMap::find(const string& circuit, const string& name, const bool
|
||||
if (i == 0) {
|
||||
key = string(isPassive ? "P" : (isWrite ? "W" : "R")) + lcircuit + FIELD_SEPARATOR + lname;
|
||||
} else if (lcircuit.length() == 0) {
|
||||
key = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + lname; // second try: without circuit
|
||||
key = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + lname; // second try: without circuit
|
||||
} else {
|
||||
continue; // not allowed without circuit
|
||||
continue; // not allowed without circuit
|
||||
}
|
||||
map<string, vector<Message*> >::iterator it = m_messagesByName.find(key);
|
||||
if (it != m_messagesByName.end()) {
|
||||
@@ -1940,7 +1963,7 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
|
||||
}
|
||||
}
|
||||
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
|
||||
if (it->first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-"
|
||||
if (it->first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-"
|
||||
continue;
|
||||
}
|
||||
for (vector<Message*>::iterator msgIt = it->second.begin(); msgIt != it->second.end(); msgIt++) {
|
||||
@@ -2032,7 +2055,7 @@ Message* MessageMap::find(SymbolString& master, bool anyDestination,
|
||||
}
|
||||
if ((key & ID_SOURCE_MASK) != 0) {
|
||||
key &= ~ID_SOURCE_MASK;
|
||||
it = m_messagesByKey.find(key & ~ID_SOURCE_MASK); // try again without specific source master
|
||||
it = m_messagesByKey.find(key & ~ID_SOURCE_MASK); // try again without specific source master
|
||||
if (it != m_messagesByKey.end()) {
|
||||
Message* message = getFirstAvailable(it->second, &master);
|
||||
if (message) {
|
||||
@@ -2044,7 +2067,7 @@ Message* MessageMap::find(SymbolString& master, bool anyDestination,
|
||||
key &= ~ID_SOURCE_MASK;
|
||||
}
|
||||
if (withRead) {
|
||||
it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_READ); // try again with special value for active read
|
||||
it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_READ); // try again with special value for active read
|
||||
if (it != m_messagesByKey.end()) {
|
||||
Message* message = getFirstAvailable(it->second, &master);
|
||||
if (message) {
|
||||
@@ -2053,7 +2076,7 @@ Message* MessageMap::find(SymbolString& master, bool anyDestination,
|
||||
}
|
||||
}
|
||||
if (withWrite) {
|
||||
it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_WRITE); // try again with special value for active write
|
||||
it = m_messagesByKey.find(key | ID_SOURCE_ACTIVE_WRITE); // try again with special value for active write
|
||||
if (it != m_messagesByKey.end()) {
|
||||
Message* message = getFirstAvailable(it->second, &master);
|
||||
if (message) {
|
||||
@@ -2102,7 +2125,7 @@ void MessageMap::clear() {
|
||||
// free message instances by name
|
||||
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
|
||||
vector<Message*> nameMessages = it->second;
|
||||
if (it->first[0] != '-') { // avoid double free: instances stored multiple times have a key starting with "-"
|
||||
if (it->first[0] != '-') { // avoid double free: instances stored multiple times have a key starting with "-"
|
||||
for (vector<Message*>::iterator nit = nameMessages.begin(); nit != nameMessages.end(); nit++) {
|
||||
Message* message = *nit;
|
||||
map<uint64_t, vector<Message*> >::iterator keyIt = m_messagesByKey.find(message->getKey());
|
||||
@@ -2163,14 +2186,14 @@ Message* MessageMap::getNextPoll() {
|
||||
m_pollMessages.pop();
|
||||
ret->m_pollCount++;
|
||||
time(&(ret->m_lastPollTime));
|
||||
m_pollMessages.push(ret); // re-insert at new position
|
||||
m_pollMessages.push(ret); // re-insert at new position
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MessageMap::dump(ostream& output, bool withConditions) {
|
||||
bool first = true;
|
||||
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
|
||||
if (it->first[0] == '-') { // skip instances stored multiple times (key starting with "-")
|
||||
if (it->first[0] == '-') { // skip instances stored multiple times (key starting with "-")
|
||||
continue;
|
||||
}
|
||||
if (m_addAll) {
|
||||
@@ -2204,4 +2227,4 @@ void MessageMap::dump(ostream& output, bool withConditions) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
+91
-64
@@ -100,7 +100,7 @@ class MessageMap;
|
||||
*/
|
||||
class Message {
|
||||
friend class MessageMap;
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param circuit the optional circuit name.
|
||||
@@ -126,7 +126,7 @@ class Message {
|
||||
Condition* condition = NULL);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* Construct a new scan @a Message instance.
|
||||
* @param circuit the circuit name, or empty for not storing by name.
|
||||
@@ -145,7 +145,7 @@ class Message {
|
||||
DataField* data, const bool deleteData);
|
||||
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@@ -229,7 +229,8 @@ class Message {
|
||||
* @param circuit the new circuit name, or empty to use the current circuit name.
|
||||
* @return the derived @a Message instance.
|
||||
*/
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN,
|
||||
const string circuit = "");
|
||||
|
||||
/**
|
||||
* Derive a new @a Message from this message.
|
||||
@@ -400,7 +401,7 @@ class Message {
|
||||
const unsigned char dstAddress = SYN, unsigned char index = 0);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* Prepare a part of the master data @a SymbolString for sending (everything including NN).
|
||||
* @param master the master data @a SymbolString for writing symbols to.
|
||||
@@ -412,7 +413,7 @@ class Message {
|
||||
virtual result_t prepareMasterPart(SymbolString& master, istringstream& input, char separator, unsigned char index);
|
||||
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Prepare the slave @a SymbolString for sending an answer to the bus.
|
||||
* @param input the @a istringstream to parse the formatted value(s) from.
|
||||
@@ -527,7 +528,7 @@ class Message {
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** the optional circuit name. */
|
||||
const string m_circuit;
|
||||
|
||||
@@ -618,7 +619,7 @@ class Message {
|
||||
* A chained @a Message that needs more than one read/write on the bus to collect/send the data.
|
||||
*/
|
||||
class ChainedMessage : public Message {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param circuit the optional circuit name.
|
||||
@@ -647,7 +648,8 @@ class ChainedMessage : public Message {
|
||||
virtual ~ChainedMessage();
|
||||
|
||||
// @copydoc
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN,
|
||||
const string circuit = "");
|
||||
|
||||
// @copydoc
|
||||
virtual unsigned char getIdLength() const { return (unsigned char)(m_ids[0].size() - 2); }
|
||||
@@ -662,12 +664,12 @@ class ChainedMessage : public Message {
|
||||
virtual unsigned char getCount() { return (unsigned char)m_ids.size(); }
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual result_t prepareMasterPart(SymbolString& master, istringstream& input, char separator, unsigned char index);
|
||||
|
||||
|
||||
public:
|
||||
public:
|
||||
// @copydoc
|
||||
virtual result_t storeLastData(SymbolString& master, SymbolString& slave);
|
||||
|
||||
@@ -675,12 +677,12 @@ class ChainedMessage : public Message {
|
||||
virtual result_t storeLastData(const PartType partType, SymbolString& data, unsigned char index);
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the primary, secondary, and optional further ID bytes for each part of the chain. */
|
||||
const vector< vector<unsigned char> > m_ids;
|
||||
|
||||
@@ -723,7 +725,7 @@ struct compareMessagePriority : binary_function<Message*, Message*, bool> {
|
||||
*/
|
||||
class MessagePriorityQueue
|
||||
: public priority_queue<Message*, vector<Message*>, compareMessagePriority> {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Add data to the queue and ensure it is contained only once.
|
||||
* @param __x the element to add.
|
||||
@@ -744,7 +746,7 @@ class MessagePriorityQueue
|
||||
* An abstract condition based on the value of one or more @a Message instances.
|
||||
*/
|
||||
class Condition {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
*/
|
||||
@@ -766,7 +768,8 @@ class Condition {
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end, string defaultDest, string defaultCircuit, SimpleCondition*& returnValue);
|
||||
static result_t create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end,
|
||||
string defaultDest, string defaultCircuit, SimpleCondition*& returnValue);
|
||||
|
||||
/**
|
||||
* Derive a new @a SimpleCondition from this condition.
|
||||
@@ -796,7 +799,8 @@ class Condition {
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
|
||||
/**
|
||||
* Check and return whether this condition is fulfilled.
|
||||
@@ -805,7 +809,7 @@ class Condition {
|
||||
virtual bool isTrue() = 0;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** the system time when the condition was last checked, 0 for never. */
|
||||
time_t m_lastCheckTime;
|
||||
|
||||
@@ -818,20 +822,23 @@ class Condition {
|
||||
* A simple @a Condition based on the value of one @a Message.
|
||||
*/
|
||||
class SimpleCondition : public Condition {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condName the name of the condition.
|
||||
* @param refName the reference name for dumping.
|
||||
* @param circuit the circuit name.
|
||||
* @param name the message name, or empty for scan message.
|
||||
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message).
|
||||
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination
|
||||
* as well as scan message).
|
||||
* @param field the field name.
|
||||
* @param hasValues whether a value has to be checked against.
|
||||
*/
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const bool hasValues = false)
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const bool hasValues = false)
|
||||
: Condition(),
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress),
|
||||
m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -848,7 +855,8 @@ class SimpleCondition : public Condition {
|
||||
virtual CombinedCondition* combineAnd(Condition* other);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
@@ -860,7 +868,7 @@ class SimpleCondition : public Condition {
|
||||
virtual bool isNumeric() { return true; }
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* Check the values against the field in the @a Message.
|
||||
* @param message the @a Message to check against.
|
||||
@@ -873,7 +881,7 @@ class SimpleCondition : public Condition {
|
||||
string m_matchedValue;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the condition name. */
|
||||
const string m_condName;
|
||||
|
||||
@@ -886,7 +894,8 @@ class SimpleCondition : public Condition {
|
||||
/** the message name, or empty for scan message. */
|
||||
const string m_name;
|
||||
|
||||
/** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message). */
|
||||
/** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan
|
||||
* message). */
|
||||
const unsigned char m_dstAddress;
|
||||
|
||||
/** the field name, or empty for first field. */
|
||||
@@ -904,7 +913,7 @@ class SimpleCondition : public Condition {
|
||||
* A simple @a Condition based on the numeric value of one @a Message.
|
||||
*/
|
||||
class SimpleNumericCondition : public SimpleCondition {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condName the name of the condition.
|
||||
@@ -915,7 +924,8 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
|
||||
*/
|
||||
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges)
|
||||
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges)
|
||||
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
|
||||
m_valueRanges(valueRanges) { }
|
||||
|
||||
@@ -925,12 +935,12 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
virtual ~SimpleNumericCondition() {}
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual bool checkValue(Message* message, const string field);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check. */
|
||||
const vector<unsigned int> m_valueRanges;
|
||||
};
|
||||
@@ -940,7 +950,7 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
* A simple @a Condition based on the string value of one @a Message.
|
||||
*/
|
||||
class SimpleStringCondition : public SimpleCondition {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condName the name of the condition.
|
||||
@@ -951,7 +961,8 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param values the valid values.
|
||||
*/
|
||||
SimpleStringCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const vector<string> values)
|
||||
SimpleStringCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const vector<string> values)
|
||||
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
|
||||
m_values(values) { }
|
||||
|
||||
@@ -964,12 +975,12 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
virtual bool isNumeric() { return false; }
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// @copydoc
|
||||
virtual bool checkValue(Message* message, const string field);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the valid values. */
|
||||
const vector<string> m_values;
|
||||
};
|
||||
@@ -979,7 +990,7 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
* A @a Condition combining two or more @a SimpleCondition instances with a logical and.
|
||||
*/
|
||||
class CombinedCondition : public Condition {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
*/
|
||||
@@ -998,13 +1009,14 @@ class CombinedCondition : public Condition {
|
||||
virtual CombinedCondition* combineAnd(Condition* other) { m_conditions.push_back(other); return this; }
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the @a Condition instances used. */
|
||||
vector<Condition*> m_conditions;
|
||||
};
|
||||
@@ -1014,17 +1026,20 @@ class CombinedCondition : public Condition {
|
||||
* An abstract instruction based on the value of one or more @a Message instances.
|
||||
*/
|
||||
class Instruction {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condition the @a Condition this instruction requires, or null.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be
|
||||
* executed for the same source file.
|
||||
* @param defaultDest the default destination address, or empty.
|
||||
* @param defaultCircuit the default circuit name, or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a "."), or empty.
|
||||
*/
|
||||
Instruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix)
|
||||
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit), m_defaultSuffix(defaultSuffix) { }
|
||||
Instruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix)
|
||||
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit),
|
||||
m_defaultSuffix(defaultSuffix) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -1044,8 +1059,9 @@ class Instruction {
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string contextPath, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue);
|
||||
static result_t create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, Condition* condition, const string type, vector<string>::iterator& it,
|
||||
const vector<string>::iterator end, Instruction*& returnValue);
|
||||
|
||||
/**
|
||||
* Return the @a Condition this instruction requires.
|
||||
@@ -1054,8 +1070,10 @@ class Instruction {
|
||||
Condition* getCondition() { return m_condition; }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @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.
|
||||
* 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.
|
||||
* @return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed
|
||||
* for the same source file.
|
||||
*/
|
||||
bool isSingleton() { return m_singleton; }
|
||||
|
||||
@@ -1075,15 +1093,16 @@ class Instruction {
|
||||
virtual result_t execute(MessageMap* messages, ostringstream& log, Condition* condition) = 0;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the @a Condition this instruction requires, or null. */
|
||||
Condition* m_condition;
|
||||
|
||||
/** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file. */
|
||||
/** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the
|
||||
* same source file. */
|
||||
bool m_singleton;
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/** the default destination address, or empty. */
|
||||
const string m_defaultDest;
|
||||
|
||||
@@ -1099,17 +1118,20 @@ class Instruction {
|
||||
* An @a Instruction allowing to load another file.
|
||||
*/
|
||||
class LoadInstruction : public Instruction {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condition the @a Condition this instruction requires, or null.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be
|
||||
* executed for the same source file.
|
||||
* @param defaultDest the default destination address (may be overwritten by file name), or empty.
|
||||
* @param defaultCircuit the default circuit name (may be overwritten by file name), or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a ".", may be overwritten by file name), or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a ".", may be overwritten by file name), or
|
||||
* empty.
|
||||
* @param filename the name of the file to load.
|
||||
*/
|
||||
LoadInstruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix, const string filename)
|
||||
LoadInstruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string filename)
|
||||
: Instruction(condition, singleton, defaultDest, defaultCircuit, defaultSuffix), m_filename(filename) { }
|
||||
|
||||
/**
|
||||
@@ -1121,7 +1143,7 @@ class LoadInstruction : public Instruction {
|
||||
virtual result_t execute(MessageMap* messages, ostringstream& log, Condition* condition);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the name of the file to load. */
|
||||
const string m_filename;
|
||||
};
|
||||
@@ -1131,7 +1153,7 @@ class LoadInstruction : public Instruction {
|
||||
* Holds a map of all known @a Message instances.
|
||||
*/
|
||||
class MessageMap : public FileReader {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param addAll whether to add all messages, even if duplicate.
|
||||
@@ -1174,8 +1196,8 @@ class MessageMap : public FileReader {
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo);
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo);
|
||||
|
||||
/**
|
||||
* Get the scan @a Message instance for the specified address.
|
||||
@@ -1219,7 +1241,8 @@ class MessageMap : public FileReader {
|
||||
/**
|
||||
* Get the loaded files for a participant.
|
||||
* @param address the slave address.
|
||||
* @return the name of the file(s) loaded for the participant (separated by comma and enclosed in double quotes), or empty.
|
||||
* @return the name of the file(s) loaded for the participant (separated by comma and enclosed in double quotes),
|
||||
* or empty.
|
||||
*/
|
||||
string getLoadedFiles(unsigned char address);
|
||||
|
||||
@@ -1246,15 +1269,19 @@ class MessageMap : public FileReader {
|
||||
* Find all active get @a Message instances for the specified circuit and name.
|
||||
* @param circuit the circuit name, or empty for any.
|
||||
* @param name the message name, or empty for any.
|
||||
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given circuit and name (default true).
|
||||
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given
|
||||
* circuit and name (default true).
|
||||
* @param withRead true to include read messages (default true).
|
||||
* @param withWrite true to include write messages (default false).
|
||||
* @param withPassive true to include passive messages (default false).
|
||||
* @return the found @a Message instances.
|
||||
* @param completeMatchIgnoreCircuitSuffix ignore different circuit suffixes (after "#") for completeMatch.
|
||||
* @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).
|
||||
* @param since the start time from which to add updates (inclusive, also removes messages with unset destination address), or 0 to ignore.
|
||||
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination address), or 0 to ignore.
|
||||
* @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).
|
||||
* @param since the start time from which to add updates (inclusive, also removes messages with unset destination
|
||||
* address), or 0 to ignore.
|
||||
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination
|
||||
* address), or 0 to ignore.
|
||||
* Note: the caller may not free the returned instances.
|
||||
*/
|
||||
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true,
|
||||
@@ -1344,7 +1371,7 @@ class MessageMap : public FileReader {
|
||||
void dump(ostream& output, bool withConditions = false);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** whether to add all messages, even if duplicate. */
|
||||
const bool m_addAll;
|
||||
|
||||
@@ -1382,6 +1409,6 @@ class MessageMap : public FileReader {
|
||||
map<string, vector<Instruction*> > m_instructions;
|
||||
};
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_MESSAGE_H_
|
||||
#endif // LIB_EBUS_MESSAGE_H_
|
||||
|
||||
@@ -58,4 +58,4 @@ const char* getResultCode(result_t resultCode) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
@@ -46,14 +46,14 @@ enum result_t {
|
||||
RESULT_ERR_EOF = -7, //!< end of input reached
|
||||
RESULT_ERR_INVALID_ARG = -8, //!< invalid argument
|
||||
RESULT_ERR_INVALID_NUM = -9, //!< invalid numeric argument
|
||||
RESULT_ERR_INVALID_ADDR = -10, //!< invalid address
|
||||
RESULT_ERR_INVALID_ADDR = -10, //!< invalid address
|
||||
RESULT_ERR_INVALID_POS = -11, //!< invalid position
|
||||
RESULT_ERR_OUT_OF_RANGE = -12, //!< argument value out of valid range
|
||||
RESULT_ERR_INVALID_PART = -13, //!< invalid part type value
|
||||
RESULT_ERR_MISSING_TYPE = -14, //!< missing data type
|
||||
RESULT_ERR_INVALID_LIST = -15, //!< invalid value list
|
||||
RESULT_ERR_OUT_OF_RANGE = -12, //!< argument value out of valid range
|
||||
RESULT_ERR_INVALID_PART = -13, //!< invalid part type value
|
||||
RESULT_ERR_MISSING_TYPE = -14, //!< missing data type
|
||||
RESULT_ERR_INVALID_LIST = -15, //!< invalid value list
|
||||
RESULT_ERR_DUPLICATE = -16, //!< duplicate entry
|
||||
RESULT_ERR_DUPLICATE_NAME = -17, //!< duplicate entry (name)
|
||||
RESULT_ERR_DUPLICATE_NAME = -17, //!< duplicate entry (name)
|
||||
|
||||
RESULT_ERR_BUS_LOST = -18, //!< arbitration lost
|
||||
RESULT_ERR_CRC = -19, //!< CRC error
|
||||
@@ -72,6 +72,6 @@ enum result_t {
|
||||
*/
|
||||
const char* getResultCode(result_t resultCode);
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_RESULT_H_
|
||||
#endif // LIB_EBUS_RESULT_H_
|
||||
|
||||
+11
-11
@@ -66,7 +66,7 @@ void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol) {
|
||||
push_back(data[i], isEscaped, addCrc);
|
||||
}
|
||||
if (addCrc) {
|
||||
push_back(m_crc, false, false); // add CRC
|
||||
push_back(m_crc, false, false); // add CRC
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ result_t SymbolString::parseHex(const string& str, const bool isEscaped) {
|
||||
unsigned long value = strtoul(strBegin, &strEnd, 16);
|
||||
|
||||
if (strEnd == NULL || strEnd != strBegin+2 || value > 0xff) {
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||
}
|
||||
push_back((unsigned char)value, isEscaped, addCrc);
|
||||
}
|
||||
if (addCrc) {
|
||||
push_back(m_crc, false, false); // add CRC
|
||||
push_back(m_crc, false, false); // add CRC
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -97,16 +97,16 @@ const string SymbolString::getDataStr(const bool unescape, const bool skipLastSy
|
||||
if (m_unescapeState == 0 && unescape && previousEscape) {
|
||||
if (!skipLastSymbol || i+1 < m_data.size()) {
|
||||
if (value == 0x00) {
|
||||
sstr << "a9"; // ESC
|
||||
sstr << "a9"; // ESC
|
||||
} else if (value == 0x01) {
|
||||
sstr << "aa"; // SYN
|
||||
sstr << "aa"; // SYN
|
||||
} else {
|
||||
sstr << "XX"; // invalid escape sequence
|
||||
sstr << "XX"; // invalid escape sequence
|
||||
}
|
||||
}
|
||||
previousEscape = false;
|
||||
} else if (m_unescapeState == 0 && unescape && value == ESC) {
|
||||
previousEscape = true; // escape sequence not yet finished
|
||||
previousEscape = true; // escape sequence not yet finished
|
||||
} else if (!skipLastSymbol || i+1 < m_data.size()) {
|
||||
sstr << nouppercase << setw(2) << hex
|
||||
<< setfill('0') << static_cast<unsigned>(value);
|
||||
@@ -116,7 +116,7 @@ const string SymbolString::getDataStr(const bool unescape, const bool skipLastSy
|
||||
}
|
||||
|
||||
result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) {
|
||||
if (m_unescapeState == 0) { // store escaped data
|
||||
if (m_unescapeState == 0) { // store escaped data
|
||||
if (!isEscaped && value == ESC) {
|
||||
m_data.push_back(ESC);
|
||||
m_data.push_back(0x00);
|
||||
@@ -141,7 +141,7 @@ result_t SymbolString::push_back(const unsigned char value, const bool isEscaped
|
||||
}
|
||||
if (!isEscaped) {
|
||||
if (m_unescapeState != 1) {
|
||||
return RESULT_ERR_ESC; // invalid unescape state
|
||||
return RESULT_ERR_ESC; // invalid unescape state
|
||||
}
|
||||
m_data.push_back(value);
|
||||
if (updateCRC) {
|
||||
@@ -171,7 +171,7 @@ result_t SymbolString::push_back(const unsigned char value, const bool isEscaped
|
||||
m_unescapeState = 1;
|
||||
return RESULT_OK;
|
||||
}
|
||||
return RESULT_ERR_ESC; // invalid escape sequence
|
||||
return RESULT_ERR_ESC; // invalid escape sequence
|
||||
}
|
||||
if (value == ESC) {
|
||||
if (updateCRC) {
|
||||
@@ -261,4 +261,4 @@ bool isValidAddress(unsigned char addr, bool allowBroadcast) {
|
||||
return addr != SYN && addr != ESC && (allowBroadcast || addr != BROADCAST);
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
+29
-15
@@ -68,18 +68,19 @@ namespace ebusd {
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
static const unsigned char ESC = 0xA9; //!< escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
|
||||
/** escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA. */
|
||||
static const unsigned char ESC = 0xA9;
|
||||
static const unsigned char SYN = 0xAA; //!< synchronization symbol
|
||||
static const unsigned char ACK = 0x00; //!< positive acknowledge
|
||||
static const unsigned char NAK = 0xFF; //!< negative acknowledge
|
||||
static const unsigned char BROADCAST = 0xFE; //!< the broadcast destination address
|
||||
static const unsigned char BROADCAST = 0xFE; //!< the broadcast destination address
|
||||
|
||||
|
||||
/**
|
||||
* A string of escaped or unescaped bus symbols.
|
||||
*/
|
||||
class SymbolString {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Creates a new empty escaped or unescaped instance.
|
||||
* @param escaped whether to create an escaped instance.
|
||||
@@ -114,24 +115,35 @@ class SymbolString {
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the reference to the symbol at the specified index.
|
||||
*/
|
||||
unsigned char& operator[](const size_t index) { if (index >= m_data.size()) { m_data.resize(index+1, 0); } return m_data[index]; }
|
||||
unsigned char& operator[](const size_t index) {
|
||||
if (index >= m_data.size()) {
|
||||
m_data.resize(index+1, 0);
|
||||
}
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this instance is equal to the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols).
|
||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same
|
||||
* symbols).
|
||||
*/
|
||||
bool operator == (SymbolString& other) { return m_unescapeState == other.m_unescapeState && m_data == other.m_data; }
|
||||
bool operator == (SymbolString& other) {
|
||||
return m_unescapeState == other.m_unescapeState && m_data == other.m_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this instance is different from the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is different from the other instance.
|
||||
*/
|
||||
bool operator != (SymbolString& other) { return m_unescapeState != other.m_unescapeState || m_data != other.m_data; }
|
||||
bool operator != (SymbolString& other) {
|
||||
return m_unescapeState != other.m_unescapeState || m_data != other.m_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master address and ending with the CRC).
|
||||
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master
|
||||
* address and ending with the CRC).
|
||||
* @param other the other instance.
|
||||
* @return 0 if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols),
|
||||
* 1 if this instance is completely different to the other instance,
|
||||
@@ -159,8 +171,8 @@ class SymbolString {
|
||||
* @param isEscaped whether the symbol is escaped.
|
||||
* @param updateCRC whether to update the calculated CRC in @a m_crc.
|
||||
* @return RESULT_OK if another symbol was appended,
|
||||
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was received,
|
||||
* RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
|
||||
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was
|
||||
* received, RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
|
||||
*/
|
||||
result_t push_back(const unsigned char value, const bool isEscaped = true, const bool updateCRC = true);
|
||||
|
||||
@@ -188,7 +200,7 @@ class SymbolString {
|
||||
void clear(const bool escape) { m_data.clear(); m_unescapeState = escape ? 0 : 1; m_crc = 0; }
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* Hidden copy constructor.
|
||||
* @param str the @a SymbolString to copy from.
|
||||
@@ -234,14 +246,16 @@ bool isSlaveMaster(unsigned char addr);
|
||||
/**
|
||||
* Return the slave address associated with the specified address (master or slave).
|
||||
* @param addr the address to check.
|
||||
* @return the slave address, or SYN if the specified address is neither a master address nor a slave address of a master.
|
||||
* @return the slave address, or SYN if the specified address is neither a master address nor a slave address of a
|
||||
* master.
|
||||
*/
|
||||
unsigned char getSlaveAddress(unsigned char addr);
|
||||
|
||||
/**
|
||||
* Return the master address associated with the specified address (master or slave).
|
||||
* @param addr the address to check.
|
||||
* @return the master address, or SYN if the specified address is neither a master address nor a slave address of a master.
|
||||
* @return the master address, or SYN if the specified address is neither a master address nor a slave address of a
|
||||
* master.
|
||||
*/
|
||||
unsigned char getMasterAddress(unsigned char addr);
|
||||
|
||||
@@ -260,6 +274,6 @@ unsigned char getMasterNumber(unsigned char addr);
|
||||
*/
|
||||
bool isValidAddress(unsigned char addr, bool allowBroadcast = true);
|
||||
|
||||
} // namespace ebusd
|
||||
} // namespace ebusd
|
||||
|
||||
#endif // LIB_EBUS_SYMBOL_H_
|
||||
#endif // LIB_EBUS_SYMBOL_H_
|
||||
|
||||
@@ -59,7 +59,8 @@ int main() {
|
||||
{"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
|
||||
{"x,,str:10", "", "10fe07000a20202020202020202020", "00", "R"},
|
||||
{"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""},
|
||||
{"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778",
|
||||
"00", ""},
|
||||
{"x,,str:*", "abcde", "10fe0700056162636465", "00", ""},
|
||||
{"x,,str,2", "", "", "", "c"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"},
|
||||
@@ -73,7 +74,8 @@ int main() {
|
||||
{"x,,nts:10", "", "10fe07000a00000000000000000000", "00", ""},
|
||||
{"x,,nts:10", "abc", "10fe07000a6162630065666768696a", "00", "W"},
|
||||
{"x,,nts:11", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x,,nts:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""},
|
||||
{"x,,nts:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778",
|
||||
"00", ""},
|
||||
{"x,,nts:*", "abcde", "10fe0700056162636465", "00", "W"},
|
||||
{"x,,nts:*", "abcde", "10fe070006616263646500", "00", ""},
|
||||
{"x,,nts,2", "", "", "", "c"},
|
||||
@@ -86,9 +88,9 @@ int main() {
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "rW"},
|
||||
{"x,,hex:5,=48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,bda", "26.10.2014", "10fe07000426100614", "00", ""}, // Sunday
|
||||
{"x,,bda", "01.01.2000", "10fe07000401010500", "00", ""}, // Saturday
|
||||
{"x,,bda", "31.12.2099", "10fe07000431120399", "00", ""}, // Thursday
|
||||
{"x,,bda", "26.10.2014", "10fe07000426100614", "00", ""}, // Sunday
|
||||
{"x,,bda", "01.01.2000", "10fe07000401010500", "00", ""}, // Saturday
|
||||
{"x,,bda", "31.12.2099", "10fe07000431120399", "00", ""}, // Thursday
|
||||
{"x,,bda", "-.-.-", "10fe070004ffff00ff", "00", ""},
|
||||
{"x,,bda", "", "10fe07000432100014", "00", "rw"},
|
||||
{"x,,bda:3", "26.10.2014", "10fe070003261014", "00", ""},
|
||||
@@ -97,9 +99,9 @@ int main() {
|
||||
{"x,,bda:3", "-.-.-", "10fe070003ffffff", "00", ""},
|
||||
{"x,,bda:3", "", "10fe070003321299", "00", "rw"},
|
||||
{"x,,bda,2", "", "", "", "c"},
|
||||
{"x,,hda", "26.10.2014", "10fe0700041a0a070e", "00", ""}, // Sunday
|
||||
{"x,,hda", "01.01.2000", "10fe07000401010600", "00", ""}, // Saturday
|
||||
{"x,,hda", "31.12.2099", "10fe0700041f0c0463", "00", ""}, // Thursday
|
||||
{"x,,hda", "26.10.2014", "10fe0700041a0a070e", "00", ""}, // Sunday
|
||||
{"x,,hda", "01.01.2000", "10fe07000401010600", "00", ""}, // Saturday
|
||||
{"x,,hda", "31.12.2099", "10fe0700041f0c0463", "00", ""}, // Thursday
|
||||
{"x,,hda", "-.-.-", "10fe070004ffff00ff", "00", ""},
|
||||
{"x,,hda", "", "10fe070004200c0463", "00", "rw"},
|
||||
{"x,,hda:3", "26.10.2014", "10fe0700031a0a0e", "00", ""},
|
||||
@@ -301,7 +303,7 @@ int main() {
|
||||
{"uin10,uin,-10", "", "", "", "t"}, // template
|
||||
{"x,,uin10", "380", "10feffff022600", "00", ""}, // template reference
|
||||
{"x,,uin10,-10", "3800", "10feffff022600", "00", ""}, // template reference, valid divider product
|
||||
{"x,,uin10,10", "", "", "", "c"}, // template reference, invalid divider product
|
||||
{"x,,uin10,10", "", "", "", "c"}, // template reference, invalid divider product
|
||||
{"x,,sin", "-90", "10feffff02a6ff", "00", ""},
|
||||
{"x,,sin", "0", "10feffff020000", "00", ""},
|
||||
{"x,,sin", "-1", "10feffff02ffff", "00", ""},
|
||||
@@ -427,35 +429,43 @@ int main() {
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "x=on ja/nein [Wahrheitswert]", "10feffff0108", "00", "vvv"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "x=1 ja/nein [Wahrheitswert]", "10feffff0108", "00", "vvvn"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": \"on\"}", "10feffff0108", "00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108", "00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108", "00", "j"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": \"on\", \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00", "vvvj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108",
|
||||
"00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108",
|
||||
"00", "j"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert",
|
||||
"\n \"x\": {\"value\": \"on\", \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108",
|
||||
"00", "vvvj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": 1}", "10feffff0108", "00", "vnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": 1, \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00", "vvvnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"x\", \"value\": 1}", "10feffff0108", "00", "nj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert",
|
||||
"\n \"x\": {\"value\": 1, \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00",
|
||||
"vvvnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"x\", \"value\": 1}", "10feffff0108", "00",
|
||||
"nj"},
|
||||
{"x,,uch,1=test;2=high;3=off;0x10=on", "on", "10feffff0110", "00", ""},
|
||||
{"x,s,uch", "3", "1050ffff00", "0103", ""},
|
||||
{"x,,d2b,,°C,Aussentemperatur", "x=18.004 °C [Aussentemperatur]", "10fe0700090112", "00", "vvv"},
|
||||
{"x,,bti,,,,y,,bda,,,,z,,bdy", "21:04:58;26.10.2014;Sun", "10fe0700085804212610061406", "00", ""}, // combination
|
||||
{"x,,bi3,,,,y,,bi5", "1;0", "10feffff0108", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "1;1", "10feffff0128", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "0;1", "10feffff0120", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "0;0", "10feffff0100", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi7,,,,t,,uch", "0;0;9", "10feffff020009", "00", ""}, // bit combination
|
||||
{"x,,bi6:2,,,,y,,bi0:2,,,,t,,uch", "2;1;9", "10feffff03800109", "00", ""}, // bit combination
|
||||
{"x,,BI0;BI1;BI2;BI3;BI4;BI5;BI6;BI7", "0;0;1;0;0;0;0;0", "ff75b50900", "0104", ""}, // bits
|
||||
{"temp,d2b,,°C,Aussentemperatur", "", "", "", "t"}, // template with relative pos
|
||||
{"x,,temp", "18.004", "10fe0700020112", "00", ""}, // reference to template
|
||||
{"x,,temp,10", "1.8004", "10fe0700020112", "00", ""}, // reference to template, valid divider product
|
||||
{"x,,temp,-10", "", "", "", "c"}, // reference to template, invalid divider product
|
||||
{"x,,bti,,,,y,,bda,,,,z,,bdy", "21:04:58;26.10.2014;Sun", "10fe0700085804212610061406", "00", ""}, // combination
|
||||
{"x,,bi3,,,,y,,bi5", "1;0", "10feffff0108", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "1;1", "10feffff0128", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "0;1", "10feffff0120", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi5", "0;0", "10feffff0100", "00", ""}, // bit combination
|
||||
{"x,,bi3,,,,y,,bi7,,,,t,,uch", "0;0;9", "10feffff020009", "00", ""}, // bit combination
|
||||
{"x,,bi6:2,,,,y,,bi0:2,,,,t,,uch", "2;1;9", "10feffff03800109", "00", ""}, // bit combination
|
||||
{"x,,BI0;BI1;BI2;BI3;BI4;BI5;BI6;BI7", "0;0;1;0;0;0;0;0", "ff75b50900", "0104", ""}, // bits
|
||||
{"temp,d2b,,°C,Aussentemperatur", "", "", "", "t"}, // template with relative pos
|
||||
{"x,,temp", "18.004", "10fe0700020112", "00", ""}, // reference to template
|
||||
{"x,,temp,10", "1.8004", "10fe0700020112", "00", ""}, // reference to template, valid divider product
|
||||
{"x,,temp,-10", "", "", "", "c"}, // reference to template, invalid divider product
|
||||
{"relrel,d2b,,,,y,d1c", "", "", "", "t"}, // template struct with relative pos
|
||||
{"x,,relrel", "18.004;9.5", "10fe070003011213", "00", ""}, // reference to template struct
|
||||
{"x,,relrel", "18.004;9.5", "10fe070003011213", "00", ""}, // reference to template struct
|
||||
{"trelrel,temp;temp", "", "", "", "t"}, // template struct with relative pos and ref to templates
|
||||
{"x,,trelrel", "18.004;19.008", "10fe07000401120213", "00", ""}, // reference to template struct
|
||||
{"x,,temp,,,,y,,d1c", "18.004;9.5", "10fe070003011213", "00", ""}, // reference to template, normal def
|
||||
{"x,,temp;HEX:2", "18.004;13 14", "10fe07000401121314", "00", ""}, // reference to template and base type
|
||||
{"x,,temp;HEX:2", "temp=18.004;=13 14", "10fe07000401121314", "00", "v"}, // reference to template and base type
|
||||
{"x,,temp:degrees;HEX:2", "degrees=18.004;=13 14", "10fe07000401121314", "00", "v"}, // reference to template and base type
|
||||
{"x,,trelrel", "18.004;19.008", "10fe07000401120213", "00", ""}, // reference to template struct
|
||||
{"x,,temp,,,,y,,d1c", "18.004;9.5", "10fe070003011213", "00", ""}, // reference to template, normal def
|
||||
{"x,,temp;HEX:2", "18.004;13 14", "10fe07000401121314", "00", ""}, // reference to template and base type
|
||||
{"x,,temp;HEX:2", "temp=18.004;=13 14", "10fe07000401121314", "00", "v"}, // reference to template and base type
|
||||
// reference to template and base type
|
||||
{"x,,temp:degrees;HEX:2", "degrees=18.004;=13 14", "10fe07000401121314", "00", "v"},
|
||||
};
|
||||
DataFieldTemplates* templates = new DataFieldTemplates();
|
||||
DataField* fields = NULL;
|
||||
@@ -510,7 +520,8 @@ int main() {
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate, !isTemplate && (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate,
|
||||
!isTemplate && (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
|
||||
@@ -555,18 +566,21 @@ int main() {
|
||||
SymbolString writeMstr(false);
|
||||
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
SymbolString writeSstr(false);
|
||||
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(pt_masterData, mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, !output.str().empty());
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1,
|
||||
!output.str().empty());
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
@@ -607,7 +621,9 @@ int main() {
|
||||
error = true;
|
||||
} else {
|
||||
bool match = mstr == writeMstr && sstr == writeSstr;
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " " + sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
|
||||
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " "
|
||||
+ writeSstr.getDataStr(true, false));
|
||||
}
|
||||
}
|
||||
delete fields;
|
||||
|
||||
@@ -47,7 +47,7 @@ DataFieldTemplates* templates = NULL;
|
||||
|
||||
namespace ebusd {
|
||||
DataFieldTemplates* getTemplates(const string filename) {
|
||||
if (filename == "") { // avoid compiler warning
|
||||
if (filename == "") { // avoid compiler warning
|
||||
return templates;
|
||||
}
|
||||
return templates;
|
||||
@@ -73,13 +73,23 @@ int main() {
|
||||
{"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"},
|
||||
{"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"},
|
||||
{"tempsensorc,temp;sensorc,,Temperatursensor", "", "", "", "template"},
|
||||
{"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate", "28.0;24.0;4.938;35.0;41.0;4", "ff08b5110101", "093830f00446520400ff", "d"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00},\n \"sensor\": {\"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor", "\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate",
|
||||
"28.0;24.0;4.938;35.0;41.0;4", "ff08b5110101", "093830f00446520400ff", "d"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor",
|
||||
"temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"\n \"temp\": {\"value\": -14.00},\n \"sensor\": {\"value\": \"ok\"}", "ff25b509030d2800", "0320ff00",
|
||||
"mj"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n"
|
||||
" \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor",
|
||||
"temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor",
|
||||
"\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}",
|
||||
"ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,,name,,,25,B509,0d2800,,,tempsensorc", "-14.00", "ff25b509030d2800", "0320ff55", "m"},
|
||||
{"r,,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", "m"},
|
||||
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||
@@ -92,20 +102,27 @@ int main() {
|
||||
{"r,ehp,time,,,08;10,b509,0d2800,,,time", "", "", "", "c"},
|
||||
{"r,ehp,time,,,08;09,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md*"},
|
||||
{"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"},
|
||||
{"r,700,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"},
|
||||
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"},
|
||||
{"r,700,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f",
|
||||
"d"},
|
||||
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06",
|
||||
"d"},
|
||||
{"", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"},
|
||||
{"", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"},
|
||||
{"w,700,date,,,15,b524,020000003400,,,date", "23.11.2015", "ff15b52409020000003400170b0f", "00", "m"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "3;15:00:17", "ff08b509040d280003", "0311000f", "mdi"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f", "mD"},
|
||||
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f",
|
||||
"mD"},
|
||||
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00",
|
||||
"03ba0008", "pm"},
|
||||
{"uw,ehp,test,Test,,08,B5de,ab,,,power,,,,,s,hex:1", "8;39", "1008b5de02ab08", "0139", "pm"},
|
||||
{"u,ehp,hwTankTemp,Speichertemperatur IST,,25,B509,290000,,,IGN:2,,,,,,tempsensor", "", "", "", "M"},
|
||||
{"", "55.50;ok", "1025b50903290000", "050000780300", "d"},
|
||||
{"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2", "valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" },
|
||||
{"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2",
|
||||
"valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "",
|
||||
"", "", "c" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,",
|
||||
"", "", "", "c" },
|
||||
{"r,ehp,ApplianceCode,,,08,b509,0d4301,,,UCH,", "9", "ff08b509030d4301", "0109", "d" },
|
||||
{"r,ehp,,,,08,b509,0d", "", "", "", "defaults" },
|
||||
{"w,ehp,,,,08,b509,0e", "", "", "", "defaults" },
|
||||
@@ -113,22 +130,39 @@ int main() {
|
||||
{"[airtowater]r,ehp,notavailable,,,,,0100,,,uch", "1", "", "", "c" },
|
||||
{"[brinetowater]r,ehp,available,,,,,0100,,,uch", "1", "ff08b509030d0100", "0101", "d" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,,bit0=\"comment, continued comment", "", "", "", "c" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]", "ff08b509030d6800", "0101", "mD" },
|
||||
{"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" },
|
||||
{"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02", "084142434445464748;054b4c4d4e4f;02494a", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
|
||||
{"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8", "ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127", "09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509030d6900", "03138040", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509030d6900", "0313ffbf", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509030d6900", "03137fff", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509030d6900", "03137fbf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71", "ff08b509030d6900", "0213ff", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71", "ff08b509030d6900", "0213bf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70", "ff08b509030d6900", "02137f", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70", "ff08b509030d6900", "02133f", "md" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]",
|
||||
"ff08b509030d6800", "0101", "mD" },
|
||||
{"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" },
|
||||
{"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02",
|
||||
"084142434445464748;054b4c4d4e4f;02494a", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
|
||||
{"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8",
|
||||
"ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127",
|
||||
"09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61",
|
||||
"ff08b509030d6900", "03138040", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60",
|
||||
"ff08b509030d6900", "0313ffbf", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61",
|
||||
"ff08b509030d6900", "03137fff", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60",
|
||||
"ff08b509030d6900", "03137fbf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71",
|
||||
"ff08b509030d6900", "0213ff", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71",
|
||||
"ff08b509030d6900", "0213bf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70",
|
||||
"ff08b509030d6900", "02137f", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70",
|
||||
"ff08b509030d6900", "02133f", "md" },
|
||||
{"r,cir*cuit#level,na*me,com*ment,ff,75,b509,0d", "", "", "", "defaults" },
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH", "r,cirCIRCUITcuit#level,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42", "ff08b509030d0100", "012a", "mDN"},
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH",
|
||||
"r,cirCIRCUITcuit#level,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42",
|
||||
"ff08b509030d0100", "012a", "mDN"},
|
||||
};
|
||||
templates = new DataFieldTemplates();
|
||||
MessageMap* messages = new MessageMap();
|
||||
@@ -174,7 +208,8 @@ int main() {
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl;
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": template fields create error: trailing input "
|
||||
<< static_cast<unsigned>(entries.end()-it) << endl;
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": create template OK" << endl;
|
||||
result = templates->add(fields, "", true);
|
||||
@@ -195,7 +230,8 @@ int main() {
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl;
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": defaults read error: trailing input "
|
||||
<< static_cast<unsigned>(entries.end()-it) << endl;
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": read defaults OK" << endl;
|
||||
if (isCondition) {
|
||||
@@ -204,7 +240,8 @@ int main() {
|
||||
} else {
|
||||
result = messages->resolveConditions();
|
||||
if (result != RESULT_OK) {
|
||||
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl;
|
||||
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError()
|
||||
<< endl;
|
||||
} else {
|
||||
cout << " resolve conditions OK" << endl;
|
||||
}
|
||||
@@ -314,7 +351,8 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it)
|
||||
<< endl;
|
||||
continue;
|
||||
}
|
||||
if (multi && deleteMessages.size() == 1) {
|
||||
@@ -368,7 +406,8 @@ int main() {
|
||||
message->dump(output, NULL, true);
|
||||
output << ": ";
|
||||
}
|
||||
result = message->decodeLastData(output, (decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
|
||||
result = message->decodeLastData(output,
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
|
||||
<< getResultCode(result) << endl;
|
||||
@@ -399,7 +438,8 @@ int main() {
|
||||
cout << " \"" << inputStr << "\": prepare OK" << endl;
|
||||
|
||||
bool match = writeMstr == *mstrs[0];
|
||||
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false), writeMstr.getDataStr(true, false));
|
||||
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false),
|
||||
writeMstr.getDataStr(true, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
*/
|
||||
void clockGettime(struct timespec* t);
|
||||
|
||||
#endif // LIB_UTILS_CLOCK_H_
|
||||
#endif // LIB_UTILS_CLOCK_H_
|
||||
|
||||
@@ -71,7 +71,6 @@ bool setLogFacilities(const char* facilities) {
|
||||
newFacilites |= 1 << val;
|
||||
}
|
||||
}
|
||||
//s_lastFacilities = newFacilites;
|
||||
s_logFacilites = newFacilites;
|
||||
free(input);
|
||||
return true;
|
||||
@@ -81,7 +80,7 @@ bool getLogFacilities(char* buffer) {
|
||||
if (s_logFacilites == LF_ALL) {
|
||||
return snprintf(buffer, 48, "%s", facilityNames[lf_COUNT]) != 0;
|
||||
}
|
||||
*buffer = 0; // for strcat to work
|
||||
*buffer = 0; // for strcat to work
|
||||
bool found = false;
|
||||
size_t len = 0;
|
||||
for (int val = 0; val < lf_COUNT; val++) {
|
||||
|
||||
+11
-7
@@ -36,12 +36,12 @@ enum LogFacility {
|
||||
|
||||
/** the available log levels. */
|
||||
enum LogLevel {
|
||||
ll_none = 0, //!< no level at all
|
||||
ll_none = 0, //!< no level at all
|
||||
ll_error, //!< error message
|
||||
ll_notice, //!< important message
|
||||
ll_info, //!< informational message
|
||||
ll_debug, //!< debugging message (normally suppressed)
|
||||
ll_COUNT = 5 //!< number of available log levels
|
||||
ll_COUNT = 5 //!< number of available log levels
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,15 +125,19 @@ void logWrite(const char* facility, const LogLevel level, const char* message, .
|
||||
#define logDebug(facility, ...) (needsLog(facility, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for an error message that calls the logging function only if needed. */
|
||||
#define logOtherError(facility, ...) (needsLog(lf_other, ll_error) ? logWrite(facility, ll_error, __VA_ARGS__) : void(0))
|
||||
#define logOtherError(facility, ...) \
|
||||
(needsLog(lf_other, ll_error) ? logWrite(facility, ll_error, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for a notice message that calls the logging function only if needed. */
|
||||
#define logOtherNotice(facility, ...) (needsLog(lf_other, ll_notice) ? logWrite(facility, ll_notice, __VA_ARGS__) : void(0))
|
||||
#define logOtherNotice(facility, ...) \
|
||||
(needsLog(lf_other, ll_notice) ? logWrite(facility, ll_notice, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for an info message that calls the logging function only if needed. */
|
||||
#define logOtherInfo(facility, ...) (needsLog(lf_other, ll_info) ? logWrite(facility, ll_info, __VA_ARGS__) : void(0))
|
||||
#define logOtherInfo(facility, ...) \
|
||||
(needsLog(lf_other, ll_info) ? logWrite(facility, ll_info, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for a debug message that calls the logging function only if needed. */
|
||||
#define logOtherDebug(facility, ...) (needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
#define logOtherDebug(facility, ...) \
|
||||
(needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
|
||||
#endif // LIB_UTILS_LOG_H_
|
||||
#endif // LIB_UTILS_LOG_H_
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
* class to notify other thread per pipe.
|
||||
*/
|
||||
class Notify {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* constructs a new instance and do notifying.
|
||||
*/
|
||||
@@ -61,7 +61,7 @@ class Notify {
|
||||
*/
|
||||
int notify() const { return write(m_sendfd, "1", 1); }
|
||||
|
||||
private:
|
||||
private:
|
||||
/** file descriptor to watch */
|
||||
int m_recvfd;
|
||||
|
||||
@@ -69,6 +69,6 @@ class Notify {
|
||||
int m_sendfd;
|
||||
};
|
||||
|
||||
#endif // LIB_UTILS_NOTIFY_H_
|
||||
#endif // LIB_UTILS_NOTIFY_H_
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ using std::list;
|
||||
*/
|
||||
template <typename T>
|
||||
class Queue {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
@@ -52,7 +52,7 @@ class Queue {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* Hidden copy constructor.
|
||||
* @param src the object to copy from.
|
||||
@@ -60,7 +60,7 @@ class Queue {
|
||||
Queue(const Queue& src);
|
||||
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Add an item to the end of queue.
|
||||
* @param item the item to add.
|
||||
@@ -141,7 +141,7 @@ class Queue {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the queue itself */
|
||||
list<T> m_queue;
|
||||
|
||||
@@ -152,4 +152,4 @@ class Queue {
|
||||
pthread_cond_t m_cond;
|
||||
};
|
||||
|
||||
#endif // LIB_UTILS_QUEUE_H_
|
||||
#endif // LIB_UTILS_QUEUE_H_
|
||||
|
||||
@@ -35,7 +35,7 @@ using std::string;
|
||||
* Helper class for writing to a rotating file with maximum size.
|
||||
*/
|
||||
class RotateFile {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param fileName the name of the file write to.
|
||||
@@ -72,7 +72,7 @@ class RotateFile {
|
||||
void write(unsigned char* value, unsigned int size, bool received = true);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** whether writing to the file is enabled. */
|
||||
bool m_enabled;
|
||||
|
||||
@@ -92,5 +92,5 @@ class RotateFile {
|
||||
uint64_t m_fileSize;
|
||||
};
|
||||
|
||||
#endif // LIB_UTILS_ROTATEFILE_H_
|
||||
#endif // LIB_UTILS_ROTATEFILE_H_
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ using std::string;
|
||||
* class for low level tcp socket operations. (open, close, send, receive).
|
||||
*/
|
||||
class TCPSocket {
|
||||
public:
|
||||
public:
|
||||
/** grant access for friend class TCPClient */
|
||||
friend class TCPClient;
|
||||
|
||||
@@ -91,7 +91,7 @@ class TCPSocket {
|
||||
bool isValid();
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** file descriptor from tcp socket */
|
||||
int m_sfd;
|
||||
|
||||
@@ -113,7 +113,7 @@ class TCPSocket {
|
||||
* class to initiate a tcp socket connection to a listening server.
|
||||
*/
|
||||
class TCPClient {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* initiate a tcp socket connection to a listening server.
|
||||
* @param server the server name or ip address to connect.
|
||||
@@ -127,7 +127,7 @@ class TCPClient {
|
||||
* class for a tcp based network server.
|
||||
*/
|
||||
class TCPServer {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* creates a new instance of a listening tcp server.
|
||||
* @param port the tcp port.
|
||||
@@ -160,7 +160,7 @@ class TCPServer {
|
||||
int getFD() const { return m_lfd; }
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** file descriptor from listening tcp socket */
|
||||
int m_lfd;
|
||||
|
||||
@@ -174,5 +174,5 @@ class TCPServer {
|
||||
bool m_listening;
|
||||
};
|
||||
|
||||
#endif // LIB_UTILS_TCPSOCKET_H_
|
||||
#endif // LIB_UTILS_TCPSOCKET_H_
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
* wrapper class for pthread.
|
||||
*/
|
||||
class Thread {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* constructor.
|
||||
*/
|
||||
@@ -76,14 +76,14 @@ class Thread {
|
||||
pthread_t self() { return m_threadid; }
|
||||
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/**
|
||||
* Thread entry method to be overridden by derived class.
|
||||
*/
|
||||
virtual void run() = 0;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* Enter the Thread loop by calling run().
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ class Thread {
|
||||
* A @a Thread that can be waited on.
|
||||
*/
|
||||
class WaitThread : public Thread {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
@@ -132,7 +132,7 @@ class WaitThread : public Thread {
|
||||
bool Wait(int seconds);
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
/** the mutex for waiting. */
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
@@ -140,4 +140,4 @@ class WaitThread : public Thread {
|
||||
pthread_cond_t m_cond;
|
||||
};
|
||||
|
||||
#endif // LIB_UTILS_THREAD_H_
|
||||
#endif // LIB_UTILS_THREAD_H_
|
||||
|
||||
Reference in New Issue
Block a user