store bit count separately, added ignored type (IGN), moved field length definition from part to type and allow adjusting length for bit types, added PartType masterDataID, simplfied
This commit is contained in:
+182
-150
@@ -29,11 +29,12 @@
|
||||
|
||||
/** the known data field types. */
|
||||
static const dataType_t dataTypes[] = {
|
||||
{"IGN",16*8,bt_str, IGN|ADJ, 0, 1, 16, 0, 0}, // >= 1 byte ignored data
|
||||
{"STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0}, // >= 1 byte character string filled up with space
|
||||
{"HEX",16*8,bt_hexstr, ADJ, 0, 2, 47, 0, 0}, // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
|
||||
{"BDA", 32, bt_dat, BCD, 0, 10, 10, 0, 0}, // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is ignored weekday)
|
||||
{"BDA", 32, bt_dat, BCD, 0, 10, 10, 0, 0}, // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday)
|
||||
{"BDA", 24, bt_dat, BCD, 0, 10, 10, 0, 0}, // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99)
|
||||
{"HDA", 32, bt_dat, 0, 0, 10, 10, 0, 0}, // date, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is ignored weekday) // TODO remove duplicate of BDA
|
||||
{"HDA", 32, bt_dat, 0, 0, 10, 10, 0, 0}, // date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday) // TODO remove duplicate of BDA
|
||||
{"HDA", 24, bt_dat, 0, 0, 10, 10, 0, 0}, // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99) // TODO remove duplicate of BDA
|
||||
{"BTI", 24, bt_tim, BCD|REV, 0, 8, 8, 0, 0}, // time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23)
|
||||
{"HTM", 16, bt_tim, 0, 0, 5, 5, 0, 0}, // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b)
|
||||
@@ -52,41 +53,14 @@ static const dataType_t dataTypes[] = {
|
||||
{"D2C", 16, bt_num, SIG, 0x8000, 0x8001, 0x7fff, 16, 2}, // signed number (fraction 1/16), -2047.9 - +2047.9
|
||||
{"ULG", 32, bt_num, LST, 0xffffffff, 0, 0xfffffffe, 1, 0}, // unsigned integer, 0 - 4294967294
|
||||
{"SLG", 32, bt_num, SIG, 0x80000000, 0x80000001, 0xffffffff, 1, 0}, // signed integer, -2147483647 - +2147483647
|
||||
{"BI0", 1, bt_num, LST, 0, 0, 0x1, 1, 0}, // single bit 0
|
||||
{"BI1", 1, bt_num, LST, 0, 0, 0x1, 1, 1}, // single bit 1
|
||||
{"BI2", 1, bt_num, LST, 0, 0, 0x1, 1, 2}, // single bit 2
|
||||
{"BI3", 1, bt_num, LST, 0, 0, 0x1, 1, 3}, // single bit 3
|
||||
{"BI4", 1, bt_num, LST, 0, 0, 0x1, 1, 4}, // single bit 4
|
||||
{"BI5", 1, bt_num, LST, 0, 0, 0x1, 1, 5}, // single bit 5
|
||||
{"BI6", 1, bt_num, LST, 0, 0, 0x1, 1, 6}, // single bit 6
|
||||
{"BI7", 1, bt_num, LST, 0, 0, 0x1, 1, 7}, // single bit 7
|
||||
{"B01", 2, bt_num, LST, 0, 0, 0x3, 1, 0}, // two bits 0-1
|
||||
{"B12", 2, bt_num, LST, 0, 0, 0x3, 1, 1}, // two bits 1-2
|
||||
{"B23", 2, bt_num, LST, 0, 0, 0x3, 1, 2}, // two bits 2-3
|
||||
{"B34", 2, bt_num, LST, 0, 0, 0x3, 1, 3}, // two bits 3-4
|
||||
{"B45", 2, bt_num, LST, 0, 0, 0x3, 1, 4}, // two bits 4-5
|
||||
{"B56", 2, bt_num, LST, 0, 0, 0x3, 1, 5}, // two bits 5-6
|
||||
{"B67", 2, bt_num, LST, 0, 0, 0x3, 1, 6}, // two bits 6-7
|
||||
{"B02", 3, bt_num, LST, 0, 0, 0x7, 1, 0}, // three bits 0-2
|
||||
{"B13", 3, bt_num, LST, 0, 0, 0x7, 1, 1}, // three bits 1-3
|
||||
{"B24", 3, bt_num, LST, 0, 0, 0x7, 1, 2}, // three bits 2-4
|
||||
{"B35", 3, bt_num, LST, 0, 0, 0x7, 1, 3}, // three bits 3-5
|
||||
{"B46", 3, bt_num, LST, 0, 0, 0x7, 1, 4}, // three bits 4-6
|
||||
{"B57", 3, bt_num, LST, 0, 0, 0x7, 1, 5}, // three bits 5-7
|
||||
{"B03", 4, bt_num, LST, 0, 0, 0xf, 1, 0}, // four bits 0-3
|
||||
{"B14", 4, bt_num, LST, 0, 0, 0xf, 1, 1}, // four bits 1-4
|
||||
{"B25", 4, bt_num, LST, 0, 0, 0xf, 1, 2}, // four bits 2-5
|
||||
{"B36", 4, bt_num, LST, 0, 0, 0xf, 1, 3}, // four bits 3-6
|
||||
{"B47", 4, bt_num, LST, 0, 0, 0xf, 1, 4}, // four bits 4-7
|
||||
{"B04", 5, bt_num, LST, 0, 0, 0x1f, 1, 0}, // five bits 0-4
|
||||
{"B15", 5, bt_num, LST, 0, 0, 0x1f, 1, 1}, // five bits 1-5
|
||||
{"B26", 5, bt_num, LST, 0, 0, 0x1f, 1, 2}, // five bits 2-6
|
||||
{"B37", 5, bt_num, LST, 0, 0, 0x1f, 1, 3}, // five bits 3-7
|
||||
{"B05", 6, bt_num, LST, 0, 0, 0x3f, 1, 0}, // six bits 0-5
|
||||
{"B16", 6, bt_num, LST, 0, 0, 0x3f, 1, 1}, // six bits 1-6
|
||||
{"B27", 6, bt_num, LST, 0, 0, 0x3f, 1, 2}, // six bits 2-7
|
||||
{"B06", 7, bt_num, LST, 0, 0, 0x7f, 1, 0}, // seven bits 0-6
|
||||
{"B17", 7, bt_num, LST, 0, 0, 0x7f, 1, 1}, // seven bits 1-7
|
||||
{"BI0", 7, bt_num, ADJ|LST, 0, 0, 0xef, 1, 0}, // bit 0 (up to 7 bits until bit 6)
|
||||
{"BI1", 7, bt_num, ADJ|LST, 0, 0, 0x7f, 1, 1}, // bit 1 (up to 7 bits until bit 7)
|
||||
{"BI2", 6, bt_num, ADJ|LST, 0, 0, 0x3f, 1, 2}, // bit 2 (up to 6 bits until bit 7)
|
||||
{"BI3", 5, bt_num, ADJ|LST, 0, 0, 0x1f, 1, 3}, // bit 3 (up to 5 bits until bit 7)
|
||||
{"BI4", 4, bt_num, ADJ|LST, 0, 0, 0x0f, 1, 4}, // bit 4 (up to 4 bits until bit 7)
|
||||
{"BI5", 3, bt_num, ADJ|LST, 0, 0, 0x07, 1, 5}, // bit 5 (up to 3 bits until bit 7)
|
||||
{"BI6", 2, bt_num, ADJ|LST, 0, 0, 0x03, 1, 6}, // bit 6 (up to 2 bits until bit 7)
|
||||
{"BI7", 1, bt_num, ADJ|LST, 0, 0, 0x01, 1, 7}, // bit 7
|
||||
};
|
||||
|
||||
|
||||
@@ -132,18 +106,17 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
std::string unit, comment;
|
||||
PartType partType;
|
||||
unsigned int divisor = 0;
|
||||
unsigned char length;
|
||||
const bool isTemplate = dstAddress == SYN;
|
||||
std::string token;
|
||||
if (it == end)
|
||||
break;
|
||||
|
||||
// name;[m|s][len];type[;[divisor|values][;[unit][;[comment]]]]
|
||||
// name;part;type[:len][;[divisor|values][;[unit][;[comment]]]]
|
||||
const std::string name = *it++;
|
||||
if (it == end)
|
||||
break;
|
||||
|
||||
const char* posStr = (*it++).c_str();
|
||||
const char* partStr = (*it++).c_str();
|
||||
if (it == end)
|
||||
break;
|
||||
|
||||
@@ -151,18 +124,17 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
firstName = name;
|
||||
firstComment = comment;
|
||||
}
|
||||
if (dstAddress == BROADCAST || isMaster(dstAddress)
|
||||
|| (isTemplate == false && isSetMessage == true && (posStr[0] == 0 || posStr[0] <= '9'))
|
||||
|| posStr[0] == 'm') { // master data
|
||||
partType = pt_masterData;
|
||||
if (posStr[0] == 'm')
|
||||
posStr++;
|
||||
if (isTemplate == false && strcasecmp(partStr, "I") == 0) {
|
||||
partType = pt_masterDataID;
|
||||
}
|
||||
else if ((isTemplate == false && isSetMessage == false && (posStr[0] == 0 || posStr[0] <= '9'))
|
||||
|| posStr[0] == 's') { // slave data
|
||||
else if (dstAddress == BROADCAST || isMaster(dstAddress)
|
||||
|| (isTemplate == false && isSetMessage == true && partStr[0] == 0)
|
||||
|| strcasecmp(partStr, "M") == 0) { // master data
|
||||
partType = pt_masterData;
|
||||
}
|
||||
else if ((isTemplate == false && isSetMessage == false && partStr[0] == 0)
|
||||
|| strcasecmp(partStr, "S") == 0) { // slave data
|
||||
partType = pt_slaveData;
|
||||
if (posStr[0] == 's')
|
||||
posStr++;
|
||||
}
|
||||
else if (isTemplate) {
|
||||
partType = pt_any;
|
||||
@@ -172,17 +144,10 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
break;
|
||||
}
|
||||
|
||||
if (posStr[0] == 0) {
|
||||
length = 0;
|
||||
}
|
||||
else {
|
||||
length = parseInt(posStr, 10, 1, MAX_POS, result);
|
||||
if (result != RESULT_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
const char* typeStr = (*it++).c_str();
|
||||
if (typeStr[0] == 0) {
|
||||
std::string typeStr = *it++;
|
||||
if (typeStr.empty() == true) {
|
||||
if (name.empty() == false || partStr[0] != 0)
|
||||
result = RESULT_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -190,7 +155,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
if (it != end) {
|
||||
std::string divisorStr = *it++;
|
||||
if (divisorStr.empty() == false) {
|
||||
if (divisorStr.find_first_not_of("0123456789") == std::string::npos) {
|
||||
if (divisorStr.find('=') == std::string::npos) {
|
||||
divisor = parseInt(divisorStr.c_str(), 10, 1, 10000, result);
|
||||
if (result != RESULT_OK)
|
||||
break;
|
||||
@@ -231,47 +196,73 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
comment.clear();
|
||||
}
|
||||
|
||||
// check for reference(s) to templates
|
||||
if (templates.empty() == false) {
|
||||
std::istringstream stream(typeStr);
|
||||
bool found = false;
|
||||
while (std::getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||
std::map< std::string, DataField*>::const_iterator ref = templates.find(token);
|
||||
if (ref == templates.end()) {
|
||||
if (found == false)
|
||||
break; // fallback to direct definition
|
||||
result = RESULT_ERR_INVALID_ARG; // cannot mix reference and direct definition
|
||||
break;
|
||||
size_t pos = typeStr.find(':');
|
||||
unsigned char length;
|
||||
if (pos == std::string::npos) {
|
||||
length = 0;
|
||||
// check for reference(s) to templates
|
||||
if (templates.empty() == false) {
|
||||
std::istringstream stream(typeStr);
|
||||
bool found = false;
|
||||
std::string lengthStr;
|
||||
while (std::getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||
std::map<std::string, DataField*>::const_iterator ref = templates.find(token);
|
||||
if (ref == templates.end()) {
|
||||
if (found == false)
|
||||
break; // fallback to direct definition
|
||||
result = RESULT_ERR_INVALID_ARG; // cannot mix reference and direct definition
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
result = ref->second->derive(name, comment, unit, partType, divisor, values, fields);
|
||||
if (result != RESULT_OK)
|
||||
break;
|
||||
}
|
||||
if (length > 1) {
|
||||
result = RESULT_ERR_INVALID_ARG; // different length not possible for derivation
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
result = ref->second->derive(name, comment, unit, partType, divisor, values, fields);
|
||||
if (result != RESULT_OK)
|
||||
break;
|
||||
if (found == true || result != RESULT_OK)
|
||||
break; // TODO check for found == true
|
||||
}
|
||||
if (found == true || result != RESULT_OK)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
length = parseInt(typeStr.substr(pos+1).c_str(), 10, 1, MAX_POS, result);
|
||||
if (result != RESULT_OK)
|
||||
break;
|
||||
typeStr = typeStr.substr(0, pos);
|
||||
}
|
||||
|
||||
SingleDataField* add = NULL;
|
||||
const char* typeName = typeStr.c_str();
|
||||
for (size_t i = 0; result == RESULT_OK && add == NULL && i < sizeof(dataTypes) / sizeof(dataTypes[0]); i++) {
|
||||
dataType_t dataType = dataTypes[i];
|
||||
if (strcasecmp(typeStr, dataType.name) == 0) {
|
||||
unsigned char numBytes = (dataType.numBits + 7) / 8;
|
||||
unsigned char useLength = length;
|
||||
if ((dataType.flags & ADJ) != 0) {
|
||||
if (useLength == 0)
|
||||
useLength = 1; // minimum length defaults to 1
|
||||
else if (useLength > numBytes) {
|
||||
if (strcasecmp(typeName, dataType.name) == 0) {
|
||||
unsigned char bitCount = dataType.maxBits;
|
||||
unsigned char useLength = (bitCount + 7) / 8;
|
||||
if ((dataType.flags & ADJ) != 0) { // adjustable length
|
||||
if ((bitCount % 8) != 0) {
|
||||
if (length == 0) {
|
||||
useLength = 1; // default length: 1 byte
|
||||
bitCount = 1; // default count: 1 bit
|
||||
}
|
||||
else if (length > bitCount) {
|
||||
result = RESULT_ERR_INVALID_ARG; // invalid length
|
||||
break;
|
||||
}
|
||||
else {
|
||||
bitCount = length;
|
||||
useLength = (length + 7) / 8;
|
||||
}
|
||||
}
|
||||
else if (length == 0) {
|
||||
useLength = 1; // default length: 1 byte
|
||||
}
|
||||
else if (length <= useLength) {
|
||||
useLength = length;
|
||||
}
|
||||
else {
|
||||
result = RESULT_ERR_INVALID_ARG; // invalid length
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (useLength == 0)
|
||||
useLength = numBytes;
|
||||
else if (useLength != numBytes)
|
||||
else if (length > 0 && length != useLength)
|
||||
continue; // check for another one with same name but different length
|
||||
|
||||
switch (dataType.type)
|
||||
@@ -294,7 +285,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
else
|
||||
divisor *= dataType.divisor;
|
||||
|
||||
add = new NumberDataField(name, comment, unit, dataType, partType, useLength, divisor);
|
||||
add = new NumberDataField(name, comment, unit, dataType, partType, useLength, bitCount, divisor);
|
||||
break;
|
||||
}
|
||||
if (values.begin()->first < dataType.minValueOrLength
|
||||
@@ -303,7 +294,7 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
break;
|
||||
}
|
||||
|
||||
add = new ValueListDataField(name, comment, unit, dataType, partType, useLength, values);
|
||||
add = new ValueListDataField(name, comment, unit, dataType, partType, useLength, bitCount, values);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -330,22 +321,17 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||
}
|
||||
|
||||
|
||||
bool SingleDataField::hasFullByteOffset()
|
||||
{
|
||||
return m_length > 1 || (m_dataType.numBits % 8) == 0
|
||||
|| m_dataType.precisionOrFirstBit + (m_dataType.numBits % 8) >= 8;
|
||||
}
|
||||
|
||||
result_t SingleDataField::read(SymbolString& masterData, unsigned char masterOffset,
|
||||
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_slaveData ? masterData : slaveData;
|
||||
unsigned char offset;
|
||||
switch (m_partType)
|
||||
{
|
||||
case pt_masterData:
|
||||
case pt_masterDataID:
|
||||
offset = 5 + masterOffset; // skip QQ ZZ PB SB NN
|
||||
break;
|
||||
case pt_slaveData:
|
||||
@@ -355,7 +341,14 @@ result_t SingleDataField::read(SymbolString& masterData, unsigned char masterOff
|
||||
return RESULT_ERR_INVALID_ARG; // invalid part type
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
if (isIgnored() == true) {
|
||||
if (offset + m_length > input.size()) {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
if (verbose == true)
|
||||
output << m_name << "=";
|
||||
|
||||
result_t result = readSymbols(input, offset, output);
|
||||
@@ -375,11 +368,12 @@ result_t SingleDataField::write(std::istringstream& input,
|
||||
SymbolString& slaveData, unsigned char slaveOffset,
|
||||
char separator)
|
||||
{
|
||||
SymbolString& output = m_partType == pt_masterData ? masterData : slaveData;
|
||||
SymbolString& output = m_partType != pt_slaveData ? masterData : slaveData;
|
||||
unsigned char offset;
|
||||
switch (m_partType)
|
||||
{
|
||||
case pt_masterData:
|
||||
case pt_masterDataID:
|
||||
offset = 5 + masterOffset; // skip QQ ZZ PB SB NN
|
||||
break;
|
||||
case pt_slaveData:
|
||||
@@ -423,6 +417,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
||||
if (baseOffset + m_length > input.size()) {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
|
||||
start = m_length - 1;
|
||||
incr = -1;
|
||||
@@ -494,6 +489,12 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
||||
incr = -1;
|
||||
}
|
||||
|
||||
if (isIgnored() == true) {
|
||||
for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
|
||||
output[baseOffset + offset] = m_dataType.replacement; // fill up with replacement
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
result_t result;
|
||||
size_t i = 0;
|
||||
for (size_t offset = start; i < count; offset += incr, i++) {
|
||||
@@ -581,6 +582,12 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
||||
}
|
||||
|
||||
|
||||
bool NumericDataField::hasFullByteOffset(bool after)
|
||||
{
|
||||
return m_length > 1 || (m_bitCount % 8) == 0
|
||||
|| (after == true && m_bitOffset + (m_bitCount % 8) >= 8);
|
||||
}
|
||||
|
||||
result_t NumericDataField::readRawValue(SymbolString& input,
|
||||
unsigned char baseOffset, unsigned int& value)
|
||||
{
|
||||
@@ -619,9 +626,10 @@ result_t NumericDataField::readRawValue(SymbolString& input,
|
||||
|
||||
if ((m_dataType.flags & BCD) == 0) {
|
||||
value >>= m_bitOffset;
|
||||
if ((m_dataType.numBits % 8) != 0)
|
||||
value &= (1 << m_dataType.numBits) - 1;
|
||||
if ((m_bitCount % 8) != 0)
|
||||
value &= (1 << m_bitCount) - 1;
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -638,8 +646,9 @@ result_t NumericDataField::writeRawValue(unsigned int value,
|
||||
}
|
||||
|
||||
if ((m_dataType.flags & BCD) == 0) {
|
||||
if ((m_dataType.numBits % 8) != 0)
|
||||
value &= (1 << m_dataType.numBits) - 1;
|
||||
if ((m_bitCount % 8) != 0 && (value & ~((1 << m_bitCount) - 1)) != 0)
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
|
||||
value <<= m_bitOffset;
|
||||
}
|
||||
for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) {
|
||||
@@ -656,7 +665,7 @@ result_t NumericDataField::writeRawValue(unsigned int value,
|
||||
ch = (value / exp) & 0xff;
|
||||
exp = exp << 8;
|
||||
}
|
||||
if (offset == start && (m_dataType.numBits % 8) != 0 && baseOffset + offset < output.size())
|
||||
if (offset == start && (m_bitCount % 8) != 0 && baseOffset + offset < output.size())
|
||||
output[baseOffset + offset] |= ch;
|
||||
else
|
||||
output[baseOffset + offset] = ch;
|
||||
@@ -687,10 +696,10 @@ result_t NumberDataField::derive(std::string name, std::string comment,
|
||||
if (divisor != 1)
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
|
||||
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, m_bitCount, values));
|
||||
}
|
||||
else
|
||||
fields.push_back(new NumberDataField(name, comment, unit, m_dataType, partType, m_length, divisor));
|
||||
fields.push_back(new NumberDataField(name, comment, unit, m_dataType, partType, m_length, m_bitCount, divisor));
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -710,27 +719,27 @@ result_t NumberDataField::readSymbols(SymbolString& input,
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
bool negative = (m_dataType.flags & SIG) != 0 && (value & (1 << (m_dataType.numBits - 1))) != 0;
|
||||
if (m_dataType.numBits == 32) {
|
||||
bool negative = (m_dataType.flags & SIG) != 0 && (value & (1 << (m_bitCount - 1))) != 0;
|
||||
if (m_bitCount == 32) {
|
||||
if (negative == false) {
|
||||
if (m_divisor <= 1)
|
||||
output << static_cast<unsigned>(value);
|
||||
else
|
||||
output << std::setprecision((m_dataType.numBits % 8) == 0 ? m_dataType.precisionOrFirstBit : 0)
|
||||
output << std::setprecision((m_bitCount % 8) == 0 ? m_dataType.precisionOrFirstBit : 0)
|
||||
<< std::fixed << static_cast<float>(value / (float) m_divisor);
|
||||
return RESULT_OK;
|
||||
}
|
||||
signedValue = (int) value; // negative signed value
|
||||
}
|
||||
else if (negative) // negative signed value
|
||||
signedValue = (int) value - (1 << m_dataType.numBits);
|
||||
signedValue = (int) value - (1 << m_bitCount);
|
||||
else
|
||||
signedValue = (int) value;
|
||||
|
||||
if (m_divisor <= 1)
|
||||
output << static_cast<int>(signedValue);
|
||||
else
|
||||
output << std::setprecision((m_dataType.numBits % 8) == 0 ? m_dataType.precisionOrFirstBit : 0)
|
||||
output << std::setprecision((m_bitCount % 8) == 0 ? m_dataType.precisionOrFirstBit : 0)
|
||||
<< std::fixed << static_cast<float>(signedValue / (float) m_divisor);
|
||||
|
||||
return RESULT_OK;
|
||||
@@ -742,18 +751,17 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
|
||||
unsigned int value;
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
if (strcasecmp(str, NULL_VALUE) == 0)
|
||||
// replacement value
|
||||
value = m_dataType.replacement;
|
||||
if (isIgnored() == true || strcasecmp(str, NULL_VALUE) == 0)
|
||||
value = m_dataType.replacement; // replacement value
|
||||
else if (str == NULL || *str == 0)
|
||||
return RESULT_ERR_INVALID_ARG; // input too short
|
||||
return RESULT_ERR_INVALID_ARG; // input too short//TODO LENGTH_SEPARATOR
|
||||
else {
|
||||
char* strEnd = NULL;
|
||||
if (m_divisor <= 1) {
|
||||
if ((m_dataType.flags & SIG) != 0) {
|
||||
int signedValue = strtol(str, &strEnd, 10);
|
||||
if (signedValue < 0 && m_dataType.numBits != 32)
|
||||
value = (unsigned int) (signedValue + (1 << m_dataType.numBits));
|
||||
if (signedValue < 0 && m_bitCount != 32)
|
||||
value = (unsigned int) (signedValue + (1 << m_bitCount));
|
||||
else
|
||||
value = (unsigned int) signedValue;
|
||||
}
|
||||
@@ -771,8 +779,8 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
|
||||
if ((m_dataType.flags & SIG) != 0) {
|
||||
if (dvalue < -(1LL << (8 * m_length)) || dvalue >= (1LL << (8 * m_length)))
|
||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
||||
if (dvalue < 0 && m_dataType.numBits != 32)
|
||||
value = (unsigned int) (dvalue + (1 << m_dataType.numBits));
|
||||
if (dvalue < 0 && m_bitCount != 32)
|
||||
value = (unsigned int) (dvalue + (1 << m_bitCount));
|
||||
else
|
||||
value = (unsigned int) dvalue;
|
||||
}
|
||||
@@ -784,7 +792,7 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
|
||||
}
|
||||
|
||||
if ((m_dataType.flags & SIG) != 0) { // signed value
|
||||
if ((value & (1 << (m_dataType.numBits - 1))) != 0) { // negative signed value
|
||||
if ((value & (1 << (m_bitCount - 1))) != 0) { // negative signed value
|
||||
if (value < m_dataType.minValueOrLength)
|
||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
||||
}
|
||||
@@ -823,7 +831,7 @@ result_t ValueListDataField::derive(std::string name, std::string comment,
|
||||
else
|
||||
values = m_values;
|
||||
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, m_dataType, partType, m_length, m_bitCount, values));
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -854,14 +862,17 @@ result_t ValueListDataField::readSymbols(SymbolString& input,
|
||||
result_t ValueListDataField::writeSymbols(std::istringstream& input,
|
||||
unsigned char baseOffset, SymbolString& output)
|
||||
{
|
||||
if (isIgnored() == true)
|
||||
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value
|
||||
|
||||
const char* str = input.str().c_str();
|
||||
|
||||
for (std::map<unsigned int, std::string>::iterator it = m_values.begin(); it != m_values.end(); it++)
|
||||
if (it->second.compare(str) == 0)
|
||||
return writeRawValue(it->first, baseOffset, output);
|
||||
|
||||
if (strcasecmp(str, NULL_VALUE) == 0) // replacement value
|
||||
return writeRawValue(m_dataType.replacement, baseOffset, output);
|
||||
if (strcasecmp(str, NULL_VALUE) == 0)
|
||||
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value
|
||||
|
||||
return RESULT_ERR_INVALID_ARG; // value assignment not found
|
||||
}
|
||||
@@ -878,15 +889,17 @@ unsigned char DataFieldSet::getLength(PartType partType)
|
||||
{
|
||||
unsigned char length = 0;
|
||||
|
||||
bool previousFullByteOffset[] = { true, true, true };
|
||||
bool previousFullByteOffset[] = { true, true, true, true };
|
||||
|
||||
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (field->getPartType() == partType) {
|
||||
length += field->getLength(partType);
|
||||
if (previousFullByteOffset[partType] == false) {
|
||||
if (previousFullByteOffset[partType] == false && field->hasFullByteOffset(false) == false)
|
||||
length--;
|
||||
}
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset();
|
||||
|
||||
length += field->getLength(partType);
|
||||
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,29 +931,38 @@ result_t DataFieldSet::read(SymbolString& masterData, unsigned char masterOffset
|
||||
output << m_name << "={ ";
|
||||
|
||||
bool first = true;
|
||||
unsigned char offsets[] = { 0, masterOffset, slaveOffset };
|
||||
bool previousFullByteOffset[] = { true, true, true };
|
||||
unsigned char offsets[4];
|
||||
memset(offsets, 0, sizeof(offsets));
|
||||
offsets[pt_masterData] = masterOffset;
|
||||
offsets[pt_slaveData] = slaveOffset;
|
||||
bool previousFullByteOffset[] = { true, true, true, true };
|
||||
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
output << separator;
|
||||
|
||||
SingleDataField* field = *it;
|
||||
bool ignored = field->isIgnored();
|
||||
PartType partType = field->getPartType();
|
||||
if (previousFullByteOffset[partType] == false) {
|
||||
offsets[partType]--;
|
||||
|
||||
if (ignored == false) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
output << separator;
|
||||
}
|
||||
if (partType == pt_masterDataID)
|
||||
partType = pt_masterData;
|
||||
if (previousFullByteOffset[partType] == false && field->hasFullByteOffset(false) == false)
|
||||
offsets[partType]--;
|
||||
|
||||
result_t result = field->read(masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], output, verbose, separator);
|
||||
|
||||
if (result != RESULT_OK)
|
||||
return result;
|
||||
|
||||
offsets[partType] += field->getLength(partType);
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset();
|
||||
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset(true);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
if (verbose == true) {
|
||||
if (m_comment.length() > 0)
|
||||
output << " [" << m_comment << "]";
|
||||
output << "}";
|
||||
@@ -956,18 +978,28 @@ result_t DataFieldSet::write(std::istringstream& input,
|
||||
{
|
||||
std::string token;
|
||||
|
||||
unsigned char offsets[] = { 0, masterOffset, slaveOffset };
|
||||
bool previousFullByteOffset[] = { true, true, true };
|
||||
unsigned char offsets[4];
|
||||
memset(offsets, 0, sizeof(offsets));
|
||||
offsets[pt_masterData] = masterOffset;
|
||||
offsets[pt_slaveData] = slaveOffset;
|
||||
bool previousFullByteOffset[] = { true, true, true, true };
|
||||
for (std::vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
bool ignored = field->isIgnored();
|
||||
PartType partType = field->getPartType();
|
||||
if (previousFullByteOffset[partType] == false) {
|
||||
|
||||
if (partType == pt_masterDataID)
|
||||
partType = pt_masterData;
|
||||
if (previousFullByteOffset[partType] == false && field->hasFullByteOffset(false) == false)
|
||||
offsets[partType]--;
|
||||
}
|
||||
|
||||
result_t result;
|
||||
if (m_fields.size() > 1) {
|
||||
if (std::getline(input, token, separator) == 0)
|
||||
if (ignored == true)
|
||||
token.clear();
|
||||
else if (std::getline(input, token, separator) == 0)
|
||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
||||
|
||||
std::istringstream single(token);
|
||||
result = (*it)->write(single, masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], separator);
|
||||
}
|
||||
@@ -978,7 +1010,7 @@ result_t DataFieldSet::write(std::istringstream& input,
|
||||
return result;
|
||||
|
||||
offsets[partType] += field->getLength(partType);
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset();
|
||||
previousFullByteOffset[partType] = field->hasFullByteOffset(true);
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
|
||||
+30
-13
@@ -28,9 +28,10 @@
|
||||
|
||||
/** the message part in which a data field is stored. */
|
||||
enum PartType {
|
||||
pt_any, // stored in any data (master or slave)
|
||||
pt_masterData, // stored in master data
|
||||
pt_slaveData, // stored in slave data
|
||||
pt_any, // stored in any data (master or slave)
|
||||
pt_masterData, // stored in master data
|
||||
pt_masterDataID, // stored in master data and also used as message ID part
|
||||
pt_slaveData, // stored in slave data
|
||||
};
|
||||
|
||||
/** the available base data types. */
|
||||
@@ -49,11 +50,12 @@ const unsigned int REV = 0x04; // reverted binary representation (most significa
|
||||
const unsigned int SIG = 0x08; // signed value
|
||||
const unsigned int LST = 0x10; // value list is possible (without applied divisor)
|
||||
const unsigned int DAY = 0x20; // forced value list defaulting to week days
|
||||
const unsigned int IGN = 0x40; // ignore value during read and write
|
||||
|
||||
/** the structure for defining field types with their properties. */
|
||||
typedef struct {
|
||||
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 @a BCD)
|
||||
const unsigned int maxBits; // 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 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)
|
||||
@@ -208,6 +210,11 @@ public:
|
||||
* @return the value unit.
|
||||
*/
|
||||
std::string getUnit() const { return m_unit; }
|
||||
/**
|
||||
* @brief Get whether this field is ignored.
|
||||
* @return whether this field is ignored.
|
||||
*/
|
||||
bool isIgnored() const { return (m_dataType.flags & IGN) != 0; }
|
||||
/**
|
||||
* @brief Get the message part in which the field is stored.
|
||||
* @return the message part in which the field is stored.
|
||||
@@ -218,10 +225,11 @@ public:
|
||||
// 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.
|
||||
* @param after @p true to check after consuming the bits, false to check before.
|
||||
* @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();
|
||||
virtual bool hasFullByteOffset(bool after) { return true; }
|
||||
/**
|
||||
* @brief Reads the value from the master or slave @a SymbolString.
|
||||
* @param masterData the unescaped master data @a SymbolString for reading binary data.
|
||||
@@ -337,17 +345,20 @@ public:
|
||||
* @param dataType the data type definition.
|
||||
* @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 bitCount the number of bits 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,
|
||||
const std::string unit, const dataType_t dataType, const PartType partType,
|
||||
const unsigned char length, const unsigned char bitOffset)
|
||||
const unsigned char length, const unsigned char bitCount, const unsigned char bitOffset)
|
||||
: SingleDataField(name, comment, unit, dataType, partType, length),
|
||||
m_bitOffset(bitOffset) {}
|
||||
m_bitCount(bitCount), m_bitOffset(bitOffset) {}
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~NumericDataField() {}
|
||||
// @copydoc
|
||||
virtual bool hasFullByteOffset(bool after);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -368,9 +379,13 @@ protected:
|
||||
*/
|
||||
result_t writeRawValue(unsigned int value, const unsigned char offset, SymbolString& output);
|
||||
|
||||
/** the number of bits in the binary value. */
|
||||
const unsigned char m_bitCount;
|
||||
|
||||
/** the offset to the first bit in the binary value. */
|
||||
const unsigned char m_bitOffset;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -393,9 +408,10 @@ public:
|
||||
*/
|
||||
NumberDataField(const std::string name, const std::string comment,
|
||||
const std::string unit, const dataType_t dataType, const PartType partType,
|
||||
const unsigned char length, const unsigned int divisor)
|
||||
: NumericDataField(name, comment, unit, dataType, partType, length,
|
||||
(dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0),
|
||||
const unsigned char length, const unsigned char bitCount,
|
||||
const unsigned int divisor)
|
||||
: NumericDataField(name, comment, unit, dataType, partType, length, bitCount,
|
||||
(dataType.maxBits < 8) ? dataType.precisionOrFirstBit : 0),
|
||||
m_divisor(divisor) {}
|
||||
/**
|
||||
* @brief Destructor.
|
||||
@@ -439,9 +455,10 @@ public:
|
||||
*/
|
||||
ValueListDataField(const std::string name, const std::string comment,
|
||||
const std::string unit, const dataType_t dataType, const PartType partType,
|
||||
const unsigned char length, const std::map<unsigned int, std::string> values)
|
||||
: NumericDataField(name, comment, unit, dataType, partType, length,
|
||||
(dataType.numBits%8) != 0 ? dataType.precisionOrFirstBit : 0),
|
||||
const unsigned char length, const unsigned char bitCount,
|
||||
const std::map<unsigned int, std::string> values)
|
||||
: NumericDataField(name, comment, unit, dataType, partType, length, bitCount,
|
||||
(dataType.maxBits < 8) ? dataType.precisionOrFirstBit : 0),
|
||||
m_values(values) {}
|
||||
/**
|
||||
* @brief Destructor.
|
||||
|
||||
@@ -43,21 +43,23 @@ int main()
|
||||
{
|
||||
std::string checks[][5] = {
|
||||
//name;[len];type[;[divisor|values][;[unit][;[comment]]]], decoded value, master, slave, flags
|
||||
{"x;10;str", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x;10;str", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""},
|
||||
{"x;10;str", " ", "10fe07000a20202020202020202020", "00", ""},
|
||||
{"x;11;str", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x;;ign:10", "", "10fe07000a00000000000000000000", "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", " ", "10fe07000a20202020202020202020", "00", ""},
|
||||
{"x;;str:11", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x;;hex", "20", "10fe07000120", "00", ""},
|
||||
{"x;10;hex", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x;11;hex", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
|
||||
{"x;;hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x;;hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
|
||||
{"x;;bda", "26.10.2014","10fe07000426100014", "00", ""},
|
||||
{"x;;bda", "01.01.2000","10fe07000401010000", "00", ""},
|
||||
{"x;;bda", "31.12.2099","10fe07000431120099", "00", ""},
|
||||
{"x;;bda", "", "10fe07000432100014", "00", "rw"},
|
||||
{"x;3;bda","26.10.2014","10fe070003261014", "00", ""},
|
||||
{"x;3;bda","01.01.2000","10fe070003010100", "00", ""},
|
||||
{"x;3;bda","31.12.2099","10fe070003311299", "00", ""},
|
||||
{"x;3;bda","", "10fe070003321299", "00", "rw"},
|
||||
{"x;;bda:3","26.10.2014","10fe070003261014", "00", ""},
|
||||
{"x;;bda:3","01.01.2000","10fe070003010100", "00", ""},
|
||||
{"x;;bda:3","31.12.2099","10fe070003311299", "00", ""},
|
||||
{"x;;bda:3","", "10fe070003321299", "00", "rw"},
|
||||
{"x;;bti", "21:04:58", "10fe070003580421", "00", ""},
|
||||
{"x;;bti", "00:00:00", "10fe070003000000", "00", ""},
|
||||
{"x;;bti", "23:59:59", "10fe070003595923", "00", ""},
|
||||
@@ -84,8 +86,8 @@ int main()
|
||||
{"x;;bcd", "99", "10feffff0199", "00", ""},
|
||||
{"x;;bcd", "-", "10feffff01ff", "00", ""},
|
||||
{"x;;bcd", "", "10feffff019a", "00", "rw"},
|
||||
{"x;16;str", "0123456789ABCDEF", "10feffff1130313233343536373839414243444546", "00", ""},
|
||||
{"x;17;uch", "", "10feffff00", "00", "c"},
|
||||
{"x;;str:16", "0123456789ABCDEF", "10feffff1130313233343536373839414243444546", "00", ""},
|
||||
{"x;;uch:17", "", "10feffff00", "00", "c"},
|
||||
{"x;s;uch", "0", "1025ffff0310111213", "0300010203", "W"},
|
||||
{"x;s;uch", "0", "1025ffff00", "0100", ""},
|
||||
{"x;s;uch;;;;y;m;uch", "2;3","1025ffff0103", "0102", ""},
|
||||
@@ -148,14 +150,15 @@ int main()
|
||||
{"x;;bi3", "-", "10feffff0100", "00", ""},
|
||||
{"x;;bi3;0=off,1=on","on", "10feffff0108", "00", ""},
|
||||
{"x;;bi3;0=off,1=on","off","10feffff0100", "00", ""},
|
||||
{"x;;b34", "1", "10feffff0108", "00", ""},
|
||||
{"x;;b34", "-", "10feffff0100", "00", ""},
|
||||
{"x;;b34", "3", "10feffff0118", "00", ""},
|
||||
{"x;;b34;1=on","on", "10feffff0108", "00", ""},
|
||||
{"x;;b34;1=on","-", "10feffff0100", "00", ""},
|
||||
{"x;;b34;0=off,1=on,2=auto,3=eco","auto", "10feffff0110", "00", ""},
|
||||
{"x;;b34;0=off,1=on","on", "10feffff0108", "00", ""},
|
||||
{"x;;b34;0=off,1=on","off","10feffff0100", "00", ""},
|
||||
{"x;;bi3:2", "1", "10feffff0108", "00", ""},
|
||||
{"x;;bi3:2", "1", "10feffff01ef", "00", "W"},
|
||||
{"x;;bi3:2", "-", "10feffff0100", "00", ""},
|
||||
{"x;;bi3:2", "3", "10feffff0118", "00", ""},
|
||||
{"x;;bi3:2;1=on","on", "10feffff0108", "00", ""},
|
||||
{"x;;bi3:2;1=on","-", "10feffff0100", "00", ""},
|
||||
{"x;;bi3:2;0=off,1=on,2=auto,3=eco","auto", "10feffff0110", "00", ""},
|
||||
{"x;;bi3:2;0=off,1=on","on", "10feffff0108", "00", ""},
|
||||
{"x;;bi3:2;0=off,1=on","off","10feffff0100", "00", ""},
|
||||
{"x;;uch;1=test,2=high,3=off,4=on","on","10feffff0104", "00", ""},
|
||||
{"x;s;uch","3","1050ffff00", "0103", ""},
|
||||
{"x;;d2b;;°C;Aussentemperatur","x=18.004 °C [Aussentemperatur]","10fe0700090112", "00", "v"},
|
||||
@@ -164,8 +167,8 @@ int main()
|
||||
{"x;;bi3;;;;y;;bi5", "1;1", "10feffff0128", "00", ""}, // bit combination
|
||||
{"x;;bi3;;;;y;;bi5", "-;1", "10feffff0120", "00", ""}, // bit combination
|
||||
{"x;;bi3;;;;y;;bi5", "-;-", "10feffff0100", "00", ""}, // bit combination
|
||||
{"x;;bi3;;;;y;;bi7;;;;t;;uch", "-;-;9","10feffff020009", "00", ""}, // bit combination, auto pos incr
|
||||
{"x;;bi3;;;;y;;bi5;;;;t;;uch", "-;-;9","10feffff020009", "00", "RW"}, // bit combination
|
||||
{"x;;bi3;;;;y;;bi7;;;;t;;uch", "-;-;9","10feffff020009", "00", ""}, // bit combination
|
||||
{"x;;bi6:2;;;;y;;bi0:2;;;;t;;uch", "2;1;9","10feffff03800109", "00", ""}, // bit combination
|
||||
{"temp;;d2b;;°C;Aussentemperatur","","", "", "t"}, // template with relative pos
|
||||
{"x;;temp","18.004","10fe0700020112", "00", ""}, // reference to template
|
||||
{"relrel;;d2b;;;;y;;d1c","","", "", "t"}, // template struct with relative pos
|
||||
@@ -202,7 +205,6 @@ int main()
|
||||
}
|
||||
std::vector<std::string>::iterator it = entries.begin();
|
||||
result_t result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate ? SYN : mstr[1]);
|
||||
|
||||
if (failedCreate == true) {
|
||||
if (result == RESULT_OK)
|
||||
std::cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user