/** * @file Decoders.h * Provides a set of TTCN-3 recoder decoder methods * @author Yann garcia * @version 1.0 * @date 20/07/2009 */ #ifndef STF_370_Decoders #define STF_370_Decoders #include #include #include #include "Singleton.h" /*! Class Decoders * \brief This class provides a set of convesion methods. It shall be used with Singleton class. */ class Decoders : public Singleton { private: //! Singleton implementation friend class Singleton; //! Convertion map from char to int. std::map m_char2digits; //! Decoders. /*! Default ctor. */ Decoders() { m_char2digits['0'] = 0x00; m_char2digits['1'] = 0x01; m_char2digits['2'] = 0x02; m_char2digits['3'] = 0x03; m_char2digits['4'] = 0x04; m_char2digits['5'] = 0x05; m_char2digits['6'] = 0x06; m_char2digits['7'] = 0x07; m_char2digits['8'] = 0x08; m_char2digits['9'] = 0x09; m_char2digits['a'] = 0x0a; m_char2digits['b'] = 0x0b; m_char2digits['c'] = 0x0c; m_char2digits['d'] = 0x0d; m_char2digits['e'] = 0x0e; m_char2digits['f'] = 0x0f; }; public: //! DecodeByte. /*! Decode a byte, one byte without length. * @param frame: The hexadecimal string * @param [out/out] poffset: The current decoder index * @return The message type. */ unsigned char DecodeByte(std::string frame, int *poffset) { // Sanity checks. if (frame.length() < (*poffset + 2)) { return 0xff; } // Extract the length. try { return static_cast(m_char2digits[tolower(frame[(*poffset)++])] << 4 | m_char2digits[tolower(frame[(*poffset)++])]); } catch (const std::exception& e) { return 0xff; } }; //! DecodeLengthPlusString. /*! Decode a bytes sequence + , with on 2 bytes. * @param frame: The hexadecimal string * @param [out/out] poffset: The current decoder index * @param [out] pLength: The length of the decoded string. * @return The real string on success, an empty string otherwise. On error, *pLength is set to -1. */ std::string DecodeLengthPlusString(std::string frame, int *pOffset, int *pLength) { *pLength = -1; // Sanity checks. if (frame.length() < (*pOffset + 2 * sizeof(short))) { std::cerr << "DecodeLengthPlusString: bad offset value: " << *pOffset << std::endl; return std::string(""); } try { // Extract the length. int ended = *pOffset + 2 * sizeof(short); //std::clog << "DecodeLengthPlusString: ended: " << ended << std::endl; *pLength = 0; for (std::string::const_iterator it = frame.begin() + *pOffset; it != frame.begin() + ended; ++it) { if ((*it == '0') && (*(it + 1) == '0')) { it += 1; } else { *pLength <<= 8; *pLength |= static_cast(m_char2digits[tolower(*it++)] << 4 | m_char2digits[tolower(*it)]); } *pOffset += 2; } //std::cout << "DecodeLengthPlusString: length value:" << *pLength << " - " << *pOffset << std::endl; if (*pLength == 0) { std::cerr << "DecodeLengthPlusString: length is null" << std::endl; return std::string(""); } std::ostringstream hexStream; //hexStream << std:setw(2); ended = *pOffset + 2 * *pLength; for (std::string::const_iterator it = frame.begin() + *pOffset; it != frame.begin() + ended; ++it) { hexStream << static_cast(m_char2digits[tolower(*it++)] << 4 | m_char2digits[tolower(*it)]); *pOffset += 2; } return hexStream.str(); } catch (const std::exception& e) { *pLength = -1; return std::string(""); } }; //! DecodeUInt16. /*! Decode a bytes sequence on 2 bytes. * @param frame: The hexadecimal string * @param [out/out] pOffset: The current decoder index * @return The number of parameters value on success, -1 otherwise. */ int DecodeUInt16(std::string frame, int *pOffset) { // Sanity checks. if (frame.length() < (*pOffset + 2 * sizeof(short))) { std::cerr << "DecodeUInt16: bad offset value: " << *pOffset << std::endl; return -1; } try { // Extract the length. int ended = *pOffset + 2 * sizeof(short); //std::clog << "DecodeUInt16: ended: " << ended << std::endl; int conv = 0; for (std::string::const_iterator it = frame.begin() + *pOffset; it != frame.begin() + ended; ++it) { if ((*it == '0') && (*(it + 1) == '0')) { it += 1; } else { conv <<= 8; conv |= static_cast(m_char2digits[tolower(*it++)] << 4 | m_char2digits[tolower(*it)]); } *pOffset += 2; } return conv; } catch (const std::exception& e) { return -1; } }; //! DecodeParamsNum. /*! Decode a bytes sequence on 2 bytes. * @param frame: The hexadecimal string * @param [out/out] pOffset: The current decoder index * @return The number of parameters value on success, -1 otherwise. */ int DecodeParamsNum(std::string frame, int *pOffset) { return DecodeUInt16(frame, pOffset); }; //! DecodeInteger. /*! Decode a bytes sequence on 8 bytes. * @param frame: The hexadecimal string * @param [out/out] pOffset: The current decoder index * @return The integer value on success, -1 otherwise. */ int DecodeInteger(std::string frame, int *pOffset) { // Sanity checks. if (frame.length() < (*pOffset + 2 * sizeof(long long))) { return -1; } // Extract the length. try { int ended = *pOffset + 2 * sizeof(long long); int conv = 0; for (std::string::const_iterator it = frame.begin() + *pOffset; it != frame.begin() + ended; ++it) { conv <<= 8; conv |= static_cast(m_char2digits[tolower(*it++)] << 4 | m_char2digits[tolower(*it)]); *pOffset += 2; } return conv; } catch (const std::exception& e) { return -1; } }; //! DecodeUInt32. /*! Decode a bytes sequence on 4 bytes. * @param frame: The hexadecimal string * @param [out/out] pOffset: The current decoder index * @return The integer value on success, -1 otherwise. */ int DecodeUInt32(std::string frame, int *pOffset) { // Sanity checks. if (frame.length() < (*pOffset + 2 * sizeof(int))) { return -1; } // Extract the length. try { int ended = *pOffset + 2 * sizeof(int); int conv = 0; for (std::string::const_iterator it = frame.begin() + *pOffset; it != frame.begin() + ended; ++it) { conv <<= 8; conv |= static_cast(m_char2digits[tolower(*it++)] << 4 | m_char2digits[tolower(*it)]); *pOffset += 2; } return conv; } catch (const std::exception& e) { return -1; } }; //! DecodeEnumerated. /*! Decode a bytes sequence + . * @param frame: The hexadecimal string * @param [out/out] pOffset: The current decoder index * @return The byte value on success, 0xff otherwise. */ unsigned char DecodeEnumerated(std::string frame, int *pOffset) { // Sanity checks. if (frame.length() < (*pOffset + 2)) { return 0xff; } // Extract the length. try { return static_cast(m_char2digits[tolower(frame[(*pOffset)++])] << 4 | m_char2digits[tolower(frame[(*pOffset)++])]); } catch (const std::exception& e) { return 0xff; } }; }; #endif // STF_370_Decoders