1 /////////////////////////////////////////
2 //
3 //   OpenLieroX
4 //
5 //   Auxiliary Software class library
6 //
7 //   based on the work of JasonB
8 //   enhanced by Dark Charlie and Albert Zeyer
9 //
10 //   code under LGPL
11 //
12 /////////////////////////////////////////
13 
14 
15 // Byte stream class
16 // Created 13/10/01
17 // Jason Boettcher
18 
19 
20 #ifndef __CBYTESTREAM_H__
21 #define __CBYTESTREAM_H__
22 
23 #include <SDL.h> // for SInt16
24 #include <string>
25 #include <set>
26 #include "types.h"
27 #include "Networking.h"
28 #include "SmartPointer.h"
29 
30 struct ScriptVar_t;
31 struct Logger;
32 struct PrintOutFct;
33 
34 class CBytestream {
35 public:
CBytestream()36 	CBytestream() : pos(0), bitPos(0), Data("") {}
CBytestream(const std::string & rawData)37 	CBytestream(const std::string& rawData) : pos(0), bitPos(0), Data(rawData) {}
38 
CBytestream(const CBytestream & bs)39 	CBytestream(const CBytestream& bs) {
40 		operator=(bs);
41 	}
42 
43 	CBytestream& operator=(const CBytestream& bs) {
44 		pos = bs.pos;
45 		Data = bs.Data;
46 		bitPos = bs.bitPos;
47 		return *this;
48 	}
49 
50 private:
51 	// Attributes
52 	size_t pos;
53 	size_t bitPos;
54 	std::string Data;
55 
56 public:
57 	// Methods
58 
59 	// Debug
60 	void		Test();
61 
62 
63 	// Generic data
ResetBitPos()64 	void		ResetBitPos()		{ bitPos = 0; }
ResetPosToBegin()65 	void		ResetPosToBegin()	{ pos = 0; bitPos = 0; }
GetLength()66 	size_t		GetLength()	const 	{ return Data.size(); }
GetPos()67 	size_t		GetPos() const 		{ return pos; }
GetRestLen()68 	size_t		GetRestLen() const 	{ return isPosAtEnd() ? 0 : (Data.size() - pos); }
isPosAtEnd()69 	bool		isPosAtEnd() const { return GetPos() >= GetLength(); }
revertByte()70 	void		revertByte()		{ assert(pos > 0); pos--; }
flushOld()71 	void		flushOld()			{ Data.erase(0, pos); pos = 0; }
getRawData(size_t start,size_t end)72 	std::string	getRawData(size_t start, size_t end) { assert(start <= end); return Data.substr(start, end - start + 1); }
73 
74 	void		Clear();
75 	void		Append(CBytestream *bs);
76 
77 	// Note: marks positions are relative to start; start=0 means from the very beginning of the stream (not from pos)
78     void        Dump(const PrintOutFct& printer, const std::set<size_t>& marks = std::set<size_t>(), size_t start = 0, size_t count = (size_t)-1);
79 	void		Dump();
80 
81 	// Writes
82 	bool		writeByte(uchar byte);
83 	bool		writeBool(bool value);
84 	bool		writeInt(int value, uchar numbytes);
85 	bool		writeInt16(Sint16 value);
86 	bool		writeUInt64(Uint64 value);
87 	bool		writeFloat(float value);
88 	bool		writeString(const std::string& value);
89 	bool		write2Int12(short x, short y);
90 	bool		write2Int4(short x, short y);
91 	bool		writeBit(bool bit);
92 	bool		writeData(const std::string& value);	// Do not append '\0' at the end, writes just the raw data
93 	bool		writeVar(const ScriptVar_t& var);
94 
95 	// Reads
96 	uchar		readByte();
97 	bool		readBool();
98 	int			readInt(uchar numbytes); // readInt(2) will return 0:65535 range, not -32768:32767, so save it into Sint16
99 	Sint16		readInt16();
100 	Uint64		readUInt64();
101 	float		readFloat();
102 	std::string readString();
103 	std::string readString(size_t maxlen);
104 	void		read2Int12(short& x, short& y);
105 	void		read2Int4(short& x, short& y);
106 	bool		readBit();
107 	std::string	readData( size_t size = (size_t)(-1) );
108 	bool		readVar(ScriptVar_t& var);
109 
110 	// Peeks
111 	uchar		peekByte() const;
112 	std::string	peekData(size_t len) const;
113 
114 	// Skips
115 	// Folowing functions return true if we're at the end of stream after the skip
116 	bool		Skip(size_t num);
SkipInt()117 	bool SkipInt()		{ return Skip(4); }
SkipFloat()118 	bool SkipFloat()		{ return Skip(4); }
SkipShort()119 	bool SkipShort()		{ return Skip(2); }
120 	bool		SkipString();
SkipAll()121 	void		SkipAll()		{ pos = Data.size(); }
SkipRestBits()122 	bool	SkipRestBits() { if(isPosAtEnd()) return true; ResetBitPos(); pos++; return isPosAtEnd(); }
123 
124 	// Networking stuff
125 	bool	Send(NetworkSocket* sock);
126 	size_t	Read(NetworkSocket* sock);
Send(const SmartPointer<NetworkSocket> & sock)127 	bool Send(const SmartPointer<NetworkSocket>& sock) { return Send(sock.get()); }
Read(const SmartPointer<NetworkSocket> & sock)128 	size_t Read(const SmartPointer<NetworkSocket>& sock) { return Read(sock.get()); }
129 };
130 
131 // Inline class to operate with bits for dirt updates, hopefully optimized by compiler
132 // No bound-checking is made, be sure your data is large enough
133 class CBytestreamBitIterator
134 {
135 	char * data;
136 	size_t pos;
137 	Uint8 bitMask;
138 
139 	public:
140 
CBytestreamBitIterator(char * Data)141 	CBytestreamBitIterator(char * Data): data(Data)
142 	{
143 		resetPos();
144 	}
145 
getPos()146 	size_t getPos() const
147 	{
148 		return pos;
149 	}
resetPos()150 	void resetPos()
151 	{
152 		pos = 0;
153 		bitMask = 1;
154 	}
155 
156 	CBytestreamBitIterator& operator ++()
157 	{
158 		if( bitMask >= 128 )
159 		{
160 			bitMask = 1;
161 			pos ++;
162 		}
163 		else
164 			bitMask *= 2;
165 		return *this;
166 	}
167 
getBit()168 	bool getBit() const
169 	{
170 		return ( data[pos] & bitMask ) != 0;
171 	}
setBit()172 	void setBit()
173 	{
174 		data[pos] |= bitMask;
175 	}
clearBit()176 	void clearBit()
177 	{
178 		data[pos] &= ~ bitMask;
179 	}
xorBit()180 	void xorBit()
181 	{
182 		data[pos] ^= bitMask;
183 	}
184 
185 	// Slower functions
readBit()186 	bool readBit()
187 	{
188 		bool ret = getBit();
189 		++(*this);
190 		return ret;
191 	}
writeBit(bool bit)192 	void writeBit( bool bit )
193 	{
194 		if( bit )
195 			setBit();
196 		else
197 			clearBit();
198 		++(*this);
199 	}
200 
getSizeInBytes(size_t bits)201 	static size_t getSizeInBytes( size_t bits )
202 	{
203 		size_t bytes = bits / 8;
204 		if( bits % 8 )
205 			bytes++;
206 		return bytes;
207 	}
208 };
209 
210 
211 template< bool (*fct1) (CBytestream*), bool (*fct2) (CBytestream*) >
SkipMult(CBytestream * bs)212 bool SkipMult(CBytestream* bs) { return (*fct1)(bs) && (*fct2)(bs); }
213 
214 template< size_t NUM >
Skip(CBytestream * bs)215 bool Skip(CBytestream* bs) { return bs->Skip(NUM); }
216 
SkipString(CBytestream * bs)217 inline bool SkipString(CBytestream* bs) { return bs->SkipString(); }
218 
219 #endif  //  __CBITSTREAM_H__
220