code style

This commit is contained in:
john30
2017-01-14 19:00:47 +01:00
parent ebcb260d5f
commit 5bf2f124b3
42 changed files with 1347 additions and 1066 deletions
+1 -1
View File
@@ -26,4 +26,4 @@ bool libebus_contrib_register() {
return true;
}
} // namespace ebusd
} // namespace ebusd
+2 -2
View File
@@ -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_
+17 -17
View File
@@ -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
+3 -3
View File
@@ -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_
+8 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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_
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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_
+1 -1
View File
@@ -58,4 +58,4 @@ const char* getResultCode(result_t resultCode) {
}
}
} // namespace ebusd
} // namespace ebusd
+8 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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_
+53 -37
View File
@@ -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;
+76 -36
View File
@@ -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));
}
}
+1 -1
View File
@@ -29,4 +29,4 @@
*/
void clockGettime(struct timespec* t);
#endif // LIB_UTILS_CLOCK_H_
#endif // LIB_UTILS_CLOCK_H_
+1 -2
View File
@@ -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
View File
@@ -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_
+3 -3
View File
@@ -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_
+5 -5
View File
@@ -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_
+3 -3
View File
@@ -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_
+6 -6
View File
@@ -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_
+6 -6
View File
@@ -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_