added special length '*' for consuming remaining input

This commit is contained in:
john30
2016-01-03 18:55:45 +01:00
parent 62317ea47b
commit bc84dd389f
4 changed files with 168 additions and 118 deletions
+128 -98
View File
@@ -312,7 +312,9 @@ result_t DataField::create(vector<string>::iterator& it,
size_t pos = token.find(LENGTH_SEPARATOR); size_t pos = token.find(LENGTH_SEPARATOR);
if (pos == string::npos) if (pos == string::npos)
length = 0; // no length specified length = 0; // no length specified
else { else if (pos+2==token.length() && token[pos+1]=='*') {
length = REMAIN_LEN;
} else {
length = (unsigned char)parseInt(token.substr(pos+1).c_str(), 10, 1, maxFieldLength, result); length = (unsigned char)parseInt(token.substr(pos+1).c_str(), 10, 1, maxFieldLength, result);
if (result != RESULT_OK) if (result != RESULT_OK)
break; break;
@@ -367,81 +369,82 @@ result_t SingleDataField::create(const char* typeNameStr, const unsigned char le
{ {
for (size_t i = 0; i < sizeof(dataTypes) / sizeof(dataType_t); i++) { // TODO use a map for (size_t i = 0; i < sizeof(dataTypes) / sizeof(dataType_t); i++) { // TODO use a map
const dataType_t* dataType = &dataTypes[i]; const dataType_t* dataType = &dataTypes[i];
if (strcasecmp(typeNameStr, dataType->name) == 0) { if (strcasecmp(typeNameStr, dataType->name) != 0)
unsigned char bitCount = dataType->bitCount; continue;
unsigned char byteCount = (unsigned char)((bitCount + 7) / 8);
if ((dataType->flags & ADJ) != 0) { // adjustable length
if ((bitCount % 8) != 0) {
if (length == 0)
bitCount = 1; // default bit count: 1 bit
else if (length <= bitCount)
bitCount = length;
else
return RESULT_ERR_OUT_OF_RANGE; // invalid length
byteCount = (unsigned char)((bitCount + 7) / 8); unsigned char bitCount = dataType->bitCount;
} unsigned char byteCount = (unsigned char)((bitCount + 7) / 8);
else if (length == 0) if ((dataType->flags & ADJ) != 0) { // adjustable length
byteCount = 1; //default byte count: 1 byte if ((bitCount % 8) != 0) {
else if (length <= byteCount) if (length == 0)
byteCount = length; bitCount = 1; // default bit count: 1 bit
else if (length <= bitCount)
bitCount = length;
else 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 && length != byteCount) else if (length == 0)
continue; // check for another one with same name but different length 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
}
else if (length > 0 && length != byteCount)
continue; // check for another one with same name but different length
switch (dataType->type) switch (dataType->type)
{ {
case bt_str: case bt_str:
case bt_hexstr: case bt_hexstr:
case bt_dat: case bt_dat:
case bt_tim: case bt_tim:
if (divisor != 0 || !values.empty()) 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 StringDataField(name, comment, unit, *dataType, partType, byteCount); returnField = new StringDataField(name, comment, unit, *dataType, partType, byteCount);
return RESULT_OK; return RESULT_OK;
case bt_num: case bt_num:
if (values.empty() && (dataType->flags & DAY) != 0) { if (values.empty() && (dataType->flags & DAY) != 0) {
for (unsigned int i = 0; i < sizeof(dayNames) / sizeof(dayNames[0]); i++) for (unsigned int i = 0; i < sizeof(dayNames) / sizeof(dayNames[0]); i++)
values[dataType->minValue + i] = dayNames[i]; values[dataType->minValue + i] = dayNames[i];
}
if (values.empty() || (dataType->flags & LST) == 0) {
if (divisor == 0)
divisor = 1;
if ((dataType->bitCount % 8) == 0) {
if (divisor < 0) {
if (dataType->divisorOrFirstBit > 1)
return RESULT_ERR_INVALID_ARG;
if (dataType->divisorOrFirstBit < 0)
divisor *= -dataType->divisorOrFirstBit;
} else if (dataType->divisorOrFirstBit < 0) {
if (divisor > 1)
return RESULT_ERR_INVALID_ARG;
if (divisor < 0)
divisor *= -dataType->divisorOrFirstBit;
} else
divisor *= dataType->divisorOrFirstBit;
if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR)
return RESULT_ERR_OUT_OF_RANGE;
} }
if (values.empty() || (dataType->flags & LST) == 0) {
if (divisor == 0)
divisor = 1;
if ((dataType->bitCount % 8) == 0) { returnField = new NumberDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, divisor);
if (divisor < 0) {
if (dataType->divisorOrFirstBit > 1)
return RESULT_ERR_INVALID_ARG;
if (dataType->divisorOrFirstBit < 0)
divisor *= -dataType->divisorOrFirstBit;
} else if (dataType->divisorOrFirstBit < 0) {
if (divisor > 1)
return RESULT_ERR_INVALID_ARG;
if (divisor < 0)
divisor *= -dataType->divisorOrFirstBit;
} else
divisor *= dataType->divisorOrFirstBit;
if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR)
return RESULT_ERR_OUT_OF_RANGE;
}
returnField = new NumberDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, divisor);
return RESULT_OK;
}
if (values.begin()->first < dataType->minValue || values.rbegin()->first > dataType->maxValue)
return RESULT_ERR_OUT_OF_RANGE;
if (divisor != 0)
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
//TODO add special field for fixed values (exactly one value in the list of values)
returnField = new ValueListDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, values);
return RESULT_OK; return RESULT_OK;
} }
if (values.begin()->first < dataType->minValue || values.rbegin()->first > dataType->maxValue)
return RESULT_ERR_OUT_OF_RANGE;
if (divisor != 0)
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
//TODO add special field for fixed values (exactly one value in the list of values)
returnField = new ValueListDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, values);
return RESULT_OK;
} }
} }
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
@@ -479,7 +482,8 @@ result_t SingleDataField::read(const PartType partType,
return RESULT_ERR_INVALID_PART; return RESULT_ERR_INVALID_PART;
} }
if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) {
if (offset + m_length > data.size()) { bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0;
if (!remainder && offset + m_length > data.size()) {
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
return RESULT_EMPTY; return RESULT_EMPTY;
@@ -507,7 +511,8 @@ result_t SingleDataField::read(const PartType partType,
return RESULT_ERR_INVALID_PART; return RESULT_ERR_INVALID_PART;
} }
if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) {
if (offset + m_length > data.size()) { bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0;
if (!remainder && offset + m_length > data.size()) {
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
return RESULT_EMPTY; return RESULT_EMPTY;
@@ -552,7 +557,7 @@ result_t SingleDataField::read(const PartType partType,
result_t SingleDataField::write(istringstream& input, result_t SingleDataField::write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator) unsigned char offset, char separator, unsigned char* length)
{ {
if (partType != m_partType) if (partType != m_partType)
return RESULT_OK; return RESULT_OK;
@@ -568,7 +573,7 @@ result_t SingleDataField::write(istringstream& input,
default: default:
return RESULT_ERR_INVALID_PART; return RESULT_ERR_INVALID_PART;
} }
return writeSymbols(input, offset, data); return writeSymbols(input, offset, data, length);
} }
StringDataField* StringDataField::clone() StringDataField* StringDataField::clone()
@@ -605,8 +610,12 @@ bool StringDataField::hasField(const char* fieldName, bool numeric)
void StringDataField::dump(ostream& output) void StringDataField::dump(ostream& output)
{ {
SingleDataField::dump(output); SingleDataField::dump(output);
if ((m_dataType.flags & ADJ) != 0) if ((m_dataType.flags & ADJ) != 0) {
output << ":" << static_cast<unsigned>(m_length); if (m_length==REMAIN_LEN)
output << ":*";
else
output << ":" << static_cast<unsigned>(m_length);
}
output << FIELD_SEPARATOR; // no value list, no divisor output << FIELD_SEPARATOR; // no value list, no divisor
dumpString(output, m_unit); dumpString(output, m_unit);
dumpString(output, m_comment); dumpString(output, m_comment);
@@ -623,8 +632,9 @@ result_t StringDataField::readSymbols(SymbolString& input, const unsigned char b
size_t start = 0, count = m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
unsigned char ch, last = 0, hour = 0; unsigned char ch, last = 0, hour = 0;
if (count==REMAIN_LEN && input.size()>baseOffset) {
if (baseOffset + m_length > input.size()) { count = input.size()-baseOffset;
} else if (baseOffset + count > input.size()) {
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
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)
@@ -714,9 +724,10 @@ result_t StringDataField::readSymbols(SymbolString& input, const unsigned char b
} }
result_t StringDataField::writeSymbols(istringstream& input, result_t StringDataField::writeSymbols(istringstream& input,
unsigned char baseOffset, SymbolString& output) unsigned char baseOffset, SymbolString& output, unsigned char* length)
{ {
size_t start = 0, count = m_length; size_t start = 0, count = m_length;
bool remainder = count==REMAIN_LEN && (m_dataType.flags & ADJ)!=0;
int incr = 1; int incr = 1;
unsigned int value = 0, last = 0, lastLast = 0; unsigned int value = 0, last = 0, lastLast = 0;
string token; string token;
@@ -725,11 +736,15 @@ result_t StringDataField::writeSymbols(istringstream& input,
start = m_length - 1; start = m_length - 1;
incr = -1; incr = -1;
} }
if (isIgnored() && (m_dataType.flags & REQ) == 0) { if (isIgnored() && (m_dataType.flags & REQ) == 0) {
if (remainder) {
count = 1;
}
for (size_t offset = start, i = 0; i < count; offset += incr, i++) { for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
output[baseOffset + offset] = (unsigned char)m_dataType.replacement; // fill up with replacement output[baseOffset + offset] = (unsigned char)m_dataType.replacement; // fill up with replacement
} }
if (length!=NULL)
*length = (unsigned char)count;
return RESULT_OK; return RESULT_OK;
} }
result_t result; result_t result;
@@ -740,9 +755,9 @@ result_t StringDataField::writeSymbols(istringstream& input,
case bt_hexstr: case bt_hexstr:
while (!input.eof() && input.peek() == ' ') while (!input.eof() && input.peek() == ' ')
input.get(); input.get();
if (input.eof()) // no more digits if (input.eof()) { // no more digits
value = m_dataType.replacement; // fill up with replacement value = m_dataType.replacement; // fill up with replacement
else { } else {
token.clear(); token.clear();
token.push_back((unsigned char)input.get()); token.push_back((unsigned char)input.get());
if (input.eof()) if (input.eof())
@@ -841,6 +856,10 @@ result_t StringDataField::writeSymbols(istringstream& input,
} }
break; break;
} }
if (remainder && input.eof() && i > 0) {
count = (offset-start)*incr;
break;
}
lastLast = last; lastLast = last;
last = value; last = value;
if ((m_dataType.flags & BCD) != 0 && ((m_dataType.flags & REQ) != 0 || value != m_dataType.replacement)) { if ((m_dataType.flags & BCD) != 0 && ((m_dataType.flags & REQ) != 0 || value != m_dataType.replacement)) {
@@ -853,9 +872,10 @@ result_t StringDataField::writeSymbols(istringstream& input,
output[baseOffset + offset] = (unsigned char)value; output[baseOffset + offset] = (unsigned char)value;
} }
if (i < m_length) if (!remainder && i < m_length) // TODO check with bt_tim and m_length == 1
return RESULT_ERR_EOF; // input too short return RESULT_ERR_EOF; // input too short
if (length!=NULL)
*length = (unsigned char)count;
return RESULT_OK; return RESULT_OK;
} }
@@ -932,7 +952,7 @@ 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, unsigned char* length)
{ {
size_t start = 0, count = m_length; size_t start = 0, count = m_length;
int incr = 1; int incr = 1;
@@ -968,7 +988,8 @@ result_t NumericDataField::writeRawValue(unsigned int value,
else else
output[baseOffset + offset] = ch; output[baseOffset + offset] = ch;
} }
if (length!=NULL)
*length = m_length;
return RESULT_OK; return RESULT_OK;
} }
@@ -1109,7 +1130,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, const unsigned char b
} }
result_t NumberDataField::writeSymbols(istringstream& input, result_t NumberDataField::writeSymbols(istringstream& input,
unsigned char baseOffset, SymbolString& output) unsigned char baseOffset, SymbolString& output, unsigned char* length)
{ {
unsigned int value; unsigned int value;
@@ -1168,7 +1189,7 @@ result_t NumberDataField::writeSymbols(istringstream& input,
return RESULT_ERR_OUT_OF_RANGE; // value out of range return RESULT_ERR_OUT_OF_RANGE; // value out of range
} }
return writeRawValue(value, baseOffset, output); return writeRawValue(value, baseOffset, output, length);
} }
@@ -1250,19 +1271,19 @@ result_t ValueListDataField::readSymbols(SymbolString& input, const unsigned cha
} }
result_t ValueListDataField::writeSymbols(istringstream& input, result_t ValueListDataField::writeSymbols(istringstream& input,
unsigned char baseOffset, SymbolString& output) unsigned char baseOffset, SymbolString& output, unsigned char* length)
{ {
if (isIgnored()) if (isIgnored())
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value return writeRawValue(m_dataType.replacement, baseOffset, output, length); // replacement value
const char* str = input.str().c_str(); const char* str = input.str().c_str();
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++)
if (it->second.compare(str) == 0) if (it->second.compare(str) == 0)
return writeRawValue(it->first, baseOffset, output); return writeRawValue(it->first, baseOffset, output, length);
if (strcasecmp(str, NULL_VALUE) == 0) if (strcasecmp(str, NULL_VALUE) == 0)
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value return writeRawValue(m_dataType.replacement, baseOffset, output, length); // replacement value
char* strEnd = NULL; // fall back to raw value in input char* strEnd = NULL; // fall back to raw value in input
unsigned int value; unsigned int value;
@@ -1270,7 +1291,7 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) 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()) if (m_values.find(value) != m_values.end())
return writeRawValue(value, baseOffset, output); return writeRawValue(value, baseOffset, output, length);
return RESULT_ERR_NOTFOUND; // value assignment not found return RESULT_ERR_NOTFOUND; // value assignment not found
} }
@@ -1334,7 +1355,7 @@ DataFieldSet* DataFieldSet::clone()
return new DataFieldSet(m_name, m_comment, fields); return new DataFieldSet(m_name, m_comment, fields);
} }
unsigned char DataFieldSet::getLength(PartType partType) unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength)
{ {
unsigned char length = 0; unsigned char length = 0;
@@ -1346,7 +1367,12 @@ unsigned char DataFieldSet::getLength(PartType partType)
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false))
length--; length--;
length = (unsigned char)(length + field->getLength(partType)); unsigned char fieldLength = field->getLength(partType, maxLength);
if (fieldLength>=maxLength)
maxLength = 0;
else
maxLength = (unsigned char)(maxLength-fieldLength);
length = (unsigned char)(length + fieldLength);
previousFullByteOffset[partType] = field->hasFullByteOffset(true); previousFullByteOffset[partType] = field->hasFullByteOffset(true);
} }
@@ -1413,7 +1439,7 @@ result_t DataFieldSet::read(const PartType partType,
if (result < RESULT_OK) if (result < RESULT_OK)
return result; return result;
offset = (unsigned char)(offset + field->getLength(partType)); offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
if (result != RESULT_EMPTY) { if (result != RESULT_EMPTY) {
found = true; found = true;
@@ -1458,7 +1484,7 @@ result_t DataFieldSet::read(const PartType partType,
if (result < RESULT_OK) if (result < RESULT_OK)
return result; return result;
offset = (unsigned char)(offset + field->getLength(partType)); offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
if (result != RESULT_EMPTY) { if (result != RESULT_EMPTY) {
found = true; found = true;
@@ -1491,11 +1517,12 @@ result_t DataFieldSet::read(const PartType partType,
result_t DataFieldSet::write(istringstream& input, result_t DataFieldSet::write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator) unsigned char offset, char separator, unsigned char* length)
{ {
string token; string token;
bool previousFullByteOffset = true; bool previousFullByteOffset = true;
unsigned char baseOffset = offset;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (partType != pt_any && field->getPartType() != partType) if (partType != pt_any && field->getPartType() != partType)
@@ -1505,6 +1532,7 @@ result_t DataFieldSet::write(istringstream& input,
offset--; offset--;
result_t result; result_t result;
unsigned char fieldLength;
if (m_fields.size() > 1) { if (m_fields.size() > 1) {
if (field->isIgnored()) if (field->isIgnored())
token.clear(); token.clear();
@@ -1512,18 +1540,20 @@ result_t DataFieldSet::write(istringstream& input,
token.clear(); token.clear();
istringstream single(token); istringstream single(token);
result = (*it)->write(single, partType, data, offset, separator); result = (*it)->write(single, partType, data, offset, separator, &fieldLength);
} }
else else
result = (*it)->write(input, partType, data, offset, separator); result = (*it)->write(input, partType, data, offset, separator, &fieldLength);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
offset = (unsigned char)(offset + field->getLength(partType)); offset = (unsigned char)(offset+fieldLength);
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
} }
if (length!=NULL)
*length = (unsigned char)(offset-baseOffset);
return RESULT_OK; return RESULT_OK;
} }
+26 -14
View File
@@ -126,6 +126,9 @@ typedef struct dataType_s {
/** the maximum allowed field length. */ /** the maximum allowed field length. */
#define MAX_LEN 31 #define MAX_LEN 31
/** the field length indicating remainder of input. */
#define REMAIN_LEN 255
/** /**
* Parse an unsigned int value. * Parse an unsigned int value.
* @param str the string to parse. * @param str the string to parse.
@@ -222,9 +225,10 @@ public:
/** /**
* Returns the length of this field (or contained fields) in bytes. * Returns the length of this field (or contained fields) in bytes.
* @param partType the message part of the contained fields to limit the length calculation to. * @param partType the message part of the contained fields to limit the length calculation to.
* @param maxLength the maximum length for calculating remainder of input.
* @return the length of this field (or contained fields) in bytes. * @return the length of this field (or contained fields) in bytes.
*/ */
virtual unsigned char getLength(PartType partType) = 0; virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN) = 0;
/** /**
* Derive a new @a DataField from this field. * Derive a new @a DataField from this field.
@@ -312,11 +316,12 @@ public:
* @param data the unescaped data @a SymbolString for writing binary data. * @param data the unescaped data @a SymbolString for writing binary data.
* @param offset the additional offset to add for writing binary data. * @param offset the additional offset to add for writing binary data.
* @param separator the separator character between multiple fields. * @param separator the separator character between multiple fields.
* @param length the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=UI_FIELD_SEPARATOR) = 0; unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL) = 0;
protected: protected:
@@ -363,7 +368,7 @@ public:
/** /**
* Factory method for creating a new @a SingleDataField instance derived from a base type. * Factory method for creating a new @a SingleDataField instance derived from a base type.
* @param typeNameStr the base type name string. * @param typeNameStr the base type name string.
* @param length the base type length, or 0 for default. * @param length the base type length, or 0 for default, or @a REMAIN_LEN for remainder within same message part.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param comment the field comment.
* @param unit the value unit. * @param unit the value unit.
@@ -398,8 +403,13 @@ public:
PartType getPartType() const { return m_partType; } PartType getPartType() const { return m_partType; }
// @copydoc // @copydoc
virtual unsigned char getLength(PartType partType) { return partType == m_partType ? m_length : (unsigned char)0; }; virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN) {
// re-use same position as previous field as not all bits of fully consumed yet if (partType != m_partType) {
return (unsigned char)0;
}
bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0;
return remainder ? maxLength : m_length;
}
/** /**
* Get whether this field uses a full byte offset. * Get whether this field uses a full byte offset.
@@ -426,7 +436,7 @@ public:
// @copydoc // @copydoc
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=UI_FIELD_SEPARATOR); unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL);
protected: protected:
@@ -455,9 +465,10 @@ protected:
* @param input the @a istringstream to parse the formatted value from. * @param input the @a istringstream to parse the formatted value from.
* @param offset the offset in the @a SymbolString. * @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.
* @param length the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output) = 0; virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length) = 0;
protected: protected:
@@ -490,7 +501,7 @@ 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 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, or @a REMAIN_LEN for remainder within same message part.
*/ */
StringDataField(const string name, const string comment, StringDataField(const string name, const string comment,
const string unit, const dataType_t dataType, const PartType partType, const string unit, const dataType_t dataType, const PartType partType,
@@ -527,7 +538,7 @@ protected:
ostringstream& output, OutputFormat outputFormat); ostringstream& output, OutputFormat outputFormat);
// @copydoc // @copydoc
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length);
}; };
@@ -583,9 +594,10 @@ protected:
* @param value the raw value to write. * @param value the raw value to write.
* @param offset the offset in the @a SymbolString. * @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.
* @param length the variable in which to store the used length in bytes, or NULL.
* @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, const unsigned char offset, SymbolString& output); result_t writeRawValue(unsigned int value, const unsigned char offset, SymbolString& output, unsigned char* length=NULL);
/** the number of bits in the binary value. */ /** the number of bits in the binary value. */
const unsigned char m_bitCount; const unsigned char m_bitCount;
@@ -643,7 +655,7 @@ protected:
ostringstream& output, OutputFormat outputFormat); ostringstream& output, OutputFormat outputFormat);
// @copydoc // @copydoc
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length);
private: private:
@@ -706,7 +718,7 @@ protected:
ostringstream& output, OutputFormat outputFormat); ostringstream& output, OutputFormat outputFormat);
// @copydoc // @copydoc
virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length);
private: private:
@@ -768,7 +780,7 @@ public:
virtual DataFieldSet* clone(); virtual DataFieldSet* clone();
// @copydoc // @copydoc
virtual unsigned char getLength(PartType partType); virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN);
// @copydoc // @copydoc
virtual result_t derive(string name, string comment, virtual result_t derive(string name, string comment,
@@ -816,7 +828,7 @@ public:
// @copydoc // @copydoc
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=UI_FIELD_SEPARATOR); unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL);
private: private:
+10 -6
View File
@@ -353,7 +353,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
return result; return result;
} }
} }
if (id.size() + data->getLength(pt_masterData) > 2 + maxLength || data->getLength(pt_slaveData) > maxLength) { if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength || data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) {
// max NN exceeded // max NN exceeded
delete data; delete data;
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
@@ -515,8 +515,8 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
{ {
if (index!=0) if (index!=0)
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
unsigned char addData = m_data->getLength(pt_masterData); unsigned char pos = master.size();
result_t result = master.push_back((unsigned char)(getIdLength() + addData), false, false); result_t result = master.push_back(0, false, false); // length, will be set later
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
for (size_t i = 2; i < m_id.size(); i++) { for (size_t i = 2; i < m_id.size(); i++) {
@@ -524,7 +524,11 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
} }
return m_data->write(input, pt_masterData, master, getIdLength(), separator); result = m_data->write(input, pt_masterData, master, getIdLength(), separator);
if (result != RESULT_OK)
return result;
master[pos] = (unsigned char)(master.size()-pos-1);
return result;
} }
result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData)
@@ -533,13 +537,13 @@ result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData)
return RESULT_ERR_INVALID_ARG; // prepare not possible return RESULT_ERR_INVALID_ARG; // prepare not possible
SymbolString slave(false); SymbolString slave(false);
unsigned char addData = m_data->getLength(pt_slaveData); result_t result = slave.push_back(0, false, false); // length, will be set later
result_t result = slave.push_back(addData, false, false);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
result = m_data->write(input, pt_slaveData, slave, 0); result = m_data->write(input, pt_slaveData, slave, 0);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
slave[0] = (unsigned char)(slave.size()-1);
time(&m_lastUpdateTime); time(&m_lastUpdateTime);
if (slave != m_lastSlaveData) { if (slave != m_lastSlaveData) {
m_lastChangeTime = m_lastUpdateTime; m_lastChangeTime = m_lastUpdateTime;
+4
View File
@@ -46,16 +46,20 @@ int main()
// entry: definition, decoded value, master data, slave data, flags // entry: definition, decoded value, master data, slave data, flags
// definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]] // definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
{"x,,ign:10", "", "10fe07000a00000000000000000000", "00", ""}, {"x,,ign:10", "", "10fe07000a00000000000000000000", "00", ""},
{"x,,ign:*", "", "10fe07000a00000000000000000000", "00", "W"},
{"x,,ign,2", "", "", "", "c"}, {"x,,ign,2", "", "", "", "c"},
{"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x,,str:10", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""}, {"x,,str:10", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""},
{"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""}, {"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
{"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
{"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"}, {"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,2", "", "", "", "c"},
{"x,,hex", "20", "10fe07000120", "00", ""}, {"x,,hex", "20", "10fe07000120", "00", ""},
{"x,,hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x,,hex:*", "48 61 6c 6c 6f", "10fe07000548616c6c6f", "00", ""},
{"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"}, {"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
{"x,,hex,2", "", "", "", "c"}, {"x,,hex,2", "", "", "", "c"},
{"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday {"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday