// // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2013 SuperTuxKart-Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 3 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*! \file network_string.hpp * \brief Defines functions to easily manipulate 8-bit network destinated strings. */ #ifndef NETWORK_STRING_HPP #define NETWORK_STRING_HPP #include "utils/types.hpp" #include #include #include #include typedef unsigned char uchar; /** \class NetworkString * \brief Describes a chain of 8-bit unsigned integers. * This class allows you to easily create and parse 8-bit strings. */ class NetworkString { union { float f; uint8_t i[4]; } f_as_i; // float as integer union { double d; uint8_t i[8]; } d_as_i; // double as integer public: NetworkString() { } NetworkString(const uint8_t& value) { m_string.push_back(value); } NetworkString(NetworkString const& copy) { m_string = copy.m_string; } NetworkString(const std::string & value) { m_string = std::vector(value.begin(), value.end()); } NetworkString& removeFront(int size) { m_string.erase(m_string.begin(), m_string.begin()+size); return *this; } NetworkString& remove(int pos, int size) { m_string.erase(m_string.begin()+pos, m_string.begin()+pos+size); return *this; } uint8_t operator[](const int& pos) const { return getUInt8(pos); } NetworkString& addUInt8(const uint8_t& value) { m_string.push_back(value); return *this; } inline NetworkString& ai8(const uint8_t& value) { return addUInt8(value); } NetworkString& addUInt16(const uint16_t& value) { m_string.push_back((value>>8)&0xff); m_string.push_back(value&0xff); return *this; } inline NetworkString& ai16(const uint16_t& value) { return addUInt16(value); } NetworkString& addUInt32(const uint32_t& value) { m_string.push_back((value>>24)&0xff); m_string.push_back((value>>16)&0xff); m_string.push_back((value>>8)&0xff); m_string.push_back(value&0xff); return *this; } inline NetworkString& ai32(const uint32_t& value) { return addUInt32(value); } NetworkString& addInt(const int& value) { m_string.push_back((value>>24)&0xff); m_string.push_back((value>>16)&0xff); m_string.push_back((value>>8)&0xff); m_string.push_back(value&0xff); return *this; } inline NetworkString& ai(const int& value) { return addInt(value); } NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION { assert(sizeof(float)==4); f_as_i.f = value; m_string.push_back(f_as_i.i[0]); m_string.push_back(f_as_i.i[1]); m_string.push_back(f_as_i.i[2]); m_string.push_back(f_as_i.i[3]); return *this; } inline NetworkString& af(const float& value) { return addFloat(value); } NetworkString& addDouble(const double& value) //!< BEWARE OF PRECISION { assert(sizeof(double)==8); d_as_i.d = value; m_string.push_back(d_as_i.i[0]); m_string.push_back(d_as_i.i[1]); m_string.push_back(d_as_i.i[2]); m_string.push_back(d_as_i.i[3]); m_string.push_back(d_as_i.i[4]); m_string.push_back(d_as_i.i[5]); m_string.push_back(d_as_i.i[6]); m_string.push_back(d_as_i.i[7]); return *this; } inline NetworkString& ad(const double& value) { return addDouble(value); } NetworkString& addChar(const char& value) { m_string.push_back((uint8_t)(value)); return *this; } inline NetworkString& ac(const char& value) { return addChar(value); } NetworkString& addString(const std::string& value) { for (unsigned int i = 0; i < value.size(); i++) m_string.push_back((uint8_t)(value[i])); return *this; } inline NetworkString& as(const std::string& value) { return addString(value); } NetworkString& operator+=(NetworkString const& value) { m_string.insert( m_string.end(), value.m_string.begin(), value.m_string.end() ); return *this; } const std::string std_string() const { std::string str(m_string.begin(), m_string.end()); return str; } int size() const { return m_string.size(); } uint8_t* getBytes() { return &m_string[0]; }; const uint8_t* getBytes() const { return &m_string[0]; }; template T get(int pos) const { int a = n; T result = 0; while(a--) { result <<= 8; // offset one byte result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data to result } return result; } inline int getInt(int pos = 0) const { return get(pos); } inline uint32_t getUInt(int pos = 0) const { return get(pos); } inline uint32_t getUInt32(int pos = 0) const { return get(pos); } inline uint16_t getUInt16(int pos = 0) const { return get(pos); } inline uint8_t getUInt8(int pos = 0) const { return get(pos); } inline char getChar(int pos = 0) const { return get(pos); } inline unsigned char getUChar(int pos = 0) const { return get(pos); } std::string getString(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); } inline int gi(int pos = 0) const { return get(pos); } inline uint32_t gui(int pos = 0) const { return get(pos); } inline uint32_t gui32(int pos = 0) const { return get(pos); } inline uint16_t gui16(int pos = 0) const { return get(pos); } inline uint8_t gui8(int pos = 0) const { return get(pos); } inline char gc(int pos = 0) const { return get(pos); } inline unsigned char guc(int pos = 0) const { return get(pos); } std::string gs(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); } double getDouble(int pos = 0) //!< BEWARE OF PRECISION { for (int i = 0; i < 8; i++) d_as_i.i[i] = m_string[pos+i]; return d_as_i.d; } float getFloat(int pos = 0) //!< BEWARE OF PRECISION { for (int i = 0; i < 4; i++) f_as_i.i[i] = m_string[pos+i]; return f_as_i.f; } //! Functions to get while removing template T getAndRemove(int pos) { int a = n; T result = 0; while(a--) { result <<= 8; // offset one byte result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data } remove(pos,n); return result; } inline int getAndRemoveInt(int pos = 0) { return getAndRemove(pos); } inline uint32_t getAndRemoveUInt(int pos = 0) { return getAndRemove(pos); } inline uint32_t getAndRemoveUInt32(int pos = 0) { return getAndRemove(pos); } inline uint16_t getAndRemoveUInt16(int pos = 0) { return getAndRemove(pos); } inline uint8_t getAndRemoveUInt8(int pos = 0) { return getAndRemove(pos); } inline char getAndRemoveChar(int pos = 0) { return getAndRemove(pos); } inline unsigned char getAndRemoveUChar(int pos = 0) { return getAndRemove(pos); } double getAndRemoveDouble(int pos = 0) //!< BEWARE OF PRECISION { for (int i = 0; i < 8; i++) d_as_i.i[i] = m_string[pos+i]; return d_as_i.d; remove(pos, 8); } float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION { for (int i = 0; i < 4; i++) f_as_i.i[i] = m_string[pos+i]; return f_as_i.f; remove(pos, 4); } inline NetworkString& gui8(uint8_t* dst) { *dst = getAndRemoveUInt8(0); return *this; } inline NetworkString& gui16(uint16_t* dst) { *dst = getAndRemoveUInt16(0); return *this; } inline NetworkString& gui32(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; } inline NetworkString& gui(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; } inline NetworkString& gi(int* dst) { *dst = getAndRemoveInt(0); return *this; } inline NetworkString& gc(char* dst) { *dst = getAndRemoveChar(0); return *this; } inline NetworkString& guc(uchar* dst) { *dst = getAndRemoveUChar(0); return *this; } inline NetworkString& gd(double* dst) { *dst = getAndRemoveDouble(0); return *this; } inline NetworkString& gf(float* dst) { *dst = getAndRemoveFloat(0); return *this; } protected: std::vector m_string; }; NetworkString operator+(NetworkString const& a, NetworkString const& b); #endif // NETWORK_STRING_HPP