1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2010-2014 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #ifndef LICQ_BUFFER_H
21 #define LICQ_BUFFER_H
22 
23 #include "logging/log.h"
24 #include "macro.h"
25 
26 #include <string>
27 
28 
29 namespace Licq
30 {
31 
32 class Buffer
33 {
34 public:
35   Buffer();
36   Buffer(unsigned long _nSize);
37   Buffer(const Buffer&);
38   virtual ~Buffer();
39 
40   virtual Buffer& operator=(const Buffer&);
41   Buffer& operator+=(const Buffer&);
42   friend Buffer operator+(const Buffer&, const Buffer&);
43 
44   /// Add an unsigned 32 bit little endian integer from the buffer
45   void packUInt32LE(uint32_t data);
46 
47   /// Add an unsigned 32 bit big endian integer from the buffer
48   void packUInt32BE(uint32_t data);
49 
50   /// Add an unsigned 16 bit little endian integer from the buffer
51   void packUInt16LE(uint16_t data);
52 
53   /// Add an unsigned 16 bit big endian integer from the buffer
54   void packUInt16BE(uint16_t data);
55 
56   /// Add an unsigned 8 bit integer from the buffer
57   void packUInt8(uint8_t data);
58 
59   /// Add an signed 8 bit integer from the buffer
60   void packInt8(int8_t data);
61 
62   /// Add binary data
63   void packRaw(const void* data, size_t length);
packRaw(const std::string & data)64   void packRaw(const std::string& data) { packRaw(data.c_str(), data.size()); }
65 
66   /// Add a null terminated string preceded by a 16bit little endian length
67   void packShortNullStringLE(const std::string& data);
68 
69   /// Add a string preceded by a 16bit big endian length
70   void packString16BE(const char* data, size_t length);
packString16BE(const std::string & data)71   void packString16BE(const std::string& data)
72   { packString16BE(data.c_str(), data.size()); }
73 
74   /// Add a string preceded by a 32bit little endian length
75   void packString32LE(const char* data, size_t length);
packString32LE(const std::string & data)76   void packString32LE(const std::string& data)
77   { packString32LE(data.c_str(), data.size()); }
78 
79   void Pack(Buffer*);
80 
81   void Copy(Buffer*);
82 
83   // Deprecated add functions
PackUnsignedLong(unsigned long data)84   void PackUnsignedLong(unsigned long data) { packUInt32LE(data); }
PackUnsignedLongBE(unsigned long data)85   void PackUnsignedLongBE(unsigned long data) { packUInt32BE(data); }
PackUnsignedShort(unsigned short data)86   void PackUnsignedShort(unsigned short data) { packUInt16LE(data); }
PackUnsignedShortBE(unsigned short data)87   void PackUnsignedShortBE(unsigned short data) { packUInt16BE(data); }
PackChar(char data)88   void PackChar(char data) { packInt8(data); }
Pack(const char * data,int size)89   void Pack(const char* data, int size) { packRaw(data, size); }
Pack(const uint8_t * data,int size)90   void Pack(const uint8_t* data, int size) { packRaw(data, size); }
pack(const std::string & data)91   void pack(const std::string& data) { packRaw(data); }
PackString(const char * data)92   void PackString(const char *data) { packShortNullStringLE(data); }
packString(const std::string & data)93   void packString(const std::string& data) { packShortNullStringLE(data); }
94 
95    /**
96     * Log the packet with the given message.
97     */
98   void log(Log::Level level, const char* format, ...) const LICQ_FORMAT(3, 4);
99 
100   virtual void Clear();
101    void Reset();
102    bool Empty() const;
103    bool Full() const;
End()104    bool End()  { return ( getDataPosRead() >= (getDataStart() + getDataSize()) ); }
105    void Create(unsigned long _nDataSize = 0);
106 
107   Buffer& operator>>(char &in);
108   Buffer& operator>>(unsigned char &in);
109   Buffer& operator>>(unsigned short &in);
110   Buffer& operator>>(unsigned long &in);
111 
112   /**
113    * Get several bytes from the buffer
114    *
115    * @param size Number of bytes to read
116    * @return A string containing the requested bytes
117    */
118   std::string unpackRawString(size_t size);
119 
120   /**
121    * Get a string from the buffer
122    * Length of string is a 8 bit byte at beginning of data
123    *
124    * @return String read
125    */
126   std::string unpackByteString();
127 
128   /**
129    * Get a string from the buffer
130    * Length of string is a 16 bit little endian word at beginning of data
131    *
132    * @return String read
133    */
134   std::string unpackShortStringLE();
135 
136   /**
137    * Get a string from the buffer
138    * Length of string is a 16 bit big endian word at beginning of data
139    *
140    * @return String read
141    */
142   std::string unpackShortStringBE();
143 
144   /**
145    * Get a string from the buffer
146    * Length of string is a 32 bit little endian word at beginning of data
147    *
148    * @return String read
149    */
150   std::string unpackLongStringLE();
151 
152   /**
153    * Get a string from the buffer
154    * Length of string is a 32 bit big endian word at beginning of data
155    *
156    * @return String read
157    */
158   std::string unpackLongStringBE();
159 
160   /// Get an unsigned 32 bit little endian integer from the buffer
161   uint32_t unpackUInt32LE();
162 
163   /// Get an unsigned 32 bit big endian integer from the buffer
164   uint32_t unpackUInt32BE();
165 
166   /// Get an unsigned 16 bit little endian integer from the buffer
167   uint16_t unpackUInt16LE();
168 
169   /// Get an unsigned 16 bit big endian integer from the buffer
170   uint16_t unpackUInt16BE();
171 
172   /// Get an unsigned 8 bit integer from the buffer
173   uint8_t unpackUInt8();
174 
175   /// Get a signed 8 bit integer from the buffer
176   int8_t unpackInt8();
177 
178   // Deprecated integer access functions
UnpackUnsignedLongBE()179   unsigned long UnpackUnsignedLongBE() { return unpackUInt32BE(); }
UnpackUnsignedShortBE()180   unsigned short UnpackUnsignedShortBE() { return unpackUInt16BE(); }
UnpackUnsignedLong()181   unsigned long UnpackUnsignedLong() { return unpackUInt32LE(); }
UnpackUnsignedShort()182   unsigned short UnpackUnsignedShort() { return unpackUInt16LE(); }
UnpackChar()183   char UnpackChar() { return unpackInt8(); }
184 
getDataStart()185    char *getDataStart() const           { return m_pDataStart; };
getDataPosRead()186    char *getDataPosRead() const         { return m_pDataPosRead; };
getDataPosWrite()187    char *getDataPosWrite() const        { return m_pDataPosWrite; };
getDataSize()188    unsigned long getDataSize() const    { return m_pDataPosWrite - m_pDataStart; };
getDataMaxSize()189    unsigned long getDataMaxSize() const { return m_nDataSize; };
190 
191   /**
192    * Get number of available bytes left to read
193    */
remainingDataToRead()194   size_t remainingDataToRead() const
195   { return m_pDataPosWrite - m_pDataPosRead; }
196 
197   /**
198    * Get number of available bytes left to write
199    */
remainingDataToWrite()200   size_t remainingDataToWrite() const
201   { return m_pDataStart + m_nDataSize - m_pDataPosWrite; }
202 
setDataSize(unsigned long _nDataSize)203    void setDataSize(unsigned long _nDataSize)  { m_nDataSize = _nDataSize; };
setDataPosWrite(char * _pDataPosWrite)204    void setDataPosWrite(char *_pDataPosWrite)  { m_pDataPosWrite = _pDataPosWrite; };
setDataPosRead(char * _pDataPosRead)205    void setDataPosRead(char *_pDataPosRead)  { m_pDataPosRead = _pDataPosRead; };
incDataPosWrite(unsigned long c)206    void incDataPosWrite(unsigned long c)  { m_pDataPosWrite += c; };
incDataPosRead(unsigned long c)207    void incDataPosRead(unsigned long c)  { m_pDataPosRead += c; };
208 
209 protected:
210 
211    char *m_pDataStart,
212         *m_pDataPosWrite,
213         *m_pDataPosRead;
214    unsigned long m_nDataSize;
215 };
216 
217 Buffer operator+(const Buffer& b0, const Buffer& b1);
218 
219 } // namespace Licq
220 
221 #endif
222