removed absolute positions, fix for part def

This commit is contained in:
john30
2014-11-22 13:36:01 +01:00
parent 60f29cecd4
commit 2317bd206f
3 changed files with 195 additions and 224 deletions
Regular → Executable
+95 -106
View File
@@ -132,13 +132,13 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
std::string unit, comment; std::string unit, comment;
PartType partType; PartType partType;
unsigned int divisor = 0; unsigned int divisor = 0;
unsigned char offset, length, offsetCnt = 0; unsigned char length;
const bool isTemplate = dstAddress == SYN; const bool isTemplate = dstAddress == SYN;
std::string token; std::string token;
if (it == end) if (it == end)
break; break;
// name;[pos];type[;[divisor|values][;[unit][;[comment]]]] // name;[m|s][len];type[;[divisor|values][;[unit][;[comment]]]]
const std::string name = *it++; const std::string name = *it++;
if (it == end) if (it == end)
break; break;
@@ -152,13 +152,13 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
firstComment = comment; firstComment = comment;
} }
if (dstAddress == BROADCAST || isMaster(dstAddress) if (dstAddress == BROADCAST || isMaster(dstAddress)
|| (isTemplate == false && isSetMessage == true && posStr[0] != 0 && posStr[0] <= '9') || (isTemplate == false && isSetMessage == true && (posStr[0] == 0 || posStr[0] <= '9'))
|| posStr[0] == 'm') { // master data || posStr[0] == 'm') { // master data
partType = pt_masterData; partType = pt_masterData;
if (posStr[0] == 'm') if (posStr[0] == 'm')
posStr++; posStr++;
} }
else if ((isTemplate == false && isSetMessage == false && posStr[0] != 0 && posStr[0] <= '9') else if ((isTemplate == false && isSetMessage == false && (posStr[0] == 0 || posStr[0] <= '9'))
|| posStr[0] == 's') { // slave data || posStr[0] == 's') { // slave data
partType = pt_slaveData; partType = pt_slaveData;
if (posStr[0] == 's') if (posStr[0] == 's')
@@ -173,33 +173,10 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
} }
if (posStr[0] == 0) { if (posStr[0] == 0) {
if (fields.empty() == false)
offset = fields.back()->getNextOffset(partType);
else
offset = 0;
length = 0; length = 0;
} }
else { else {
offset = 0; length = parseInt(posStr, 10, 1, MAX_POS, result);
length = 0;
std::istringstream stream(posStr);
while (std::getline(stream, token, '-') != 0) {
if (++offsetCnt > 2)
return RESULT_ERR_INVALID_ARG; //invalid pos definition
unsigned int pos = parseInt(token.c_str(), 10, 1, MAX_POS + 1, result) - 1; // input is 1-based
if (result != RESULT_OK)
break;
if (offsetCnt == 1)
offset = pos;
else if (pos >= offset)
length = pos + 1 - offset;
else { // wrong order e.g. 4-3
length = offset - (pos + 1);
offset = pos;
}
}
if (result != RESULT_OK) if (result != RESULT_OK)
break; break;
} }
@@ -271,14 +248,9 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
break; break;
} }
found = true; found = true;
result = ref->second->derive(name, comment, unit, partType, offset, divisor, values, fields); result = ref->second->derive(name, comment, unit, partType, divisor, values, fields);
if (result != RESULT_OK) if (result != RESULT_OK)
break; break;
offset = fields.back()->getNextOffset(partType);
}
if (offset > MAX_POS) {
result = RESULT_ERR_INVALID_ARG; // invalid pos definition
break;
} }
if (found == true || result != RESULT_OK) if (found == true || result != RESULT_OK)
break; break;
@@ -301,10 +273,6 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
useLength = numBytes; useLength = numBytes;
else if (useLength != numBytes) else if (useLength != numBytes)
continue; // check for another one with same name but different length continue; // check for another one with same name but different length
if (offset + useLength > MAX_POS) {
result = RESULT_ERR_INVALID_ARG; // invalid pos definition
break;
}
switch (dataType.type) switch (dataType.type)
{ {
@@ -312,7 +280,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
case bt_hexstr: case bt_hexstr:
case bt_dat: case bt_dat:
case bt_tim: case bt_tim:
add = new StringDataField(name, comment, unit, dataType, partType, offset, useLength); add = new StringDataField(name, comment, unit, dataType, partType, useLength);
break; break;
case bt_num: case bt_num:
if (values.empty() == true && (dataType.flags & DAY) != 0) { if (values.empty() == true && (dataType.flags & DAY) != 0) {
@@ -326,7 +294,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
else else
divisor *= dataType.divisor; divisor *= dataType.divisor;
add = new NumberDataField(name, comment, unit, dataType, partType, offset, useLength, divisor); add = new NumberDataField(name, comment, unit, dataType, partType, useLength, divisor);
break; break;
} }
if (values.begin()->first < dataType.minValueOrLength if (values.begin()->first < dataType.minValueOrLength
@@ -335,7 +303,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
break; break;
} }
add = new ValueListDataField(name, comment, unit, dataType, partType, offset, useLength, values); add = new ValueListDataField(name, comment, unit, dataType, partType, useLength, values);
break; break;
} }
} }
@@ -362,31 +330,26 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
} }
unsigned char SingleDataField::getNextOffset(PartType partType) bool SingleDataField::hasFullByteOffset()
{ {
if (partType != pt_any && partType != m_partType) return m_length > 1 || (m_dataType.numBits % 8) == 0
return 0; || m_dataType.precisionOrFirstBit + (m_dataType.numBits % 8) >= 8;
unsigned char offset = m_offset + m_length;
if ((m_dataType.numBits % 8) != 0
&& m_dataType.precisionOrFirstBit + (m_dataType.numBits % 8) < 8)
offset--; // not all bits of last offset fully consumed
return offset;
} }
result_t SingleDataField::read(SymbolString& masterData, SymbolString& slaveData, result_t SingleDataField::read(SymbolString& masterData, unsigned char masterOffset,
std::ostringstream& output, bool verbose, char separator) SymbolString& slaveData, unsigned char slaveOffset,
std::ostringstream& output,
bool verbose, char separator)
{ {
SymbolString& input = m_partType == pt_masterData ? masterData : slaveData; SymbolString& input = m_partType == pt_masterData ? masterData : slaveData;
unsigned char baseOffset; unsigned char offset;
switch (m_partType) switch (m_partType)
{ {
case pt_masterData: case pt_masterData:
baseOffset = 5; // skip QQ ZZ PB SB NN offset = 5 + masterOffset; // skip QQ ZZ PB SB NN
break; break;
case pt_slaveData: case pt_slaveData:
baseOffset = 1; // skip NN offset = 1 + slaveOffset; // skip NN
break; break;
default: default:
return RESULT_ERR_INVALID_ARG; // invalid part type return RESULT_ERR_INVALID_ARG; // invalid part type
@@ -395,7 +358,7 @@ result_t SingleDataField::read(SymbolString& masterData, SymbolString& slaveData
if (verbose) if (verbose)
output << m_name << "="; output << m_name << "=";
result_t result = readSymbols(input, baseOffset, output); result_t result = readSymbols(input, offset, output);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
@@ -407,28 +370,30 @@ result_t SingleDataField::read(SymbolString& masterData, SymbolString& slaveData
return RESULT_OK; return RESULT_OK;
} }
result_t SingleDataField::write(std::istringstream& input, SymbolString& masterData, result_t SingleDataField::write(std::istringstream& input,
SymbolString& slaveData, char separator) SymbolString& masterData, unsigned char masterOffset,
SymbolString& slaveData, unsigned char slaveOffset,
char separator)
{ {
SymbolString& output = m_partType == pt_masterData ? masterData : slaveData; SymbolString& output = m_partType == pt_masterData ? masterData : slaveData;
unsigned char baseOffset; unsigned char offset;
switch (m_partType) switch (m_partType)
{ {
case pt_masterData: case pt_masterData:
baseOffset = 5; // skip QQ ZZ PB SB NN offset = 5 + masterOffset; // skip QQ ZZ PB SB NN
break; break;
case pt_slaveData: case pt_slaveData:
baseOffset = 1; // skip NN offset = 1 + slaveOffset; // skip NN
break; break;
default: default:
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
return writeSymbols(input, baseOffset, output); return writeSymbols(input, offset, output);
} }
result_t StringDataField::derive(std::string name, std::string comment, result_t StringDataField::derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields) std::vector<SingleDataField*>& fields)
{ {
@@ -442,9 +407,8 @@ result_t StringDataField::derive(std::string name, std::string comment,
comment = m_comment; comment = m_comment;
if (unit.empty() == true) if (unit.empty() == true)
unit = m_unit; unit = m_unit;
offset += m_offset;
fields.push_back(new StringDataField(name, comment, unit, m_dataType, partType, offset, m_length)); fields.push_back(new StringDataField(name, comment, unit, m_dataType, partType, m_length));
return RESULT_OK; return RESULT_OK;
} }
@@ -452,20 +416,19 @@ result_t StringDataField::derive(std::string name, std::string comment,
result_t StringDataField::readSymbols(SymbolString& input, result_t StringDataField::readSymbols(SymbolString& input,
unsigned char baseOffset, std::ostringstream& output) unsigned char baseOffset, std::ostringstream& output)
{ {
size_t start = m_offset, end = m_offset + m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
unsigned char ch, last = 0; unsigned char ch, last = 0;
if (baseOffset + end > input.size()) { if (baseOffset + m_length > input.size()) {
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
end = start - 1; start = m_length - 1;
start = m_offset + m_length - 1;
incr = -1; incr = -1;
} }
for (size_t offset = start, i = 0; offset != end; offset += incr, i++) { for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
if (m_length == 4 && i == 2 && m_dataType.type == bt_dat) if (m_length == 4 && i == 2 && m_dataType.type == bt_dat)
continue; // skip weekday in between continue; // skip weekday in between
ch = input[baseOffset + offset]; ch = input[baseOffset + offset];
@@ -495,6 +458,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
if (i == 0) { if (i == 0) {
ch /= 6; // hours ch /= 6; // hours
offset -= incr; // repeat for minutes offset -= incr; // repeat for minutes
count++;
} }
else else
ch = (ch % 6) * 10; // minutes ch = (ch % 6) * 10; // minutes
@@ -520,20 +484,19 @@ result_t StringDataField::readSymbols(SymbolString& input,
result_t StringDataField::writeSymbols(std::istringstream& input, result_t StringDataField::writeSymbols(std::istringstream& input,
unsigned char baseOffset, SymbolString& output) unsigned char baseOffset, SymbolString& output)
{ {
size_t start = m_offset, end = m_offset + m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
unsigned long int value = 0, last = 0; unsigned long int value = 0, last = 0;
std::string token; std::string token;
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
end = start - 1; start = m_length - 1;
start = m_offset + m_length - 1;
incr = -1; incr = -1;
} }
result_t result; result_t result;
size_t i = 0; size_t i = 0;
for (size_t offset = start; offset != end; offset += incr, i++) { for (size_t offset = start; i < count; offset += incr, i++) {
switch (m_dataType.type) switch (m_dataType.type)
{ {
case bt_hexstr: case bt_hexstr:
@@ -578,8 +541,9 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
return RESULT_ERR_INVALID_ARG; // invalid time part return RESULT_ERR_INVALID_ARG; // invalid time part
if (m_length == 1) { // truncated time if (m_length == 1) { // truncated time
if (i == 0) { if (i == 0) {
offset -= incr; // repeat for minutes
last = value; last = value;
offset -= incr; // repeat for minutes
count++;
continue; continue;
} }
if ((value % 10) != 0) if ((value % 10) != 0)
@@ -620,21 +584,20 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
result_t NumericDataField::readRawValue(SymbolString& input, result_t NumericDataField::readRawValue(SymbolString& input,
unsigned char baseOffset, unsigned int& value) unsigned char baseOffset, unsigned int& value)
{ {
size_t start = m_offset, end = m_offset + m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
unsigned char ch; unsigned char ch;
if (baseOffset + end > input.size()) if (baseOffset + m_length > input.size())
return RESULT_ERR_INVALID_ARG; // not enough data available return RESULT_ERR_INVALID_ARG; // not enough data available
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
end = start - 1; start = m_length - 1;
start = m_offset + m_length - 1;
incr = -1; incr = -1;
} }
value = 0; value = 0;
for (size_t offset = start, exp = 1; offset != end; offset += incr) { for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) {
ch = input[baseOffset + offset]; ch = input[baseOffset + offset];
if ((m_dataType.flags & BCD) != 0) { if ((m_dataType.flags & BCD) != 0) {
if (ch == m_dataType.replacement) { if (ch == m_dataType.replacement) {
@@ -665,13 +628,12 @@ result_t NumericDataField::readRawValue(SymbolString& input,
result_t NumericDataField::writeRawValue(unsigned int value, result_t NumericDataField::writeRawValue(unsigned int value,
unsigned char baseOffset, SymbolString& output) unsigned char baseOffset, SymbolString& output)
{ {
size_t start = m_offset, end = m_offset + m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
unsigned char ch; unsigned char ch;
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
end = start - 1; start = m_length - 1;
start = m_offset + m_length - 1;
incr = -1; incr = -1;
} }
@@ -680,7 +642,7 @@ result_t NumericDataField::writeRawValue(unsigned int value,
value &= (1 << m_dataType.numBits) - 1; value &= (1 << m_dataType.numBits) - 1;
value <<= m_bitOffset; value <<= m_bitOffset;
} }
for (size_t offset = start, exp = 1; offset != end; offset += incr) { for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) {
if ((m_dataType.flags & BCD) != 0) { if ((m_dataType.flags & BCD) != 0) {
if (value == m_dataType.replacement) if (value == m_dataType.replacement)
ch = m_dataType.replacement; ch = m_dataType.replacement;
@@ -705,7 +667,7 @@ result_t NumericDataField::writeRawValue(unsigned int value,
result_t NumberDataField::derive(std::string name, std::string comment, result_t NumberDataField::derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields) std::vector<SingleDataField*>& fields)
{ {
@@ -717,7 +679,6 @@ result_t NumberDataField::derive(std::string name, std::string comment,
comment = m_comment; comment = m_comment;
if (unit.empty() == true) if (unit.empty() == true)
unit = m_unit; unit = m_unit;
offset += m_offset;
if (divisor == 0) if (divisor == 0)
divisor = m_divisor; divisor = m_divisor;
else else
@@ -726,10 +687,10 @@ result_t NumberDataField::derive(std::string name, std::string comment,
if (divisor != 1) if (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
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, offset, m_length, values)); fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, values));
} }
else else
fields.push_back(new NumberDataField(name, comment, unit, m_dataType, partType, offset, m_length, divisor)); fields.push_back(new NumberDataField(name, comment, unit, m_dataType, partType, m_length, divisor));
return RESULT_OK; return RESULT_OK;
} }
@@ -839,7 +800,7 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
result_t ValueListDataField::derive(std::string name, std::string comment, result_t ValueListDataField::derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields) std::vector<SingleDataField*>& fields)
{ {
@@ -851,7 +812,6 @@ result_t ValueListDataField::derive(std::string name, std::string comment,
comment = m_comment; comment = m_comment;
if (unit.empty() == true) if (unit.empty() == true)
unit = m_unit; unit = m_unit;
offset += m_offset;
if (divisor != 0 && divisor != 1) 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
@@ -863,7 +823,7 @@ result_t ValueListDataField::derive(std::string name, std::string comment,
else else
values = m_values; values = m_values;
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, offset, m_length, values)); fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, values));
return RESULT_OK; return RESULT_OK;
} }
@@ -914,21 +874,27 @@ DataFieldSet::~DataFieldSet()
} }
} }
unsigned char DataFieldSet::getNextOffset(PartType partType) unsigned char DataFieldSet::getLength(PartType partType)
{ {
return 0; unsigned char length = 0;
for (std::vector<SingleDataField*>::reverse_iterator it = m_fields.rbegin(); it < m_fields.rend(); it++) { bool previousFullByteOffset[] = { true, true, true };
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (partType == pt_any || partType == field->getPartType()) if (field->getPartType() == partType) {
return field->getNextOffset(partType); length += field->getLength(partType);
if (previousFullByteOffset[partType] == false) {
length--;
}
previousFullByteOffset[partType] = field->hasFullByteOffset();
}
} }
return 0; return length;
} }
result_t DataFieldSet::derive(std::string name, std::string comment, result_t DataFieldSet::derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields) std::vector<SingleDataField*>& fields)
{ {
@@ -936,7 +902,7 @@ result_t DataFieldSet::derive(std::string name, std::string comment,
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
result_t result = (*it)->derive("", "", "", partType, offset, divisor, values, fields); result_t result = (*it)->derive("", "", "", partType, divisor, values, fields);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
} }
@@ -944,23 +910,34 @@ result_t DataFieldSet::derive(std::string name, std::string comment,
return RESULT_OK; return RESULT_OK;
} }
result_t DataFieldSet::read(SymbolString& masterData, SymbolString& slaveData, std::ostringstream& output, result_t DataFieldSet::read(SymbolString& masterData, unsigned char masterOffset,
bool verbose, char separator) SymbolString& slaveData, unsigned char slaveOffset,
std::ostringstream& output, bool verbose, char separator)
{ {
if (verbose) if (verbose)
output << m_name << "={ "; output << m_name << "={ ";
bool first = true; bool first = true;
unsigned char offsets[] = { 0, masterOffset, slaveOffset };
bool previousFullByteOffset[] = { true, true, true };
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
if (first) if (first)
first = false; first = false;
else else
output << separator; output << separator;
result_t result = (*it)->read(masterData, slaveData, output, verbose); SingleDataField* field = *it;
PartType partType = field->getPartType();
if (previousFullByteOffset[partType] == false) {
offsets[partType]--;
}
result_t result = field->read(masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], output, verbose, separator);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
offsets[partType] += field->getLength(partType);
previousFullByteOffset[partType] = field->hasFullByteOffset();
} }
if (verbose) { if (verbose) {
@@ -972,24 +949,36 @@ result_t DataFieldSet::read(SymbolString& masterData, SymbolString& slaveData, s
return RESULT_OK; return RESULT_OK;
} }
result_t DataFieldSet::write(std::istringstream& input, SymbolString& masterData, SymbolString& slaveData, result_t DataFieldSet::write(std::istringstream& input,
SymbolString& masterData, unsigned char masterOffset,
SymbolString& slaveData, unsigned char slaveOffset,
char separator) char separator)
{ {
std::string token; std::string token;
unsigned char offsets[] = { 0, masterOffset, slaveOffset };
bool previousFullByteOffset[] = { true, true, true };
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it;
PartType partType = field->getPartType();
if (previousFullByteOffset[partType] == false) {
offsets[partType]--;
}
result_t result; result_t result;
if (m_fields.size() > 1) { if (m_fields.size() > 1) {
if (std::getline(input, token, separator) == 0) if (std::getline(input, token, separator) == 0)
return RESULT_ERR_INVALID_ARG; // incomplete return RESULT_ERR_INVALID_ARG; // incomplete
std::istringstream single(token); std::istringstream single(token);
result = (*it)->write(single, masterData, slaveData); result = (*it)->write(single, masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], separator);
} }
else else
result = (*it)->write(input, masterData, slaveData); result = (*it)->write(input, masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], separator);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
offsets[partType] += field->getLength(partType);
previousFullByteOffset[partType] = field->hasFullByteOffset();
} }
return RESULT_OK; return RESULT_OK;
+80 -78
View File
@@ -28,7 +28,7 @@
/** the message part in which a data field is stored. */ /** the message part in which a data field is stored. */
enum PartType { enum PartType {
pt_any, // stored in any data (master or slave, relative offset) pt_any, // stored in any data (master or slave)
pt_masterData, // stored in master data pt_masterData, // stored in master data
pt_slaveData, // stored in slave data pt_slaveData, // stored in slave data
}; };
@@ -53,7 +53,7 @@ const unsigned int DAY = 0x20; // forced value list defaulting to week days
/** the structure for defining field types with their properties. */ /** the structure for defining field types with their properties. */
typedef struct { typedef struct {
const char* name; // field identifier const char* name; // field identifier
const unsigned int numBits; // number of bits (maximum length if @a ADJ flag is set, must be multiple of 8 with flag BCD) const unsigned int numBits; // number of bits (maximum length if @a ADJ flag is set, must be multiple of 8 with flag @a BCD)
const BaseType type; // base data type const BaseType type; // base data type
const unsigned int flags; // flags (e.g. @a BCD) const unsigned int flags; // flags (e.g. @a BCD)
const unsigned int replacement; // replacement value (fill-up value for @a bt_str / @a bt_hexstr, no replacement if equal to @a minValueOrLength for @a bt_num) const unsigned int replacement; // replacement value (fill-up value for @a bt_str / @a bt_hexstr, no replacement if equal to @a minValueOrLength for @a bt_num)
@@ -111,24 +111,23 @@ public:
const std::map<std::string, DataField*> templates, DataField*& returnField, const std::map<std::string, DataField*> templates, DataField*& returnField,
const bool isSetMessage=false, const unsigned char dstAddress=SYN); const bool isSetMessage=false, const unsigned char dstAddress=SYN);
/** /**
* @brief Returns the offset to the first symbol in the message part for a field following this field. * @brief Returns the length of this field (or contained fields) in bytes.
* @param partType the message part for which to get the offset, or @a pt_any for any. * @param partType the message part of the contained fields to limit the length calculation to.
* @return the offset to the first symbol in the message part for a field following this field. * @return the length of this field (or contained fields) in bytes.
*/ */
virtual unsigned char getNextOffset(PartType partType=pt_any) = 0; virtual unsigned char getLength(PartType partType) = 0;
/** /**
* @brief Derives a new DataField from this field. * @brief Derives a new DataField from this field.
* @param name the field name. * @param name the field name.
* @param comment the field comment, or empty to use this fields comment. * @param comment the field comment, or empty to use this fields comment.
* @param unit the value unit, or empty to use this fields unit (if applicable). * @param unit the value unit, or empty to use this fields unit (if applicable).
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the (additional) offset to the first symbol in the message part in which the field is stored.
* @param divisor the extra divisor to apply on the value, or 1 for none (if applicable). * @param divisor the extra divisor to apply on the value, or 1 for none (if applicable).
* @param values the value=text assignments, or empty to use this fields assignments (if applicable). * @param values the value=text assignments, or empty to use this fields assignments (if applicable).
* @param fields the @a std::vector to which created @a SingleDataField instances shall be added. * @param fields the @a std::vector to which created @a SingleDataField instances shall be added.
*/ */
virtual result_t derive(std::string name, std::string comment, virtual result_t derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields) = 0; std::vector<SingleDataField*>& fields) = 0;
/** /**
@@ -151,7 +150,9 @@ public:
* @param separator the separator character between multiple fields. * @param separator the separator character between multiple fields.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t read(SymbolString& masterData, SymbolString& slaveData, std::ostringstream& output, virtual result_t read(SymbolString& masterData, unsigned char masterOffset,
SymbolString& slaveData, unsigned char slaveOffset,
std::ostringstream& output,
bool verbose=false, char separator=';') = 0; bool verbose=false, char separator=';') = 0;
/** /**
* @brief Writes the value to the master or slave @a SymbolString. * @brief Writes the value to the master or slave @a SymbolString.
@@ -161,7 +162,9 @@ public:
* @param separator the separator character between multiple fields. * @param separator the separator character between multiple fields.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t write(std::istringstream& input, SymbolString& masterData, SymbolString& slaveData, virtual result_t write(std::istringstream& input,
SymbolString& masterData, unsigned char masterOffset,
SymbolString& slaveData, unsigned char slaveOffset,
char separator=';') = 0; char separator=';') = 0;
protected: protected:
@@ -188,15 +191,14 @@ public:
* @param unit the value unit. * @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the offset to the first symbol in the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
*/ */
SingleDataField(const std::string name, const std::string comment, SingleDataField(const std::string name, const std::string comment,
const std::string unit, const dataType_t dataType, const PartType partType, const std::string unit, const dataType_t dataType, const PartType partType,
const unsigned char offset, const unsigned char length) const unsigned char length)
: DataField(name, comment), : DataField(name, comment),
m_unit(unit), m_dataType(dataType), m_partType(partType), m_unit(unit), m_dataType(dataType), m_partType(partType),
m_offset(offset), m_length(length) {} m_length(length) {}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
@@ -212,44 +214,61 @@ public:
*/ */
PartType getPartType() const { return m_partType; } PartType getPartType() const { return m_partType; }
// @copydoc // @copydoc
virtual unsigned char getNextOffset(PartType partType=pt_any); virtual unsigned char getLength(PartType partType) { return partType == m_partType ? m_length : 0; };
// re-use same position as previous field as not all bits of fully consumed yet
/**
* @brief Get whether this field uses a full byte offset.
* @return true if this field uses a full byte offset, false if this field
* only consumes a part of a byte and a subsequent field may re-use the same offset.
*/
bool hasFullByteOffset();
/** /**
* @brief Reads the value from the master or slave @a SymbolString. * @brief Reads the value from the master or slave @a SymbolString.
* @param masterData the unescaped master data @a SymbolString for reading binary data. * @param masterData the unescaped master data @a SymbolString for reading binary data.
* @param masterOffset the extra offset for reading master data.
* @param slaveData the unescaped slave data @a SymbolString for reading binary data. * @param slaveData the unescaped slave data @a SymbolString for reading binary data.
* @param slaveOffset the extra offset for reading slave data.
* @param output the ostringstream to append the formatted value to. * @param output the ostringstream to append the formatted value to.
* @param verbose whether to prepend the name, append the unit (if present), and append * @param verbose whether to prepend the name, append the unit (if present), and append
* the comment in square brackets (if present). * the comment in square brackets (if present).
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t read(SymbolString& masterData, SymbolString& slaveData, std::ostringstream& output, virtual result_t read(SymbolString& masterData, unsigned char masterOffset,
bool verbose=false, char separator=';'); SymbolString& slaveData, unsigned char slaveOffset,
std::ostringstream& output,
bool verbose, char separator);
/** /**
* @brief Writes the value to the master or slave @a SymbolString. * @brief Writes the value to the master or slave @a SymbolString.
* @param input the @a std::istringstream to parse the formatted value from. * @param input the @a std::istringstream to parse the formatted value from.
* @param masterData the unescaped master data @a SymbolString for writing binary data. * @param masterData the unescaped master data @a SymbolString for writing binary data.
* @param masterOffset the extra offset for writing master data.
* @param slaveData the unescaped slave data @a SymbolString for writing binary data. * @param slaveData the unescaped slave data @a SymbolString for writing binary data.
* @param slaveOffset the extra offset for writing slave data.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t write(std::istringstream& input, SymbolString& masterData, SymbolString& slaveData, virtual result_t write(std::istringstream& input,
char separator=';'); SymbolString& masterData, unsigned char masterOffset,
SymbolString& slaveData, unsigned char slaveOffset,
char separator);
protected: protected:
/** /**
* @brief Internal method for reading the field from a @a SymbolString. * @brief Internal method for reading the field from a @a SymbolString.
* @param input the unescaped @a SymbolString to read the binary value from. * @param input the unescaped @a SymbolString to read the binary value from.
* @param offset the offset in the @a SymbolString.
* @param output the ostringstream to append the formatted value to. * @param output the ostringstream to append the formatted value to.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t readSymbols(SymbolString& input, unsigned char baseOffset, std::ostringstream& output) = 0; virtual result_t readSymbols(SymbolString& input, const unsigned char offset, std::ostringstream& output) = 0;
/** /**
* @brief Internal method for writing the field to a @a SymbolString. * @brief Internal method for writing the field to a @a SymbolString.
* @param input the @a std::istringstream to parse the formatted value from. * @param input the @a std::istringstream to parse the formatted value from.
* @param offset the offset in the @a SymbolString.
* @param output the unescaped @a SymbolString to write the binary value to. * @param output the unescaped @a SymbolString to write the binary value to.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t writeSymbols(std::istringstream& input, unsigned char baseOffset, SymbolString& output) = 0; virtual result_t writeSymbols(std::istringstream& input, const unsigned char offset, SymbolString& output) = 0;
/** the value unit. */ /** the value unit. */
const std::string m_unit; const std::string m_unit;
@@ -257,8 +276,6 @@ protected:
const dataType_t m_dataType; const dataType_t m_dataType;
/** the message part in which the field is stored. */ /** the message part in which the field is stored. */
const PartType m_partType; const PartType m_partType;
/** the relative offset to the first symbol in the message part in which the field is stored. */
const unsigned char m_offset;
/** the number of symbols in the message part in which the field is stored. */ /** the number of symbols in the message part in which the field is stored. */
const unsigned char m_length; const unsigned char m_length;
@@ -279,29 +296,28 @@ public:
* @param unit the value unit. * @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the offset to the first symbol in the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
*/ */
StringDataField(const std::string name, const std::string comment, StringDataField(const std::string name, const std::string comment,
const std::string unit, const dataType_t dataType, const PartType partType, const std::string unit, const dataType_t dataType, const PartType partType,
const unsigned char offset, const unsigned char length) const unsigned char length)
: SingleDataField(name, comment, unit, dataType, partType, offset, length) {} : SingleDataField(name, comment, unit, dataType, partType, length) {}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
virtual ~StringDataField() {} virtual ~StringDataField() {}
// @copydoc // @copydoc
virtual result_t derive(std::string name, std::string comment, virtual result_t derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields); std::vector<SingleDataField*>& fields);
protected: protected:
// @copydoc // @copydoc
virtual result_t readSymbols(SymbolString& input, unsigned char baseOffset, std::ostringstream& output); virtual result_t readSymbols(SymbolString& input, const unsigned char offset, std::ostringstream& output);
// @copydoc // @copydoc
virtual result_t writeSymbols(std::istringstream& input, unsigned char baseOffset, SymbolString& output); virtual result_t writeSymbols(std::istringstream& input, const unsigned char offset, SymbolString& output);
}; };
@@ -320,15 +336,13 @@ public:
* @param unit the value unit. * @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the offset to the first symbol in the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
* @param bitOffset the offset to the first bit in the binary value. * @param bitOffset the offset to the first bit in the binary value.
*/ */
NumericDataField(const std::string name, const std::string comment, NumericDataField(const std::string name, const std::string comment,
const std::string unit, const dataType_t dataType, const PartType partType, const std::string unit, const dataType_t dataType, const PartType partType,
const unsigned char offset, const unsigned char length, const unsigned char length, const unsigned char bitOffset)
const unsigned char bitOffset) : SingleDataField(name, comment, unit, dataType, partType, length),
: SingleDataField(name, comment, unit, dataType, partType, offset, length),
m_bitOffset(bitOffset) {} m_bitOffset(bitOffset) {}
/** /**
* @brief Destructor. * @brief Destructor.
@@ -340,17 +354,19 @@ protected:
/** /**
* @brief Internal method for reading the raw value from a @a SymbolString. * @brief Internal method for reading the raw value from a @a SymbolString.
* @param input the unescaped @a SymbolString to read the binary value from. * @param input the unescaped @a SymbolString to read the binary value from.
* @param offset the offset in the @a SymbolString.
* @param value the variable in which to store the raw value. * @param value the variable in which to store the raw value.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
result_t readRawValue(SymbolString& input, unsigned char baseOffset, unsigned int& value); result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value);
/** /**
* @brief Internal method for writing the raw value to a @a SymbolString. * @brief Internal method for writing the raw value to a @a SymbolString.
* @param value the raw value to write. * @param value the raw value to write.
* @param offset the offset in the @a SymbolString.
* @param output the unescaped @a SymbolString to write the binary value to. * @param output the unescaped @a SymbolString to write the binary value to.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
result_t writeRawValue(unsigned int value, unsigned char baseOffset, SymbolString& output); result_t writeRawValue(unsigned int value, const unsigned char offset, SymbolString& output);
/** the offset to the first bit in the binary value. */ /** the offset to the first bit in the binary value. */
const unsigned char m_bitOffset; const unsigned char m_bitOffset;
@@ -372,33 +388,31 @@ public:
* @param unit the value unit. * @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the offset to the first symbol in the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
* @param divisor the extra divisor to apply on the value, or 1 for none. * @param divisor the extra divisor to apply on the value, or 1 for none.
*/ */
NumberDataField(const std::string name, const std::string comment, NumberDataField(const std::string name, const std::string comment,
const std::string unit, const dataType_t dataType, const PartType partType, const std::string unit, const dataType_t dataType, const PartType partType,
const unsigned char offset, const unsigned char length, const unsigned char length, const unsigned int divisor)
const unsigned int divisor) : NumericDataField(name, comment, unit, dataType, partType, length,
: NumericDataField(name, comment, unit, dataType, partType, offset, length,
(dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0), (dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0),
m_divisor(divisor) {} m_divisor(divisor) {}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
virtual ~NumberDataField() {} virtual ~NumberDataField() {}
// @copydoc
virtual result_t derive(std::string name, std::string comment,
std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields);
protected: protected:
// @copydoc // @copydoc
virtual result_t derive(std::string name, std::string comment, virtual result_t readSymbols(SymbolString& input, const unsigned char offset, std::ostringstream& output);
std::string unit, const PartType partType, unsigned char offset,
unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields);
// @copydoc // @copydoc
virtual result_t readSymbols(SymbolString& input, unsigned char baseOffset, std::ostringstream& output); virtual result_t writeSymbols(std::istringstream& input, const unsigned char offset, SymbolString& output);
// @copydoc
virtual result_t writeSymbols(std::istringstream& input, unsigned char baseOffset, SymbolString& output);
/** the combined divisor to apply on the value, or 1 for none. */ /** the combined divisor to apply on the value, or 1 for none. */
const unsigned int m_divisor; const unsigned int m_divisor;
@@ -420,33 +434,31 @@ public:
* @param unit the value unit. * @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param offset the offset to the first symbol in the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
* @param values the value=text assignments. * @param values the value=text assignments.
*/ */
ValueListDataField(const std::string name, const std::string comment, ValueListDataField(const std::string name, const std::string comment,
const std::string unit, const dataType_t dataType, const PartType partType, const std::string unit, const dataType_t dataType, const PartType partType,
const unsigned char offset, const unsigned char length, const unsigned char length, const std::map<unsigned int, std::string> values)
const std::map<unsigned int, std::string> values) : NumericDataField(name, comment, unit, dataType, partType, length,
: NumericDataField(name, comment, unit, dataType, partType, offset, length,
(dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0), (dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0),
m_values(values) {} m_values(values) {}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
virtual ~ValueListDataField() {} virtual ~ValueListDataField() {}
// @copydoc
virtual result_t derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned int divisor,
std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields);
protected: protected:
// @copydoc // @copydoc
virtual result_t derive(std::string name, std::string comment, virtual result_t readSymbols(SymbolString& input, const unsigned char offset, std::ostringstream& output);
std::string unit, const PartType partType, unsigned char offset,
unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields);
// @copydoc // @copydoc
virtual result_t readSymbols(SymbolString& input, unsigned char baseOffset, std::ostringstream& output); virtual result_t writeSymbols(std::istringstream& input, const unsigned char offset, SymbolString& output);
// @copydoc
virtual result_t writeSymbols(std::istringstream& input, unsigned char baseOffset, SymbolString& output);
/** the value=text assignments. */ /** the value=text assignments. */
std::map<unsigned int, std::string> m_values; std::map<unsigned int, std::string> m_values;
@@ -476,10 +488,10 @@ public:
*/ */
virtual ~DataFieldSet(); virtual ~DataFieldSet();
// @copydoc // @copydoc
virtual unsigned char getNextOffset(PartType partType=pt_any); virtual unsigned char getLength(PartType partType);
// @copydoc // @copydoc
virtual result_t derive(std::string name, std::string comment, virtual result_t derive(std::string name, std::string comment,
std::string unit, const PartType partType, unsigned char offset, std::string unit, const PartType partType,
unsigned int divisor, std::map<unsigned int, std::string> values, unsigned int divisor, std::map<unsigned int, std::string> values,
std::vector<SingleDataField*>& fields); std::vector<SingleDataField*>& fields);
/** /**
@@ -499,26 +511,16 @@ public:
* @return the number of available @a SingleDataField instances. * @return the number of available @a SingleDataField instances.
*/ */
size_t size() const { return m_fields.size(); } size_t size() const { return m_fields.size(); }
/** // @copydoc
* @brief Reads the values from the master and/or slave @a SymbolString. virtual result_t read(SymbolString& masterData, unsigned char masterOffset,
* @param masterData the unescaped master data @a SymbolString for reading binary data. SymbolString& slaveData, unsigned char slaveOffset,
* @param slaveData the unescaped slave data @a SymbolString for reading binary data. std::ostringstream& output,
* @param output the @a std::ostringstream to append the formatted value to. bool verbose, char separator);
* @param vervose whether to prepend the name, append the unit (if present), and append // @copydoc
* the comment in square brackets (if present). virtual result_t write(std::istringstream& input,
* @return @a RESULT_OK on success, or an error code. SymbolString& masterData, unsigned char masterOffset,
*/ SymbolString& slaveData, unsigned char slaveOffset,
virtual result_t read(SymbolString& masterData, SymbolString& slaveData, std::ostringstream& output, char separator);
bool verbose=false, char separator=';');
/**
* @brief Writes the values to the master and/or slave @a SymbolString.
* @param input the @a std::istringstream to parse the formatted value from.
* @param masterData the unescaped master data @a SymbolString for writing binary data.
* @param slaveData the unescaped slave data @a SymbolString for writing binary data.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t write(std::istringstream& input, SymbolString& masterData, SymbolString& slaveData,
char separator=';');
protected: protected:
+20 -40
View File
@@ -42,22 +42,22 @@ void verify(bool expectFailMatch, std::string type, std::string input,
int main() int main()
{ {
std::string checks[][5] = { std::string checks[][5] = {
//name;[pos];type[;[divisor|values][;[unit][;[comment]]]], decoded value, master, slave, flags //name;[len];type[;[divisor|values][;[unit][;[comment]]]], decoded value, master, slave, flags
{"x;1-10;str", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x;10;str", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x;1-10;str", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""}, {"x;10;str", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""},
{"x;1-10;str", " ", "10fe07000a20202020202020202020", "00", ""}, {"x;10;str", " ", "10fe07000a20202020202020202020", "00", ""},
{"x;1-11;str", "", "10fe07000a20202020202020202020", "00", "rW"}, {"x;11;str", "", "10fe07000a20202020202020202020", "00", "rW"},
{"x;;hex", "20", "10fe07000120", "00", ""}, {"x;;hex", "20", "10fe07000120", "00", ""},
{"x;1-10;hex", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x;10;hex", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x;1-11;hex", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"}, {"x;11;hex", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
{"x;;bda", "26.10.2014","10fe07000426100014", "00", ""}, {"x;;bda", "26.10.2014","10fe07000426100014", "00", ""},
{"x;;bda", "01.01.2000","10fe07000401010000", "00", ""}, {"x;;bda", "01.01.2000","10fe07000401010000", "00", ""},
{"x;;bda", "31.12.2099","10fe07000431120099", "00", ""}, {"x;;bda", "31.12.2099","10fe07000431120099", "00", ""},
{"x;;bda", "", "10fe07000432100014", "00", "rw"}, {"x;;bda", "", "10fe07000432100014", "00", "rw"},
{"x;1-3;bda","26.10.2014","10fe070003261014", "00", ""}, {"x;3;bda","26.10.2014","10fe070003261014", "00", ""},
{"x;1-3;bda","01.01.2000","10fe070003010100", "00", ""}, {"x;3;bda","01.01.2000","10fe070003010100", "00", ""},
{"x;1-3;bda","31.12.2099","10fe070003311299", "00", ""}, {"x;3;bda","31.12.2099","10fe070003311299", "00", ""},
{"x;1-3;bda","", "10fe070003321299", "00", "rw"}, {"x;3;bda","", "10fe070003321299", "00", "rw"},
{"x;;bti", "21:04:58", "10fe070003580421", "00", ""}, {"x;;bti", "21:04:58", "10fe070003580421", "00", ""},
{"x;;bti", "00:00:00", "10fe070003000000", "00", ""}, {"x;;bti", "00:00:00", "10fe070003000000", "00", ""},
{"x;;bti", "23:59:59", "10fe070003595923", "00", ""}, {"x;;bti", "23:59:59", "10fe070003595923", "00", ""},
@@ -84,15 +84,11 @@ int main()
{"x;;bcd", "99", "10feffff0199", "00", ""}, {"x;;bcd", "99", "10feffff0199", "00", ""},
{"x;;bcd", "-", "10feffff01ff", "00", ""}, {"x;;bcd", "-", "10feffff01ff", "00", ""},
{"x;;bcd", "", "10feffff019a", "00", "rw"}, {"x;;bcd", "", "10feffff019a", "00", "rw"},
{"x;16;uch", "15", "10feffff11000102030405060708090a0b0c0d0e0f10", "00", "W"}, {"x;16;str", "0123456789ABCDEF", "10feffff1130313233343536373839414243444546", "00", ""},
{"x;17;uch", "", "10feffff00", "00", "c"}, {"x;17;uch", "", "10feffff00", "00", "c"},
{"x;s3;uch", "2", "1025ffff0310111213", "0300010203", "W"}, {"x;s;uch", "0", "1025ffff0310111213", "0300010203", "W"},
{"x;s3;uch", "2", "1025ffff00", "03000002", ""}, {"x;s;uch", "0", "1025ffff00", "0100", ""},
{"x;3;uch", "2", "1025ffff03010101", "03000002", "W"}, {"x;s;uch;;;;y;m;uch", "2;3","1025ffff0103", "0102", ""},
{"x;3;uch", "1", "1025ffff03010101", "03000002", "sW"},
{"x;1;uch", "2", "1025ffff00", "0102", ""},
{"x;1;uch", "1", "1025ffff0101", "00", "s"},
{"x;s3;uch;;;;y;m2;uch", "2;3","1025ffff020003", "03000002", ""},
{"x;;uch", "38", "10feffff0126", "00", ""}, {"x;;uch", "38", "10feffff0126", "00", ""},
{"x;;uch", "0", "10feffff0100", "00", ""}, {"x;;uch", "0", "10feffff0100", "00", ""},
{"x;;uch", "254", "10feffff01fe", "00", ""}, {"x;;uch", "254", "10feffff01fe", "00", ""},
@@ -161,10 +157,9 @@ int main()
{"x;;b34;0=off,1=on","on", "10feffff0108", "00", ""}, {"x;;b34;0=off,1=on","on", "10feffff0108", "00", ""},
{"x;;b34;0=off,1=on","off","10feffff0100", "00", ""}, {"x;;b34;0=off,1=on","off","10feffff0100", "00", ""},
{"x;;uch;1=test,2=high,3=off,4=on","on","10feffff0104", "00", ""}, {"x;;uch;1=test,2=high,3=off,4=on","on","10feffff0104", "00", ""},
{"x;s3;uch","3","1050ffff00", "03000003", ""}, {"x;s;uch","3","1050ffff00", "0103", ""},
{"x;s3;uch","3","1050ffff00", "020000", "rW"},
{"x;;d2b;;°C;Aussentemperatur","x=18.004 °C [Aussentemperatur]","10fe0700090112", "00", "v"}, {"x;;d2b;;°C;Aussentemperatur","x=18.004 °C [Aussentemperatur]","10fe0700090112", "00", "v"},
{"x;;bti;;;;y;;bda;;;;z;6;bdy", "21:04:58;26.10.2014;Sun","10fe07000758042126100614", "00", ""}, // combination {"x;;bti;;;;y;;bda;;;;z;;bdy", "21:04:58;26.10.2014;Sun","10fe0700085804212610001406", "00", ""}, // combination
{"x;;bi3;;;;y;;bi5", "1;-", "10feffff0108", "00", ""}, // bit combination {"x;;bi3;;;;y;;bi5", "1;-", "10feffff0108", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi5", "1;1", "10feffff0128", "00", ""}, // bit combination {"x;;bi3;;;;y;;bi5", "1;1", "10feffff0128", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi5", "-;1", "10feffff0120", "00", ""}, // bit combination {"x;;bi3;;;;y;;bi5", "-;1", "10feffff0120", "00", ""}, // bit combination
@@ -173,25 +168,10 @@ int main()
{"x;;bi3;;;;y;;bi5;;;;t;;uch", "-;-;9","10feffff020009", "00", "RW"}, // bit combination {"x;;bi3;;;;y;;bi5;;;;t;;uch", "-;-;9","10feffff020009", "00", "RW"}, // bit combination
{"temp;;d2b;;°C;Aussentemperatur","","", "", "t"}, // template with relative pos {"temp;;d2b;;°C;Aussentemperatur","","", "", "t"}, // template with relative pos
{"x;;temp","18.004","10fe0700020112", "00", ""}, // reference to template {"x;;temp","18.004","10fe0700020112", "00", ""}, // reference to template
{"tempoff;2;d2b;;°C;Aussentemperatur","","", "", "t"},// template with offset pos
{"x;;tempoff","18.004","10fe070002ff0112", "00", "W"}, // reference to template
{"relrel;;d2b;;;;y;;d1c","","", "", "t"}, // template struct with relative pos {"relrel;;d2b;;;;y;;d1c","","", "", "t"}, // template struct with relative pos
{"x;2;relrel","18.004;9.5","10fe070004ff011213", "00", "W"}, // reference to template struct {"x;;relrel","18.004;9.5","10fe070003011213", "00", ""}, // reference to template struct
{"reloff;;d2b;;;;y;1;d1c","","", "", "t"}, // template struct with relative+offset pos
{"x;2;reloff","18.004;0.5","10fe070003130112", "00", "W"}, // reference to template struct
{"offrel;2;d2b;;;;y;;d1c","","", "", "t"}, // template struct with offset+relative pos
{"x;2;offrel","18.004;9.5","10fe070005fffe011213", "00", "W"}, // reference to template struct
{"offoff;2;d2b;;;;y;1;d1c","","", "", "t"}, // template struct with offset pos
{"x;2;offoff","18.004;9.5","10fe070004ff130112", "00", "W"}, // reference to template struct
{"trelrel;;temp,temp","","", "", "t"}, // template struct with relative pos and ref to templates {"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;;trelrel","18.004;19.008","10fe07000401120213", "00", ""}, // reference to template struct
{"x;2;trelrel","18.004;19.008","10fe070005ff01120213", "00", "W"}, // reference to template struct
{"treloff;;temp,tempoff","","", "", "t"}, // template struct with relative+offset pos
{"x;2;treloff","18.004;19.008","10fe070006ff0112fe0213", "00", "W"}, // reference to template struct
{"toffrel;1;tempoff,temp","","", "", "t"}, // template struct with offset+relative pos
{"x;2;toffrel","18.004;19.008","10fe070003fffe01120213", "00", "W"}, // reference to template struct
{"toffoff;1;tempoff,tempoff","","", "", "t"}, // template struct with offset pos
{"x;2;toffoff","18.004;19.008","10fe070003fffe0112fd0213", "00", "W"}, // reference to template struct
}; };
std::map<std::string, DataField*> templates; std::map<std::string, DataField*> templates;
DataField* fields = NULL; DataField* fields = NULL;
@@ -261,7 +241,7 @@ int main()
std::ostringstream output; std::ostringstream output;
SymbolString writeMstr = SymbolString(mstr.getDataStr().substr(0, 10), false); SymbolString writeMstr = SymbolString(mstr.getDataStr().substr(0, 10), false);
SymbolString writeSstr = SymbolString(sstr.getDataStr().substr(0, 2), false); SymbolString writeSstr = SymbolString(sstr.getDataStr().substr(0, 2), false);
result = fields->read(mstr, sstr, output, verbose); result = fields->read(mstr, 0, sstr, 0, output, verbose);
if (failedRead == true) if (failedRead == true)
if (result == RESULT_OK) if (result == RESULT_OK)
std::cout << " failed read " << fields->getName() << " >" std::cout << " failed read " << fields->getName() << " >"
@@ -280,7 +260,7 @@ int main()
if (verbose == false) { if (verbose == false) {
std::istringstream input(expectStr); std::istringstream input(expectStr);
result = fields->write(input, writeMstr, writeSstr); result = fields->write(input, writeMstr, 0, writeSstr, 0);
if (failedWrite == true) { if (failedWrite == true) {
if (result == RESULT_OK) if (result == RESULT_OK)
std::cout << " failed write " << fields->getName() << " >" std::cout << " failed write " << fields->getName() << " >"