From e3856c3148759b596b9fbff011c6b5007595e611 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 11 Oct 2015 22:35:45 +0200 Subject: [PATCH] added support for conditions based on raw value of numeric fields, adjust error position cout in case of duplicate, added ostream arg to printErrorPos, added separate RESULT_ERR_DUPLICATE_NAME --- src/lib/ebus/data.cpp | 113 +++++++++++++++++++++++++++++++++++++++--- src/lib/ebus/data.h | 73 +++++++++++++++++++++++---- 2 files changed, 167 insertions(+), 19 deletions(-) diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index cafe2d26..9cd78234 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -135,19 +135,19 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV return (int)ret; } -void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result) +void printErrorPos(ostream& out, vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result) { if (pos > begin) pos--; - cout << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast(lineNo) << " field " << static_cast(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl; - cout << "Erroneous item is here:" << endl; + out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast(lineNo) << " field " << static_cast(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl; + out << "Erroneous item is here:" << endl; bool first = true; int cnt = 0; while (begin != end) { if (first) first = false; else { - cout << FIELD_SEPARATOR; + out << FIELD_SEPARATOR; if (begin <= pos) { cnt++; } @@ -158,10 +158,10 @@ void printErrorPos(vector::iterator begin, const vector::iterato cnt++; string item = *begin++; - cout << TEXT_SEPARATOR << item << TEXT_SEPARATOR; + out << TEXT_SEPARATOR << item << TEXT_SEPARATOR; } - cout << endl; - cout << setw(cnt) << " " << setw(0) << "^" << endl; + out << endl; + out << setw(cnt) << " " << setw(0) << "^" << endl; } @@ -435,6 +435,35 @@ void SingleDataField::dump(ostream& output) dumpString(output, m_dataType.name); } + +result_t SingleDataField::read(const PartType partType, + SymbolString& data, unsigned char offset, + unsigned int& output, const char* fieldName, signed char fieldIndex) +{ + if (partType != m_partType) + return RESULT_EMPTY; + + switch (m_partType) + { + case pt_masterData: + offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN + break; + case pt_slaveData: + offset++; // skip NN + break; + default: + return RESULT_ERR_INVALID_PART; + } + if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { + if (offset + m_length > data.size()) { + return RESULT_ERR_INVALID_POS; + } + return RESULT_EMPTY; + } + + return readRawValue(data, offset, output); +} + result_t SingleDataField::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, OutputFormat outputFormat, @@ -539,6 +568,11 @@ result_t StringDataField::derive(string name, string comment, return RESULT_OK; } +bool StringDataField::hasField(const char* fieldName, bool numeric) +{ + return !numeric && fieldName==m_name; +} + void StringDataField::dump(ostream& output) { SingleDataField::dump(output); @@ -549,6 +583,11 @@ void StringDataField::dump(ostream& output) dumpString(output, m_comment); } +result_t StringDataField::readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value) +{ + return RESULT_EMPTY; +} + result_t StringDataField::readSymbols(SymbolString& input, const unsigned char baseOffset, ostringstream& output, OutputFormat outputFormat) { @@ -799,6 +838,11 @@ bool NumericDataField::hasFullByteOffset(bool after) || (after && m_bitOffset + (m_bitCount % 8) >= 8); } +bool NumericDataField::hasField(const char* fieldName, bool numeric) +{ + return numeric && fieldName==m_name; +} + void NumericDataField::dump(ostream& output) { SingleDataField::dump(output); @@ -1275,6 +1319,16 @@ result_t DataFieldSet::derive(string name, string comment, return RESULT_OK; } +bool DataFieldSet::hasField(const char* fieldName, bool numeric) +{ + for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { + SingleDataField* field = *it; + if (field->hasField(fieldName, numeric)==0) + return true; + } + return false; +} + void DataFieldSet::dump(ostream& output) { bool first = true; @@ -1287,6 +1341,46 @@ void DataFieldSet::dump(ostream& output) } } +result_t DataFieldSet::read(const PartType partType, + SymbolString& data, unsigned char offset, + unsigned int& output, const char* fieldName, signed char fieldIndex) +{ + bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; + for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { + SingleDataField* field = *it; + if (partType != pt_any && field->getPartType() != partType) + continue; + + if (!previousFullByteOffset && !field->hasFullByteOffset(false)) + offset--; + + result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex); + + if (result < RESULT_OK) + return result; + + offset = (unsigned char)(offset + field->getLength(partType)); + previousFullByteOffset = field->hasFullByteOffset(true); + if (result != RESULT_EMPTY) { + found = true; + } + if (findFieldIndex && fieldName == field->getName()) { + if (fieldIndex == 0) { + if (!found) + return RESULT_ERR_NOTFOUND; + break; + } + fieldIndex--; + } + } + + if (!found) { + return RESULT_EMPTY; + } + + return RESULT_OK; +} + result_t DataFieldSet::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, OutputFormat outputFormat, @@ -1390,7 +1484,7 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace) map::iterator it = m_fieldsByName.find(name); if (it != m_fieldsByName.end()) { if (!replace) - return RESULT_ERR_DUPLICATE; // duplicate key + return RESULT_ERR_DUPLICATE_NAME; // duplicate key delete it->second; it->second = field; @@ -1405,6 +1499,7 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace) result_t DataFieldTemplates::addFromFile(vector::iterator& begin, const vector::iterator end, void* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) { + vector::iterator restart = begin; DataField* field = NULL; string name; if (begin != end) { @@ -1419,6 +1514,8 @@ result_t DataFieldTemplates::addFromFile(vector::iterator& begin, const return result; result = add(field, name, true); + if (result==RESULT_ERR_DUPLICATE_NAME) + begin = restart+1; // mark name as invalid if (result != RESULT_OK) delete field; diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 88280e3b..6b66ac38 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -122,7 +122,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length=NULL); /** - * Print the error position of the iterator to stdout. + * Print the error position of the iterator. + * @param out the @a ostream to print to. * @param begin the iterator to the beginning of the items. * @param end the iterator to the end of the items. * @param pos the iterator with the erroneous position. @@ -130,7 +131,7 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV * @param lineNo the current line number in the file being read. * @param result the result code. */ -void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result); +void printErrorPos(ostream& out, vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result); class DataFieldTemplates; @@ -222,6 +223,31 @@ public: */ virtual void dump(ostream& output) = 0; + /** + * Return whether the field is available. + * @param fieldName the name of the field to find. + * @param numeric true for a numeric field, false for a string field. + * @return true if the field is available. + */ + virtual bool hasField(const char* fieldName, bool numeric) = 0; + + /** + * Reads the numeric value from the @a SymbolString. + * @param partType the @a PartType of the data. + * @param data the unescaped data @a SymbolString for reading binary data. + * @param offset the additional offset to add for reading binary data. + * @param output the variable in which to store the numeric value. + * @param fieldName the name of the field to read, or NULL for the first field. + * @param fieldIndex the optional index of the named field, or -1. + * @return @a RESULT_OK on success, + * or @a RESULT_EMPTY if the field was skipped (either if the partType does + * not match or ignored, or due to @a fieldName or @a fieldIndex), + * or an error code. + */ + virtual result_t read(const PartType partType, + SymbolString& data, unsigned char offset, + unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1) = 0; + /** * Reads the value from the @a SymbolString. * @param partType the @a PartType of the data. @@ -233,7 +259,7 @@ public: * @param fieldName the optional name of a field to limit the output to. * @param fieldIndex the optional index of the named field to limit the output to, or -1. * @return @a RESULT_OK on success (or if the partType does not match), - * or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a filterName), + * or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex), * or an error code. */ virtual result_t read(const PartType partType, @@ -345,6 +371,11 @@ public: // @copydoc virtual void dump(ostream& output); + // @copydoc + virtual result_t read(const PartType partType, + SymbolString& data, unsigned char offset, + unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1); + // @copydoc virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, @@ -358,6 +389,15 @@ public: protected: + /** + * Internal method for reading the numeric raw value from a @a SymbolString. + * @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 numeric raw value. + * @return @a RESULT_OK on success, or an error code. + */ + virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value) = 0; + /** * Internal method for reading the field from a @a SymbolString. * @param input the unescaped @a SymbolString to read the binary value from. @@ -427,11 +467,17 @@ public: int divisor, map values, vector& fields); + // @copydoc + virtual bool hasField(const char* fieldName, bool numeric); + // @copydoc virtual void dump(ostream& output); protected: + // @copydoc + virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value); + // @copydoc virtual result_t readSymbols(SymbolString& input, const unsigned char baseOffset, ostringstream& output, OutputFormat outputFormat); @@ -474,19 +520,16 @@ public: // @copydoc virtual bool hasFullByteOffset(bool after); + // @copydoc + virtual bool hasField(const char* fieldName, bool numeric); + // @copydoc virtual void dump(ostream& output); protected: - /** - * Internal method for reading the raw value from a @a SymbolString. - * @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. - * @return @a RESULT_OK on success, or an error code. - */ - result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value); + // @copydoc + virtual result_t readRawValue(SymbolString& input, const unsigned char offset, unsigned int& value); /** * Internal method for writing the raw value to a @a SymbolString. @@ -678,9 +721,17 @@ public: */ size_t size() const { return m_fields.size(); } + // @copydoc + virtual bool hasField(const char* fieldName, bool numeric); + // @copydoc virtual void dump(ostream& output); + // @copydoc + virtual result_t read(const PartType partType, + SymbolString& data, unsigned char offset, + unsigned int& output, const char* fieldName=NULL, signed char fieldIndex=-1); + // @copydoc virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset,