also detect subsequent fields with less than 8 bits not fitting into 1 byte
This commit is contained in:
+23
-11
@@ -647,8 +647,11 @@ size_t SingleDataField::getLength(PartType partType, size_t maxLength) const {
|
|||||||
return remainder ? maxLength : m_length;
|
return remainder ? maxLength : m_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleDataField::hasFullByteOffset(bool after) const {
|
bool SingleDataField::hasFullByteOffset(bool after, int16_t& previousFirstBit) const {
|
||||||
if (m_length > 1) {
|
if (m_length > 1) {
|
||||||
|
if (after) {
|
||||||
|
previousFirstBit = -1;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int16_t firstBit;
|
int16_t firstBit;
|
||||||
@@ -658,8 +661,13 @@ bool SingleDataField::hasFullByteOffset(bool after) const {
|
|||||||
} else {
|
} else {
|
||||||
firstBit = 0;
|
firstBit = 0;
|
||||||
}
|
}
|
||||||
return (m_dataType->getBitCount() % 8) == 0
|
bool ret = (m_dataType->getBitCount() % 8) == 0
|
||||||
|| (after && firstBit + (m_dataType->getBitCount() % 8) >= 8);
|
|| (firstBit == previousFirstBit) || (after && firstBit + (m_dataType->getBitCount() % 8) >= 8);
|
||||||
|
// std::cout<<(after?"after,":"before,")<<"prev="<<static_cast<unsigned>(previousFirstBit)<<",first="<<static_cast<unsigned>(firstBit)<<",length="<<static_cast<unsigned>(m_dataType->getBitCount())<<" => "<<(ret?"true":"false")<<"\n";
|
||||||
|
if (after) {
|
||||||
|
previousFirstBit = ret ? -1 : firstBit;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SingleDataField::getCount(PartType partType, const char* fieldName) const {
|
size_t SingleDataField::getCount(PartType partType, const char* fieldName) const {
|
||||||
@@ -915,9 +923,10 @@ const DataFieldSet* DataFieldSet::clone() const {
|
|||||||
size_t DataFieldSet::getLength(PartType partType, size_t maxLength) const {
|
size_t DataFieldSet::getLength(PartType partType, size_t maxLength) const {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
bool previousFullByteOffset[] = { true, true, true, true };
|
bool previousFullByteOffset[] = { true, true, true, true };
|
||||||
|
int16_t previousFirstBit[] = { -1, -1, -1, -1 };
|
||||||
for (const auto field : m_fields) {
|
for (const auto field : m_fields) {
|
||||||
if (field->getPartType() == partType) {
|
if (field->getPartType() == partType) {
|
||||||
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) {
|
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false, previousFirstBit[partType])) {
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
size_t fieldLength = field->getLength(partType, maxLength);
|
size_t fieldLength = field->getLength(partType, maxLength);
|
||||||
@@ -928,7 +937,7 @@ size_t DataFieldSet::getLength(PartType partType, size_t maxLength) const {
|
|||||||
}
|
}
|
||||||
length = length + fieldLength;
|
length = length + fieldLength;
|
||||||
|
|
||||||
previousFullByteOffset[partType] = field->hasFullByteOffset(true);
|
previousFullByteOffset[partType] = field->hasFullByteOffset(true, previousFirstBit[partType]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1010,12 +1019,13 @@ void DataFieldSet::dump(bool prependFieldSeparator, bool asJson, ostream* output
|
|||||||
result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
||||||
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const {
|
const char* fieldName, ssize_t fieldIndex, unsigned int* output) const {
|
||||||
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldIndex >= 0;
|
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldIndex >= 0;
|
||||||
|
int16_t previousFirstBit = -1;
|
||||||
PartType partType = data.isMaster() ? pt_masterData : pt_slaveData;
|
PartType partType = data.isMaster() ? pt_masterData : pt_slaveData;
|
||||||
for (const auto field : m_fields) {
|
for (const auto field : m_fields) {
|
||||||
if (field->getPartType() != partType) {
|
if (field->getPartType() != partType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
if (!previousFullByteOffset && !field->hasFullByteOffset(false, previousFirstBit)) {
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
result_t result = field->read(data, offset, fieldName, fieldIndex, output);
|
result_t result = field->read(data, offset, fieldName, fieldIndex, output);
|
||||||
@@ -1023,7 +1033,7 @@ result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
offset += field->getLength(partType, data.getDataSize()-offset);
|
offset += field->getLength(partType, data.getDataSize()-offset);
|
||||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
previousFullByteOffset = field->hasFullByteOffset(true, previousFirstBit);
|
||||||
if (result != RESULT_EMPTY) {
|
if (result != RESULT_EMPTY) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@@ -1049,6 +1059,7 @@ result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
|||||||
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
|
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex,
|
||||||
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const {
|
OutputFormat outputFormat, ssize_t outputIndex, ostream* output) const {
|
||||||
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldIndex >= 0;
|
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldIndex >= 0;
|
||||||
|
int16_t previousFirstBit = -1;
|
||||||
if (outputIndex < 0 && (!m_uniqueNames || ((outputFormat & OF_JSON) && !(outputFormat & OF_NAMES)))) {
|
if (outputIndex < 0 && (!m_uniqueNames || ((outputFormat & OF_JSON) && !(outputFormat & OF_NAMES)))) {
|
||||||
outputIndex = 0;
|
outputIndex = 0;
|
||||||
}
|
}
|
||||||
@@ -1060,7 +1071,7 @@ result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
if (!previousFullByteOffset && !field->hasFullByteOffset(false, previousFirstBit)) {
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
result_t result = field->read(data, offset, leadingSeparator, fieldName, fieldIndex,
|
result_t result = field->read(data, offset, leadingSeparator, fieldName, fieldIndex,
|
||||||
@@ -1069,7 +1080,7 @@ result_t DataFieldSet::read(const SymbolString& data, size_t offset,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
offset += field->getLength(partType, data.getDataSize()-offset);
|
offset += field->getLength(partType, data.getDataSize()-offset);
|
||||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
previousFullByteOffset = field->hasFullByteOffset(true, previousFirstBit);
|
||||||
if (result != RESULT_EMPTY) {
|
if (result != RESULT_EMPTY) {
|
||||||
found = true;
|
found = true;
|
||||||
leadingSeparator = true;
|
leadingSeparator = true;
|
||||||
@@ -1099,12 +1110,13 @@ result_t DataFieldSet::write(char separator, size_t offset, istringstream* input
|
|||||||
string token;
|
string token;
|
||||||
PartType partType = data->isMaster() ? pt_masterData : pt_slaveData;
|
PartType partType = data->isMaster() ? pt_masterData : pt_slaveData;
|
||||||
bool previousFullByteOffset = true;
|
bool previousFullByteOffset = true;
|
||||||
|
int16_t previousFirstBit = -1;
|
||||||
size_t baseOffset = offset;
|
size_t baseOffset = offset;
|
||||||
for (const auto field : m_fields) {
|
for (const auto field : m_fields) {
|
||||||
if (field->getPartType() != partType) {
|
if (field->getPartType() != partType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
if (!previousFullByteOffset && !field->hasFullByteOffset(false, previousFirstBit)) {
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
result_t result;
|
result_t result;
|
||||||
@@ -1124,7 +1136,7 @@ result_t DataFieldSet::write(char separator, size_t offset, istringstream* input
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
offset += fieldLength;
|
offset += fieldLength;
|
||||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
previousFullByteOffset = field->hasFullByteOffset(true, previousFirstBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usedLength != nullptr) {
|
if (usedLength != nullptr) {
|
||||||
|
|||||||
+4
-1
@@ -401,10 +401,13 @@ class SingleDataField : public DataField {
|
|||||||
/**
|
/**
|
||||||
* Get whether this field uses a full byte offset.
|
* Get whether this field uses a full byte offset.
|
||||||
* @param after @p true to check after consuming the bits, @p false to check before.
|
* @param after @p true to check after consuming the bits, @p false to check before.
|
||||||
|
* @param previousFirstBit the index to the first bit of the previous field, or -1
|
||||||
|
* if the previous field used a full byte offset. Will be updated during the call
|
||||||
|
* when after was true.
|
||||||
* @return @p true if this field uses a full byte offset, @p false if this field
|
* @return @p true if this field uses a full byte offset, @p false if this field
|
||||||
* only consumes a part of a byte and a subsequent field may re-use the same offset.
|
* only consumes a part of a byte and a subsequent field may re-use the same offset.
|
||||||
*/
|
*/
|
||||||
bool hasFullByteOffset(bool after) const;
|
bool hasFullByteOffset(bool after, int16_t& previousFirstBit) const;
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
size_t getCount(PartType partType = pt_any, const char* fieldName = nullptr) const override;
|
size_t getCount(PartType partType = pt_any, const char* fieldName = nullptr) const override;
|
||||||
|
|||||||
@@ -228,6 +228,9 @@ int main() {
|
|||||||
{"x,,ttq", "23:45", "10fe0700015f", "00", ""},
|
{"x,,ttq", "23:45", "10fe0700015f", "00", ""},
|
||||||
{"x,,ttq", "24:00", "10fe07000160", "00", ""},
|
{"x,,ttq", "24:00", "10fe07000160", "00", ""},
|
||||||
{"x,,ttq", "-:-", "10fe07000100", "00", ""},
|
{"x,,ttq", "-:-", "10fe07000100", "00", ""},
|
||||||
|
{"x,,ttq,,,,,,ttq", "23:00;05:45", "10fe0700025c17", "00", ""},
|
||||||
|
{"x,,ttq,,,,,,bi7,,,,,,ttq", "23:00;0;05:45", "10fe0700025c17", "00", ""},
|
||||||
|
{"x,,ttq,,,,,,bi7,,,,,,ttq", "23:00;1;05:45", "10fe070002dc17", "00", ""},
|
||||||
{"x,,ttq", "", "10fe07000161", "00", "rw"},
|
{"x,,ttq", "", "10fe07000161", "00", "rw"},
|
||||||
{"x,,ttq,2", "", "", "", "c"},
|
{"x,,ttq,2", "", "", "", "c"},
|
||||||
{"x,,ttq,,,,y,,bi7", "23:45;0", "10fe0700015f", "00", ""}, // bit combination
|
{"x,,ttq,,,,y,,bi7", "23:45;0", "10fe0700015f", "00", ""}, // bit combination
|
||||||
|
|||||||
Reference in New Issue
Block a user