1 /*=============================================================================
2 Blobby Volley 2
3 Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de)
4 Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de)
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 =============================================================================*/
20 
21 #include "GenericIO.h"
22 
23 #include <cstring>
24 #include <ostream>
25 
26 #include <boost/make_shared.hpp>
27 
28 #include "raknet/BitStream.h"
29 #include "raknet/NetworkTypes.h"
30 
31 #include "FileWrite.h"
32 #include "FileRead.h"
33 #include "PlayerInput.h"
34 
35 // -------------------------------------------------------------------------------------------------
36 //							File Output Class
37 // -------------------------------------------------------------------------------------------------
38 
39 class FileOut : public GenericOut
40 {
41 	public:
FileOut(boost::shared_ptr<FileWrite> file)42 		FileOut(boost::shared_ptr<FileWrite> file) : mFile(file)
43 		{
44 
45 		}
46 
47 	private:
byte(const unsigned char & data)48 		virtual void byte(const unsigned char& data)
49 		{
50 			mFile->writeByte(data);
51 		}
52 
boolean(const bool & data)53 		virtual void boolean(const bool& data)
54 		{
55 			mFile->writeByte(data);
56 		}
57 
uint32(const unsigned int & data)58 		virtual void uint32(const unsigned int& data)
59 		{
60 			mFile->writeUInt32(data);
61 		}
62 
number(const float & data)63 		virtual void number(const float& data)
64 		{
65 			mFile->writeFloat(data);
66 		}
67 
string(const std::string & string)68 		virtual void string(const std::string& string)
69 		{
70 			uint32(string.size());
71 			mFile->write(string.data(), string.size());
72 		}
73 
74 
tell() const75 		virtual unsigned int tell() const
76 		{
77 			return mFile->tell();
78 		}
79 
seek(unsigned int pos) const80 		virtual void seek(unsigned int pos) const
81 		{
82 			mFile->seek(pos);
83 		}
84 
array(const char * data,unsigned int length)85 		virtual void array(const char* data, unsigned int length)
86 		{
87 			mFile->write(data, length);
88 		}
89 
90 		boost::shared_ptr<FileWrite> mFile;
91 };
92 
93 // -------------------------------------------------------------------------------------------------
94 //							File Input Class
95 // -------------------------------------------------------------------------------------------------
96 
97 class FileIn : public GenericIn
98 {
99 	public:
FileIn(boost::shared_ptr<FileRead> file)100 		FileIn(boost::shared_ptr<FileRead> file) : mFile(file)
101 		{
102 
103 		}
104 
105 	private:
byte(unsigned char & data)106 		virtual void byte(unsigned char& data)
107 		{
108 			data = mFile->readByte();
109 		}
110 
boolean(bool & data)111 		virtual void boolean(bool& data)
112 		{
113 			data = mFile->readByte();
114 		}
115 
uint32(unsigned int & data)116 		virtual void uint32(unsigned int& data)
117 		{
118 			data = mFile->readUInt32();
119 		}
120 
number(float & data)121 		virtual void number(float& data)
122 		{
123 			data = mFile->readFloat();
124 		}
125 
string(std::string & string)126 		virtual void string(std::string& string)
127 		{
128 			/// \todo this might be bad performance wise
129 			unsigned int ts;
130 			uint32(ts);
131 
132 			string.resize(ts);
133 			for(unsigned int i = 0; i < ts; ++i)
134 			{
135 				unsigned char nc;
136 				byte(nc);
137 				string[i] = nc;
138 			}
139 		}
140 
141 
tell() const142 		virtual unsigned int tell() const
143 		{
144 			return mFile->tell();
145 		}
146 
seek(unsigned int pos) const147 		virtual void seek(unsigned int pos) const
148 		{
149 			mFile->seek(pos);
150 		}
151 
array(char * data,unsigned int length)152 		virtual void array(char* data, unsigned int length)
153 		{
154 			mFile->readRawBytes(data, length);
155 		}
156 
157 		boost::shared_ptr<FileRead> mFile;
158 };
159 
160 
161 // -------------------------------------------------------------------------------------------------
162 //							Bitstream Output Class
163 // -------------------------------------------------------------------------------------------------
164 
165 class NetworkOut : public GenericOut
166 {
167 	public:
NetworkOut(RakNet::BitStream * stream)168 		NetworkOut(RakNet::BitStream* stream) : mStream(stream)
169 		{
170 
171 		}
172 
173 	private:
byte(const unsigned char & data)174 		virtual void byte(const unsigned char& data)
175 		{
176 			mStream->Write(data);
177 		}
178 
boolean(const bool & data)179 		virtual void boolean(const bool& data)
180 		{
181 			mStream->Write(data);
182 		}
183 
uint32(const unsigned int & data)184 		virtual void uint32(const unsigned int& data)
185 		{
186 			mStream->Write(data);
187 		}
188 
number(const float & data)189 		virtual void number(const float& data)
190 		{
191 			mStream->Write(data);
192 		}
193 
string(const std::string & string)194 		virtual void string(const std::string& string)
195 		{
196 			uint32(string.size());
197 			mStream->Write(string.c_str(), string.size());
198 		}
199 
200 
tell() const201 		virtual unsigned int tell() const
202 		{
203 			return mStream->GetNumberOfBitsUsed();
204 		}
205 
seek(unsigned int pos) const206 		virtual void seek(unsigned int pos) const
207 		{
208 			mStream->SetWriteOffset(pos);
209 		}
210 
array(const char * data,unsigned int length)211 		virtual void array(const char* data, unsigned int length)
212 		{
213 			mStream->Write(data, length);
214 		}
215 
216 		RakNet::BitStream* mStream;
217 };
218 
219 // -------------------------------------------------------------------------------------------------
220 //							Bistream Input Class
221 // -------------------------------------------------------------------------------------------------
222 
223 class NetworkIn : public GenericIn
224 {
225 	public:
NetworkIn(RakNet::BitStream * stream)226 		NetworkIn(RakNet::BitStream* stream) : mStream(stream)
227 		{
228 
229 		}
230 
231 	private:
byte(unsigned char & data)232 		virtual void byte(unsigned char& data)
233 		{
234 			mStream->Read(data);
235 		}
236 
boolean(bool & data)237 		virtual void boolean(bool& data)
238 		{
239 			mStream->Read(data);
240 		}
241 
uint32(unsigned int & data)242 		virtual void uint32( unsigned int& data)
243 		{
244 			mStream->Read(data);
245 		}
246 
number(float & data)247 		virtual void number( float& data)
248 		{
249 			mStream->Read(data);
250 		}
251 
string(std::string & string)252 		virtual void string( std::string& string)
253 		{
254 			/// \todo this might be bad performance wise
255 			unsigned int ts;
256 			uint32(ts);
257 
258 			string.resize(ts);
259 			for(unsigned int i = 0; i < ts; ++i)
260 			{
261 				unsigned char nc;
262 				byte(nc);
263 				string[i] = nc;
264 			}
265 		}
266 
267 
tell() const268 		virtual unsigned int tell() const
269 		{
270 			return mStream->GetReadOffset();
271 		}
272 
seek(unsigned int pos) const273 		virtual void seek(unsigned int pos) const
274 		{
275 			mStream->ResetReadPointer();
276 			mStream->IgnoreBits(pos);
277 		}
278 
array(char * data,unsigned int length)279 		virtual void array( char* data, unsigned int length)
280 		{
281 			mStream->Read(data, length);
282 		}
283 
284 		RakNet::BitStream* mStream;
285 };
286 
287 // -------------------------------------------------------------------------------------------------
288 //							File Output Class
289 // -------------------------------------------------------------------------------------------------
290 
291 class StreamOut : public GenericOut
292 {
293 	public:
StreamOut(std::ostream & stream)294 		StreamOut(std::ostream& stream) : mStream(stream)
295 		{
296 
297 		}
298 
299 	private:
byte(const unsigned char & data)300 		virtual void byte(const unsigned char& data)
301 		{
302 			mStream << data << "\n";
303 		}
304 
boolean(const bool & data)305 		virtual void boolean(const bool& data)
306 		{
307 			mStream << data << "\n";
308 		}
309 
uint32(const unsigned int & data)310 		virtual void uint32(const unsigned int& data)
311 		{
312 			mStream << data << "\n";
313 		}
314 
number(const float & data)315 		virtual void number(const float& data)
316 		{
317 			mStream << data << "\n";
318 		}
319 
string(const std::string & string)320 		virtual void string(const std::string& string)
321 		{
322 			mStream << string << "\n";
323 		}
324 
325 		/// currently not supported by StreamOut
tell() const326 		virtual unsigned int tell() const
327 		{
328 			return -1;
329 		}
330 
seek(unsigned int pos) const331 		virtual void seek(unsigned int pos) const
332 		{
333 		}
334 
array(const char * data,unsigned int length)335 		virtual void array(const char* data, unsigned int length)
336 		{
337 			std::string stringed(data, length);
338 			mStream << stringed << "\n";
339 		}
340 
341 		std::ostream& mStream;
342 };
343 
344 
345 
346 // -------------------------------------------------------------------------------------------------
347 //							Factory Functions
348 // -------------------------------------------------------------------------------------------------
349 
createGenericWriter(boost::shared_ptr<FileWrite> file)350 boost::shared_ptr< GenericOut > createGenericWriter(boost::shared_ptr<FileWrite> file)
351 {
352 	return boost::make_shared< FileOut > (file);
353 }
354 
createGenericWriter(RakNet::BitStream * stream)355 boost::shared_ptr< GenericOut > createGenericWriter(RakNet::BitStream* stream)
356 {
357 	return boost::make_shared< NetworkOut > (stream);
358 }
359 
createGenericWriter(std::ostream & stream)360 boost::shared_ptr< GenericOut > createGenericWriter(std::ostream& stream)
361 {
362 	return boost::shared_ptr< StreamOut > ( new StreamOut(stream) );
363 }
364 
createGenericReader(boost::shared_ptr<FileRead> file)365 boost::shared_ptr< GenericIn > createGenericReader(boost::shared_ptr<FileRead> file)
366 {
367 	return boost::make_shared< FileIn > (file);
368 }
369 
createGenericReader(RakNet::BitStream * stream)370 boost::shared_ptr< GenericIn > createGenericReader(RakNet::BitStream* stream)
371 {
372 	return boost::make_shared< NetworkIn > (stream);
373 }
374 
375 // -------------------------------------------------------------------------------------------------
376 //			Default generic implementations
377 // -------------------------------------------------------------------------------------------------
378 
379 /*	Several instantiations of serializer functions are made so these can be used without
380 	further user actions. These are the instantiations for the standard types
381 		* unsigned char
382 		* bool
383 		* unsigned int
384 		* float
385 		* string
386 	Furthermore, some types used in BlobbyVolley get their serialisation algorithms here
387 		* Color
388 		* PlayerInput
389 		* PlayerSide
390 */
391 
392 // these templates help to avoid boilderplate code
393 
394 #define GENERATE_STD_SERIALIZER_OUT(type)		\
395 	template<>									\
396 	void predifined_serializer<type>::serialize(GenericOut& io, const type& value)
397 
398 #define GENERATE_STD_SERIALIZER_IN(type)		\
399 	template<>									\
400 	void predifined_serializer<type>::serialize(GenericIn& io, type& value)
401 
402 #define GENERATE_STD_SERIALIZER(type, func)		\
403 	GENERATE_STD_SERIALIZER_OUT(type) { io.func(value); };	\
404 	GENERATE_STD_SERIALIZER_IN(type) { io.func(value); };
405 
406 
407 namespace detail
408 {
409 	// std implementations
410 	GENERATE_STD_SERIALIZER(unsigned char, byte);
411 	GENERATE_STD_SERIALIZER(unsigned int, uint32);
412 	GENERATE_STD_SERIALIZER(bool, boolean);
413 	GENERATE_STD_SERIALIZER(float, number);
414 	GENERATE_STD_SERIALIZER(std::string, string);
415 
416 	// Blobby types
417 
418 
GENERATE_STD_SERIALIZER_OUT(Color)419 	GENERATE_STD_SERIALIZER_OUT(Color)
420 	{
421 		io.uint32(value.toInt());
422 	}
423 
GENERATE_STD_SERIALIZER_IN(Color)424 	GENERATE_STD_SERIALIZER_IN(Color)
425 	{
426 		unsigned int target;
427 		io.uint32(target);
428 		value = Color(target);
429 	}
430 
GENERATE_STD_SERIALIZER_OUT(PlayerInput)431 	GENERATE_STD_SERIALIZER_OUT(PlayerInput)
432 	{
433 		io.uint32(value.getAll());
434 	}
435 
GENERATE_STD_SERIALIZER_IN(PlayerInput)436 	GENERATE_STD_SERIALIZER_IN(PlayerInput)
437 	{
438 		unsigned int target;
439 		io.uint32(target);
440 		value.setAll(target);
441 	}
442 
GENERATE_STD_SERIALIZER_OUT(PlayerSide)443 	GENERATE_STD_SERIALIZER_OUT(PlayerSide)
444 	{
445 		io.uint32(value);
446 	}
447 
GENERATE_STD_SERIALIZER_IN(PlayerSide)448 	GENERATE_STD_SERIALIZER_IN(PlayerSide)
449 	{
450 		unsigned int target;
451 		io.uint32(target);
452 		value = (PlayerSide)target;
453 	}
454 
GENERATE_STD_SERIALIZER_OUT(PlayerID)455 	GENERATE_STD_SERIALIZER_OUT(PlayerID)
456 	{
457 		io.uint32(value.binaryAddress);
458 		io.uint32(value.port);
459 	}
460 
GENERATE_STD_SERIALIZER_IN(PlayerID)461 	GENERATE_STD_SERIALIZER_IN(PlayerID)
462 	{
463 		io.uint32(value.binaryAddress);
464 		unsigned int port;
465 		io.uint32(port);
466 		value.port = port;
467 	}
468 
469 }
470 
471 
472