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