From 7643b0593591807da6b70a27aecc8a84cc5b9b07 Mon Sep 17 00:00:00 2001 From: john30 Date: Wed, 29 Oct 2014 23:28:51 +0100 Subject: [PATCH] merge in latest libebus commit 9520d5a3283472c2a53b8396b0796723f660bed7: simplified SymbolString interface and let it handle unescaping itself --- src/libebus/result.h | 1 + src/libebus/symbol.cpp | 125 ++++++++++++++++++++++----------------- src/libebus/symbol.h | 66 ++++++++++----------- src/test/test_symbol.cpp | 16 ++--- 4 files changed, 110 insertions(+), 98 deletions(-) diff --git a/src/libebus/result.h b/src/libebus/result.h index bd0a9c13..c0f86edf 100644 --- a/src/libebus/result.h +++ b/src/libebus/result.h @@ -31,6 +31,7 @@ static const int RESULT_DATA = 2; // some data received static const int RESULT_SYN = 3; // regular SYN after message received static const int RESULT_BUS_LOCKED = 4; // bus is locked for access static const int RESULT_BUS_PRIOR_RETRY = 5; // retry to access bus +static const int RESULT_IN_ESC = 6; // start of escape sequence received static const int RESULT_ERR_SEND = -1; // send error static const int RESULT_ERR_EXTRA_DATA = -2; // received bytes > sent bytes diff --git a/src/libebus/symbol.cpp b/src/libebus/symbol.cpp index 102c4760..287020bf 100644 --- a/src/libebus/symbol.cpp +++ b/src/libebus/symbol.cpp @@ -18,6 +18,7 @@ */ #include "symbol.h" +#include "result.h" #include #include @@ -27,7 +28,7 @@ namespace libebus /** * @brief CRC8 lookup table for the polynom 0x9b = x^8 + x^7 + x^4 + x^3 + x^1 + 1. */ -static const unsigned char CRC_LOOKUP_TABLE[] +static const unsigned char CRC_LOOKUP_TABLE[] = { 0x00, 0x9b, 0xad, 0x36, 0xc1, 0x5a, 0x6c, 0xf7, 0x19, 0x82, 0xb4, 0x2f, 0xd8, 0x43, 0x75, 0xee, 0x32, 0xa9, 0x9f, 0x04, 0xf3, 0x68, 0x5e, 0xc5, 0x2b, 0xb0, 0x86, 0x1d, 0xea, 0x71, 0x47, 0xdc, @@ -49,41 +50,35 @@ static const unsigned char CRC_LOOKUP_TABLE[] SymbolString::SymbolString(const std::string str) - : m_crc(0) + : m_unescapeState(0), m_crc(0) { // parse + escape for (size_t i = 0; i+1 < str.size(); i += 2) { - unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16); - push_back_escape((unsigned char)value); + unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16); // TODO check + push_back((unsigned char)value, false, true); } // add CRC + escape - push_back_escape(m_crc, false); + push_back(m_crc, false, false); } -SymbolString::SymbolString(const std::string str, bool escaped) - : m_crc(0) +SymbolString::SymbolString(const std::string str, bool isEscaped) + : m_unescapeState(1), m_crc(0) { - bool previousEscape = false; - // parse + optionally unescape for (size_t i = 0; i+1 < str.size(); i += 2) { - unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16); - if (escaped == true) { - push_back_unescape((unsigned char)value, previousEscape, false); - } - else - m_data.push_back((unsigned char)value); + unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16); // TODO check + push_back((unsigned char)value, isEscaped, false); } } -const std::string SymbolString::getDataStr(bool unescape) +const std::string SymbolString::getDataStr(const bool unescape) { std::stringstream sstr; bool previousEscape = false; - for (size_t i = 0; i < size(); i++) { - unsigned char value = at(i); - if (unescape == true && previousEscape == true) { + for (size_t i = 0; i < m_data.size(); i++) { + unsigned char value = m_data[i]; + if (m_unescapeState == 0 && unescape == true && previousEscape == true) { if (value == 0x00) { sstr << "a9"; // ESC } @@ -95,7 +90,7 @@ const std::string SymbolString::getDataStr(bool unescape) } previousEscape = false; } - else if (unescape == true && value == ESC) { + else if (m_unescapeState == 0 && unescape == true && value == ESC) { previousEscape = true; // escape sequence not yet finished } else { @@ -107,56 +102,80 @@ const std::string SymbolString::getDataStr(bool unescape) return sstr.str(); } -void SymbolString::push_back_escape(const unsigned char value, bool updateCRC) +int SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) { - if (value == ESC) { - m_data.push_back(ESC); - m_data.push_back(0x00); - if (updateCRC) { - addCRC(ESC); - addCRC(0x00); + if (m_unescapeState == 0) { // store escaped data + if (isEscaped == false && value == ESC) { + m_data.push_back(ESC); + m_data.push_back(0x00); + if (updateCRC) { + addCRC(ESC); + addCRC(0x00); + } } - } - else if (value == SYN) { - m_data.push_back(ESC); - m_data.push_back(0x01); - if (updateCRC) { - addCRC(ESC); - addCRC(0x01); + else if (isEscaped == false && value == SYN) { + m_data.push_back(ESC); + m_data.push_back(0x01); + if (updateCRC) { + addCRC(ESC); + addCRC(0x01); + } } + else { + m_data.push_back(value); + if (updateCRC) { + addCRC(value); + } + } + return RESULT_OK; } - else { + else if (isEscaped == false) { + if (m_unescapeState != 1) + return RESULT_ERR_ESC; // invalid unescape state m_data.push_back(value); + if (updateCRC) { + if (value == ESC) { + addCRC(ESC); + addCRC(0x00); + } + else if (value == SYN) { + addCRC(ESC); + addCRC(0x01); + } + else { + addCRC(value); + } + } + return RESULT_OK; + } + else if (m_unescapeState != 1) { if (updateCRC) { addCRC(value); } - } -} - -unsigned char SymbolString::push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC) -{ - if (updateCRC) { - addCRC(value); - } - if (previousEscape == true) { if (value == 0x00) { m_data.push_back(ESC); - previousEscape = false; - return ESC; + m_unescapeState = 1; + return RESULT_OK; } if (value == 0x01) { m_data.push_back(SYN); - previousEscape = false; - return SYN; + m_unescapeState = 1; + return RESULT_OK; } - return 0; // invalid escape sequence + return RESULT_ERR_ESC; // invalid escape sequence } - if (value == ESC) { - previousEscape = true; - return 1; // escape sequence not yet finished + else if (value == ESC) { + if (updateCRC) { + addCRC(value); + } + m_unescapeState = 2; + return RESULT_IN_ESC; + } + if (updateCRC) { + addCRC(value); } m_data.push_back(value); - return value; + return RESULT_OK; } void SymbolString::addCRC(const unsigned char value) { diff --git a/src/libebus/symbol.h b/src/libebus/symbol.h index 7ed10ce4..f4199a63 100644 --- a/src/libebus/symbol.h +++ b/src/libebus/symbol.h @@ -37,71 +37,61 @@ static const unsigned char BROADCAST = 0xFE; // the broadcast destination addres /** - * @brief A string of bus symbols. + * @brief A string of escaped or unescaped bus symbols. */ class SymbolString { public: /** - * @brief Creates a new empty SymbolString. + * @brief Creates a new unescaped empty instance. + * @param escaped whether to create an escaped instance. */ - SymbolString() : m_crc(0) {} + SymbolString() : m_unescapeState(1), m_crc(0) {} /** - * @brief Creates a new escaped SymbolString from an unescaped hex string and adds the calculated CRC. + * @brief Creates a new escaped instance from an unescaped hex string and adds the calculated CRC. * @param str the unescaped hex string. */ SymbolString(const std::string str); /** - * @brief Creates a new unescaped SymbolString from a hex string. - * @param escaped whether the hex string is escaped and shall be unescaped. + * @brief Creates a new unescaped instance from a hex string. + * @param isEscaped whether the hex string is escaped and shall be unescaped. * @param str the hex string. */ - SymbolString(const std::string str, bool escaped); + SymbolString(const std::string str, const bool isEscaped); /** * @brief Returns the symbols as hex string. - * @param escaped whether to unescape the symbols. + * @param unescape whether to unescape an escaped instance. * @return the symbols as hex string. */ - const std::string getDataStr(bool unescape=false); + const std::string getDataStr(const bool unescape=true); /** - * @brief Returns the symbol at the specified index. + * @brief Returns a reference to the symbol at the specified index. * @param index the index of the symbol to return. - * @return the symbol at the specified index. - * @throw std::out_of_range if @a index is invalid. + * @return the reference to the symbol at the specified index. */ - unsigned char at(const size_t index) { return m_data.at(index); } + unsigned char& operator[](const size_t index) { if (index >= m_data.size()) m_data.resize(index+1); return m_data[index]; } /** * @brief Returns the symbol at the specified index. * @param index the index of the symbol to return. * @return the symbol at the specified index. */ - unsigned char operator[](const size_t index) { return m_data[index]; } + const unsigned char& operator[](const size_t index) const { return m_data[index]; } /** - * @brief Returns the symbol at the specified index. - * @param index the index of the symbol to return. - * @return the symbol at the specified index. + * @brief Returns whether this instance is equal to the other instance. + * @param other the other instance. + * @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols). */ - unsigned char operator[](const size_t index) const { return m_data[index]; } + bool operator==(SymbolString other) { return (m_unescapeState==0)==(m_unescapeState==0) && m_data==other.m_data; } /** - * @brief Inserts a the symbol at the specified index. - * @param index the index at which to insert the symbol. - * @param value the symbol to insert. - */ - void insert(const size_t index, const unsigned char value) { m_data.insert(m_data.begin()+index, value); } - /** - * @brief Appends a the symbol to the end of the symbol string and escapes it if necessary. + * @brief Appends a the symbol to the end of the symbol string and escapes/unescapes it if necessary. * @param value the symbol to append. + * @param isEscaped whether the symbol is escaped. * @param updateCrc whether to update the calculated CRC in @a m_crc. + * @return RESULT_OK if another symbol was appended, + * RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was received, + * RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected. */ - void push_back_escape(const unsigned char value, bool updateCRC=true); - /** - * @brief Appends a the symbol to the end of the symbol string and unescapes it. - * @param value the symbol to append. - * @param previousEscape whether the previous value was the escape symbol (set to false for the initial call). - * @param updateCrc whether to update the calculated CRC in @a m_crc. - * @return if previousEscape is false on return: the unescaped symbol. otherwise: zero if the escape sequence was invalid, one if the escape sequence is not yet finished. - */ - unsigned char push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC=true); + int push_back(const unsigned char value, const bool isEscaped, const bool updateCRC=true); /** * @brief Returns the number of symbols in this symbol string. * @return the number of available symbols. @@ -115,7 +105,7 @@ public: /** * @brief Clears the symbols. */ - void clear() { m_crc=0; m_data.clear(); } + void clear() { m_data.clear(); m_unescapeState = m_unescapeState==0 ? 0 : 1; m_crc = 0; } private: /** @@ -128,6 +118,12 @@ private: * @brief the string of bus symbols. */ std::vector m_data; + /** + * @brief 0 if the symbols in @a m_data are escaped, + * 1 if the symbols in @a m_data are unescaped and the last symbol passed to @a push_back was a normal symbol, + * 2 if the symbols in @a m_data are unescaped and the last symbol passed to @a push_back was the escape symbol. + */ + int m_unescapeState; /** * @brief the calculated CRC. */ diff --git a/src/test/test_symbol.cpp b/src/test/test_symbol.cpp index 2e495d0b..48abdb10 100644 --- a/src/test/test_symbol.cpp +++ b/src/test/test_symbol.cpp @@ -25,15 +25,9 @@ using namespace libebus; int main () { - SymbolString sstr("10feb5050427a915aa"); + SymbolString sstr = SymbolString("10feb5050427a915aa"); - std::stringstream out; - for (size_t i = 0; i(sstr[i]); - } - - std::string gotStr = out.str(), expectStr = "10feb5050427a90015a90177"; + std::string gotStr = sstr.getDataStr(false), expectStr = "10feb5050427a90015a90177"; if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0) std::cout << "ctor escaped successful." << std::endl; @@ -54,7 +48,7 @@ int main () << std::setfill('0') << static_cast(expectCrc) << std::endl; - gotStr = sstr.getDataStr(true), expectStr = "10feb5050427a915aa77"; + gotStr = sstr.getDataStr(), expectStr = "10feb5050427a915aa77"; if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0) std::cout << "unescape successful." << std::endl; @@ -63,7 +57,9 @@ int main () << ", expected " << expectStr << std::endl; sstr = SymbolString("10feb5050427a90015a90177", true); - gotStr = sstr.getDataStr(false); + + gotStr = sstr.getDataStr(); + if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0) std::cout << "ctor unescaped successful." << std::endl; else