OregonCore  revision 3611e8a-git
Your Favourite TBC server
ByteBuffer.h
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _BYTEBUFFER_H
19 #define _BYTEBUFFER_H
20 
21 #include "Common.h"
22 #include "Errors.h"
23 #include "Log.h"
25 
27 {
28  public:
29  ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size)
30  : add(_add), pos(_pos), esize(_esize), size(_size)
31  {
32  PrintPosError();
33  }
34 
35  void PrintPosError() const
36  {
37  sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: " SIZEFMTD ") value with size: " SIZEFMTD,
38  (add ? "put" : "get"), pos, size, esize);
39  }
40  private:
41  bool add;
42  size_t pos;
43  size_t esize;
44  size_t size;
45 };
46 
47 template<class T>
48 struct Unused
49 {
50  Unused() {}
51 };
52 
54 {
55  public:
56  const static size_t DEFAULT_SIZE = 0x1000;
57 
58  // constructor
59  ByteBuffer(): _rpos(0), _wpos(0)
60  {
61  _storage.reserve(DEFAULT_SIZE);
62  }
63 
64  // constructor
65  ByteBuffer(size_t res): _rpos(0), _wpos(0)
66  {
67  _storage.reserve(res);
68  }
69 
70  // copy constructor
71  ByteBuffer(const ByteBuffer& buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { }
72 
73  void clear()
74  {
75  _storage.clear();
76  _rpos = _wpos = 0;
77  }
78 
79  template <typename T> void put(size_t pos, T value)
80  {
81  EndianConvert(value);
82  put(pos, (uint8*)&value, sizeof(value));
83  }
84 
86  {
87  append<uint8>(value);
88  return *this;
89  }
90 
92  {
93  append<uint16>(value);
94  return *this;
95  }
96 
98  {
99  append<uint32>(value);
100  return *this;
101  }
102 
104  {
105  append<uint64>(value);
106  return *this;
107  }
108 
109  // signed as in 2e complement
111  {
112  append<int8>(value);
113  return *this;
114  }
115 
117  {
118  append<int16>(value);
119  return *this;
120  }
121 
123  {
124  append<int32>(value);
125  return *this;
126  }
127 
129  {
130  append<int64>(value);
131  return *this;
132  }
133 
134  // floating points
136  {
137  append<float>(value);
138  return *this;
139  }
140 
142  {
143  append<double>(value);
144  return *this;
145  }
146 
147  ByteBuffer& operator<<(const std::string& value)
148  {
149  append((uint8 const*)value.c_str(), value.length());
150  append((uint8)0);
151  return *this;
152  }
153 
154  ByteBuffer& operator<<(const char* str)
155  {
156  append((uint8 const*)str, str ? strlen(str) : 0);
157  append((uint8)0);
158  return *this;
159  }
160 
162  {
163  value = read<char>() > 0 ? true : false;
164  return *this;
165  }
166 
168  {
169  value = read<uint8>();
170  return *this;
171  }
172 
174  {
175  value = read<uint16>();
176  return *this;
177  }
178 
180  {
181  value = read<uint32>();
182  return *this;
183  }
184 
186  {
187  value = read<uint64>();
188  return *this;
189  }
190 
191  // signed as in 2e complement
193  {
194  value = read<int8>();
195  return *this;
196  }
197 
199  {
200  value = read<int16>();
201  return *this;
202  }
203 
205  {
206  value = read<int32>();
207  return *this;
208  }
209 
211  {
212  value = read<int64>();
213  return *this;
214  }
215 
217  {
218  value = read<float>();
219  return *this;
220  }
221 
223  {
224  value = read<double>();
225  return *this;
226  }
227 
228  ByteBuffer& operator>>(std::string& value)
229  {
230  value.clear();
231  while (rpos() < size()) // prevent crash at wrong string format in packet
232  {
233  char c = read<char>();
234  if (c == 0)
235  break;
236  value += c;
237  }
238  return *this;
239  }
240 
241  template<class T>
243  {
244  read_skip<T>();
245  return *this;
246  }
247 
248  uint8 operator[](size_t pos) const
249  {
250  return read<uint8>(pos);
251  }
252 
253  size_t rpos() const
254  {
255  return _rpos;
256  }
257 
258  size_t rpos(size_t rpos_)
259  {
260  _rpos = rpos_;
261  return _rpos;
262  }
263 
264  size_t wpos() const
265  {
266  return _wpos;
267  }
268 
269  size_t wpos(size_t wpos_)
270  {
271  _wpos = wpos_;
272  return _wpos;
273  }
274 
275  template<typename T>
276  void read_skip()
277  {
278  read_skip(sizeof(T));
279  }
280 
281  void read_skip(size_t skip)
282  {
283  if (_rpos + skip > size())
284  throw ByteBufferException(false, _rpos, skip, size());
285  _rpos += skip;
286  }
287 
288  template <typename T> T read()
289  {
290  T r = read<T>(_rpos);
291  _rpos += sizeof(T);
292  return r;
293  }
294 
295  template <typename T> T read(size_t pos) const
296  {
297  if (pos + sizeof(T) > size())
298  throw ByteBufferException(false, pos, sizeof(T), size());
299  T val = *((T const*)&_storage[pos]);
300  EndianConvert(val);
301  return val;
302  }
303 
304  void read(uint8* dest, size_t len)
305  {
306  if (_rpos + len > size())
307  throw ByteBufferException(false, _rpos, len, size());
308  memcpy(dest, &_storage[_rpos], len);
309  _rpos += len;
310  }
311 
313  {
314  uint64 guid = 0;
315  uint8 guidmark = 0;
316  (*this) >> guidmark;
317 
318  for (int i = 0; i < 8; ++i)
319  {
320  if (guidmark & (uint8(1) << i))
321  {
322  uint8 bit;
323  (*this) >> bit;
324  guid |= (uint64(bit) << (i * 8));
325  }
326  }
327 
328  return guid;
329  }
330 
331  const uint8* contents() const
332  {
333  return &_storage[0];
334  }
335 
336  size_t size() const
337  {
338  return _storage.size();
339  }
340  bool empty() const
341  {
342  return _storage.empty();
343  }
344 
345  void resize(size_t newsize)
346  {
347  _storage.resize(newsize);
348  _rpos = 0;
349  _wpos = size();
350  }
351 
352  void reserve(size_t ressize)
353  {
354  if (ressize > size())
355  _storage.reserve(ressize);
356  }
357 
358  void append(const std::string& str)
359  {
360  append((uint8 const*)str.c_str(), str.size() + 1);
361  }
362 
363  void append(const char* src, size_t cnt)
364  {
365  return append((const uint8*)src, cnt);
366  }
367 
368  template<class T> void append(const T* src, size_t cnt)
369  {
370  return append((const uint8*)src, cnt * sizeof(T));
371  }
372 
373  void append(const uint8* src, size_t cnt)
374  {
375  if (!cnt)
376  return;
377 
378  ASSERT(size() < 10000000);
379 
380  if (_storage.size() < _wpos + cnt)
381  _storage.resize(_wpos + cnt);
382  memcpy(&_storage[_wpos], src, cnt);
383  _wpos += cnt;
384  }
385 
386  void append(const ByteBuffer& buffer)
387  {
388  if (buffer.wpos())
389  append(buffer.contents(), buffer.wpos());
390  }
391 
392  // can be used in SMSG_MONSTER_MOVE opcode
393  void appendPackXYZ(float x, float y, float z)
394  {
395  uint32 packed = 0;
396  packed |= ((int)(x / 0.25f) & 0x7FF);
397  packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
398  packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
399  *this << packed;
400  }
401 
403  {
404  uint8 packGUID[8 + 1];
405  packGUID[0] = 0;
406  size_t size = 1;
407  for (uint8 i = 0; guid != 0; ++i)
408  {
409  if (guid & 0xFF)
410  {
411  packGUID[0] |= uint8(1 << i);
412  packGUID[size] = uint8(guid & 0xFF);
413  ++size;
414  }
415 
416  guid >>= 8;
417  }
418 
419  append(packGUID, size);
420  }
421 
422  void put(size_t pos, const uint8* src, size_t cnt)
423  {
424  if (pos + cnt > size())
425  throw ByteBufferException(true, pos, cnt, size());
426  memcpy(&_storage[pos], src, cnt);
427  }
428 
429  void print_storage() const
430  {
431  if (!sLog.IsOutDebug()) // optimize disabled debug output
432  return;
433 
434  sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
435  for (uint32 i = 0; i < size(); ++i)
436  sLog.outDebugInLine("%u - ", read<uint8>(i) );
437  sLog.outDebug(" ");
438  }
439 
440  void textlike() const
441  {
442  if (!sLog.IsOutDebug()) // optimize disabled debug output
443  return;
444 
445  sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
446  for (uint32 i = 0; i < size(); ++i)
447  sLog.outDebugInLine("%c", read<uint8>(i) );
448  sLog.outDebug(" ");
449  }
450 
451  void hexlike() const
452  {
453  if (!sLog.IsOutDebug()) // optimize disabled debug output
454  return;
455 
456  uint32 j = 1, k = 1;
457  sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
458 
459  for (uint32 i = 0; i < size(); ++i)
460  {
461  if ((i == (j * 8)) && ((i != (k * 16))))
462  {
463  if (read<uint8>(i) < 0x10)
464  sLog.outDebugInLine("| 0%X ", read<uint8>(i) );
465  else
466  sLog.outDebugInLine("| %X ", read<uint8>(i) );
467  ++j;
468  }
469  else if (i == (k * 16))
470  {
471  if (read<uint8>(i) < 0x10)
472  {
473  sLog.outDebugInLine("\n");
474 
475  sLog.outDebugInLine("0%X ", read<uint8>(i) );
476  }
477  else
478  {
479  sLog.outDebugInLine("\n");
480 
481  sLog.outDebugInLine("%X ", read<uint8>(i) );
482  }
483 
484  ++k;
485  ++j;
486  }
487  else
488  {
489  if (read<uint8>(i) < 0x10)
490  sLog.outDebugInLine("0%X ", read<uint8>(i) );
491  else
492  sLog.outDebugInLine("%X ", read<uint8>(i) );
493  }
494  }
495  sLog.outDebugInLine("\n");
496  }
497  private:
498  // limited for internal use because can "append" any unexpected type (like pointer and etc) with hard detection problem
499  template <typename T> void append(T value)
500  {
501  EndianConvert(value);
502  append((uint8*)&value, sizeof(value));
503  }
504 
505  protected:
506  size_t _rpos, _wpos;
507  std::vector<uint8> _storage;
508 };
509 
510 template <typename T>
511 inline ByteBuffer& operator<<(ByteBuffer& b, std::vector<T> const& v)
512 {
513  b << (uint32)v.size();
514  for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
515  b << *i;
516  return b;
517 }
518 
519 template <typename T>
520 inline ByteBuffer& operator>>(ByteBuffer& b, std::vector<T>& v)
521 {
522  uint32 vsize;
523  b >> vsize;
524  v.clear();
525  while (vsize--)
526  {
527  T t;
528  b >> t;
529  v.push_back(t);
530  }
531  return b;
532 }
533 
534 template <typename T>
535 inline ByteBuffer& operator<<(ByteBuffer& b, std::list<T> const& v)
536 {
537  b << (uint32)v.size();
538  for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
539  b << *i;
540  return b;
541 }
542 
543 template <typename T>
544 inline ByteBuffer& operator>>(ByteBuffer& b, std::list<T>& v)
545 {
546  uint32 vsize;
547  b >> vsize;
548  v.clear();
549  while (vsize--)
550  {
551  T t;
552  b >> t;
553  v.push_back(t);
554  }
555  return b;
556 }
557 
558 template <typename K, typename V>
559 inline ByteBuffer& operator<<(ByteBuffer& b, std::map<K, V>& m)
560 {
561  b << (uint32)m.size();
562  for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
563  b << i->first << i->second;
564  return b;
565 }
566 
567 template <typename K, typename V>
568 inline ByteBuffer& operator>>(ByteBuffer& b, std::map<K, V>& m)
569 {
570  uint32 msize;
571  b >> msize;
572  m.clear();
573  while (msize--)
574  {
575  K k;
576  V v;
577  b >> k >> v;
578  m.insert(make_pair(k, v));
579  }
580  return b;
581 }
582 
583 template<>
584 inline void ByteBuffer::read_skip<char*>()
585 {
586  std::string temp;
587  *this >> temp;
588 }
589 
590 template<>
591 inline void ByteBuffer::read_skip<char const*>()
592 {
593  read_skip<char*>();
594 }
595 
596 template<>
597 inline void ByteBuffer::read_skip<std::string>()
598 {
599  read_skip<char*>();
600 }
601 #endif
602 
ByteBuffer & operator<<(int32 value)
Definition: ByteBuffer.h:122
ByteBuffer(const ByteBuffer &buf)
Definition: ByteBuffer.h:71
ByteBuffer & operator<<(int64 value)
Definition: ByteBuffer.h:128
ByteBuffer & operator>>(Unused< T > const &)
Definition: ByteBuffer.h:242
const uint8 * contents() const
Definition: ByteBuffer.h:331
void read_skip()
Definition: ByteBuffer.h:276
ByteBuffer & operator<<(uint32 value)
Definition: ByteBuffer.h:97
ByteBuffer & operator>>(uint64 &value)
Definition: ByteBuffer.h:185
void append(const T *src, size_t cnt)
Definition: ByteBuffer.h:368
ByteBuffer & operator>>(uint32 &value)
Definition: ByteBuffer.h:179
void read_skip(size_t skip)
Definition: ByteBuffer.h:281
ByteBuffer & operator<<(const char *str)
Definition: ByteBuffer.h:154
void resize(size_t newsize)
Definition: ByteBuffer.h:345
void PrintPosError() const
Definition: ByteBuffer.h:35
void EndianConvert(T &val)
Definition: ByteConverter.h:48
size_t wpos(size_t wpos_)
Definition: ByteBuffer.h:269
#define sLog
Log class singleton.
Definition: Log.h:187
ByteBuffer & operator>>(int32 &value)
Definition: ByteBuffer.h:204
ByteBuffer & operator<<(int16 value)
Definition: ByteBuffer.h:116
ACE_INT32 int32
Definition: Define.h:67
ByteBuffer & operator<<(float value)
Definition: ByteBuffer.h:135
#define SIZEFMTD
Definition: Common.h:155
ByteBuffer & operator>>(int16 &value)
Definition: ByteBuffer.h:198
std::vector< uint8 > _storage
Definition: ByteBuffer.h:507
void appendPackXYZ(float x, float y, float z)
Definition: ByteBuffer.h:393
void put(size_t pos, const uint8 *src, size_t cnt)
Definition: ByteBuffer.h:422
ByteBuffer & operator>>(ByteBuffer &b, std::vector< T > &v)
Definition: ByteBuffer.h:520
ACE_INT8 int8
Definition: Define.h:69
size_t wpos() const
Definition: ByteBuffer.h:264
void read(uint8 *dest, size_t len)
Definition: ByteBuffer.h:304
ACE_UINT8 uint8
Definition: Define.h:73
ByteBuffer & operator>>(std::string &value)
Definition: ByteBuffer.h:228
ByteBuffer & operator>>(float &value)
Definition: ByteBuffer.h:216
bool empty() const
Definition: ByteBuffer.h:340
size_t size() const
Definition: ByteBuffer.h:336
void put(size_t pos, T value)
Definition: ByteBuffer.h:79
etc mysql my cnf *Then change max_allowed_packet to a bigger value
ByteBuffer & operator<<(uint64 value)
Definition: ByteBuffer.h:103
ByteBuffer & operator>>(uint8 &value)
Definition: ByteBuffer.h:167
void reserve(size_t ressize)
Definition: ByteBuffer.h:352
ByteBuffer(size_t res)
Definition: ByteBuffer.h:65
void hexlike() const
Definition: ByteBuffer.h:451
void append(T value)
Definition: ByteBuffer.h:499
void appendPackGUID(uint64 guid)
Definition: ByteBuffer.h:402
ACE_UINT64 uint64
Definition: Define.h:70
T read(size_t pos) const
Definition: ByteBuffer.h:295
ByteBuffer & operator>>(bool &value)
Definition: ByteBuffer.h:161
void append(const std::string &str)
Definition: ByteBuffer.h:358
ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size)
Definition: ByteBuffer.h:29
ACE_INT64 int64
Definition: Define.h:66
ByteBuffer & operator<<(double value)
Definition: ByteBuffer.h:141
#define ASSERT
Definition: Errors.h:33
void append(const uint8 *src, size_t cnt)
Definition: ByteBuffer.h:373
ByteBuffer & operator>>(int8 &value)
Definition: ByteBuffer.h:192
uint64 readPackGUID()
Definition: ByteBuffer.h:312
ACE_UINT16 uint16
Definition: Define.h:72
ByteBuffer & operator<<(uint8 value)
Definition: ByteBuffer.h:85
ACE_INT16 int16
Definition: Define.h:68
size_t rpos() const
Definition: ByteBuffer.h:253
ACE_UINT32 uint32
Definition: Define.h:71
ByteBuffer & operator<<(uint16 value)
Definition: ByteBuffer.h:91
void print_storage() const
Definition: ByteBuffer.h:429
void textlike() const
Definition: ByteBuffer.h:440
ByteBuffer & operator>>(uint16 &value)
Definition: ByteBuffer.h:173
ByteBuffer & operator<<(int8 value)
Definition: ByteBuffer.h:110
Unused()
Definition: ByteBuffer.h:50
void clear()
Definition: ByteBuffer.h:73
size_t _wpos
Definition: ByteBuffer.h:506
ByteBuffer & operator<<(const std::string &value)
Definition: ByteBuffer.h:147
size_t rpos(size_t rpos_)
Definition: ByteBuffer.h:258
void append(const ByteBuffer &buffer)
Definition: ByteBuffer.h:386
uint8 operator[](size_t pos) const
Definition: ByteBuffer.h:248
ByteBuffer & operator>>(int64 &value)
Definition: ByteBuffer.h:210
ByteBuffer & operator>>(double &value)
Definition: ByteBuffer.h:222
void append(const char *src, size_t cnt)
Definition: ByteBuffer.h:363