diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index b5fc07b6..b151c8e1 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -657,6 +657,10 @@ bool SingleDataField::hasFullByteOffset(bool after) const { || (after && firstBit + (m_dataType->getBitCount() % 8) >= 8); } +size_t SingleDataField::getCount(PartType partType, const char* fieldName) const { + return isIgnored() || (partType != pt_any && partType != m_partType) || (fieldName != NULL && m_name != fieldName) ? 0 : 1; +} + const ValueListDataField* ValueListDataField::clone() const { return new ValueListDataField(*this); @@ -925,6 +929,17 @@ size_t DataFieldSet::getLength(PartType partType, size_t maxLength) const { return length; } +size_t DataFieldSet::getCount(PartType partType, const char* fieldName) const { + if (partType == pt_any && fieldName == NULL) { + return m_fields.size() - m_ignoredCount; + } + size_t count = 0; + for (auto field : m_fields) { + count += field->getCount(partType, fieldName); + } + return count; +} + string DataFieldSet::getName(ssize_t fieldIndex) const { if (fieldIndex < (ssize_t)m_ignoredCount) { return m_name; @@ -988,7 +1003,7 @@ void DataFieldSet::dump(bool prependFieldSeparator, bool asJson, ostream* output result_t DataFieldSet::read(const SymbolString& data, size_t offset, const char* fieldName, ssize_t fieldIndex, unsigned int* output) const { - bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; + bool previousFullByteOffset = true, found = false, findFieldIndex = fieldIndex >= 0; PartType partType = data.isMaster() ? pt_masterData : pt_slaveData; for (const auto field : m_fields) { if (field->getPartType() != partType) { diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 27507b24..117eda0c 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -251,9 +251,11 @@ class DataField : public AttributedItem { /** * Get the field count (excluding ignored fields). + * @param partType the optional part to count, or @ pt_any. + * @param fieldName the optional field name to count, or NULL. * @return the field count (excluding ignored fields). */ - virtual size_t getCount() const = 0; + virtual size_t getCount(PartType partType = pt_any, const char* fieldName = NULL) const = 0; /** * Get the specified field name. @@ -399,7 +401,7 @@ class SingleDataField : public DataField { bool hasFullByteOffset(bool after) const; // @copydoc - size_t getCount() const override { return isIgnored() ? 0 : 1; } + size_t getCount(PartType partType = pt_any, const char* fieldName = NULL) const override; // @copydoc virtual string getName(ssize_t fieldIndex) const { @@ -638,7 +640,7 @@ class DataFieldSet : public DataField { size_t getLength(PartType partType, size_t maxLength) const override; // @copydoc - size_t getCount() const override { return m_fields.size() - m_ignoredCount; } + size_t getCount(PartType partType = pt_any, const char* fieldName = NULL) const override; // @copydoc string getName(ssize_t fieldIndex) const override; diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 01aed497..50156e80 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -727,7 +727,7 @@ result_t Message::decodeLastData(bool master, bool leadingSeparator, const char* if (result < RESULT_OK) { return result; } - if (result == RESULT_EMPTY && fieldName != NULL) { + if (result == RESULT_EMPTY && (fieldName != NULL || fieldIndex >= 0)) { return RESULT_ERR_NOTFOUND; } return result; @@ -742,14 +742,25 @@ result_t Message::decodeLastData(bool leadingSeparator, const char* fieldName, return result; } bool empty = result == RESULT_EMPTY; - bool useLeadingSeparator = leadingSeparator || output->tellp() > startPos; - result = m_data->read(m_lastSlaveData, 0, useLeadingSeparator, fieldName, fieldIndex, outputFormat, -1, output); - if (result < RESULT_OK) { - return result; + bool skipSlaveData = false; + if (fieldIndex >= 0) { + fieldIndex -= m_data->getCount(pt_masterData, fieldName); + if (fieldIndex < 0) { + skipSlaveData = true; + fieldIndex = 0; + } } - if (result == RESULT_EMPTY && !empty) { - result = RESULT_OK; // OK if at least one part was non-empty - } else if (result == RESULT_EMPTY && fieldName != NULL) { + if (!skipSlaveData) { + bool useLeadingSeparator = leadingSeparator || output->tellp() > startPos; + result = m_data->read(m_lastSlaveData, 0, useLeadingSeparator, fieldName, fieldIndex, outputFormat, -1, output); + if (result < RESULT_OK) { + return result; + } + if (result == RESULT_EMPTY && !empty) { + result = RESULT_OK; // OK if at least one part was non-empty + } + } + if (result == RESULT_EMPTY && (fieldName != NULL || fieldIndex >= 0)) { return RESULT_ERR_NOTFOUND; } return result;