2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "Utilities/ByteConverter.h"
27 class ByteBufferException
30 ByteBufferException(bool _add
, size_t _pos
, size_t _esize
, size_t _size
)
31 : add(_add
), pos(_pos
), esize(_esize
), size(_size
)
36 void PrintPosError() const
38 sLog
.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD
" size: "SIZEFMTD
") value with size: " SIZEFMTD
,
39 (add
? "put" : "get"), pos
, size
, esize
);
51 const static size_t DEFAULT_SIZE
= 0x1000;
54 ByteBuffer(): _rpos(0), _wpos(0)
56 _storage
.reserve(DEFAULT_SIZE
);
60 ByteBuffer(size_t res
): _rpos(0), _wpos(0)
62 _storage
.reserve(res
);
66 ByteBuffer(const ByteBuffer
&buf
): _rpos(buf
._rpos
), _wpos(buf
._wpos
), _storage(buf
._storage
) { }
74 template <typename T
> void append(T value
)
77 append((uint8
*)&value
, sizeof(value
));
80 template <typename T
> void put(size_t pos
,T value
)
83 put(pos
,(uint8
*)&value
,sizeof(value
));
86 ByteBuffer
&operator<<(uint8 value
)
92 ByteBuffer
&operator<<(uint16 value
)
94 append
<uint16
>(value
);
98 ByteBuffer
&operator<<(uint32 value
)
100 append
<uint32
>(value
);
104 ByteBuffer
&operator<<(uint64 value
)
106 append
<uint64
>(value
);
110 // signed as in 2e complement
111 ByteBuffer
&operator<<(int8 value
)
117 ByteBuffer
&operator<<(int16 value
)
119 append
<int16
>(value
);
123 ByteBuffer
&operator<<(int32 value
)
125 append
<int32
>(value
);
129 ByteBuffer
&operator<<(int64 value
)
131 append
<int64
>(value
);
136 ByteBuffer
&operator<<(float value
)
138 append
<float>(value
);
142 ByteBuffer
&operator<<(double value
)
144 append
<double>(value
);
148 ByteBuffer
&operator<<(const std::string
&value
)
150 append((uint8
const *)value
.c_str(), value
.length());
155 ByteBuffer
&operator<<(const char *str
)
157 append((uint8
const *)str
, str
? strlen(str
) : 0);
162 ByteBuffer
&operator>>(bool &value
)
164 value
= read
<char>() > 0 ? true : false;
168 ByteBuffer
&operator>>(uint8
&value
)
170 value
= read
<uint8
>();
174 ByteBuffer
&operator>>(uint16
&value
)
176 value
= read
<uint16
>();
180 ByteBuffer
&operator>>(uint32
&value
)
182 value
= read
<uint32
>();
186 ByteBuffer
&operator>>(uint64
&value
)
188 value
= read
<uint64
>();
192 //signed as in 2e complement
193 ByteBuffer
&operator>>(int8
&value
)
195 value
= read
<int8
>();
199 ByteBuffer
&operator>>(int16
&value
)
201 value
= read
<int16
>();
205 ByteBuffer
&operator>>(int32
&value
)
207 value
= read
<int32
>();
211 ByteBuffer
&operator>>(int64
&value
)
213 value
= read
<int64
>();
217 ByteBuffer
&operator>>(float &value
)
219 value
= read
<float>();
223 ByteBuffer
&operator>>(double &value
)
225 value
= read
<double>();
229 ByteBuffer
&operator>>(std::string
& value
)
232 while (rpos() < size()) // prevent crash at wrong string format in packet
234 char c
= read
<char>();
242 uint8
operator[](size_t pos
) const
244 return read
<uint8
>(pos
);
247 size_t rpos() const { return _rpos
; }
249 size_t rpos(size_t rpos_
)
255 size_t wpos() const { return _wpos
; }
257 size_t wpos(size_t wpos_
)
264 void read_skip() { read_skip(sizeof(T
)); }
266 void read_skip(size_t skip
)
268 if(_rpos
+ skip
> size())
269 throw ByteBufferException(false, _rpos
, skip
, size());
273 template <typename T
> T
read()
275 T r
= read
<T
>(_rpos
);
280 template <typename T
> T
read(size_t pos
) const
282 if(pos
+ sizeof(T
) > size())
283 throw ByteBufferException(false, pos
, sizeof(T
), size());
284 T val
= *((T
const*)&_storage
[pos
]);
289 void read(uint8
*dest
, size_t len
)
291 if(_rpos
+ len
> size())
292 throw ByteBufferException(false, _rpos
, len
, size());
293 memcpy(dest
, &_storage
[_rpos
], len
);
297 bool readPackGUID(uint64
& guid
)
299 if(rpos() + 1 > size())
307 for(int i
= 0; i
< 8; ++i
)
309 if(guidmark
& (uint8(1) << i
))
311 if(rpos() + 1 > size())
316 guid
|= (uint64(bit
) << (i
* 8));
323 const uint8
*contents() const { return &_storage
[0]; }
325 size_t size() const { return _storage
.size(); }
326 bool empty() const { return _storage
.empty(); }
328 void resize(size_t newsize
)
330 _storage
.resize(newsize
);
335 void reserve(size_t ressize
)
337 if (ressize
> size())
338 _storage
.reserve(ressize
);
341 void append(const std::string
& str
)
343 append((uint8
const*)str
.c_str(), str
.size() + 1);
346 void append(const char *src
, size_t cnt
)
348 return append((const uint8
*)src
, cnt
);
351 template<class T
> void append(const T
*src
, size_t cnt
)
353 return append((const uint8
*)src
, cnt
* sizeof(T
));
356 void append(const uint8
*src
, size_t cnt
)
361 ASSERT(size() < 10000000);
363 if (_storage
.size() < _wpos
+ cnt
)
364 _storage
.resize(_wpos
+ cnt
);
365 memcpy(&_storage
[_wpos
], src
, cnt
);
369 void append(const ByteBuffer
& buffer
)
372 append(buffer
.contents(), buffer
.wpos());
375 // can be used in SMSG_MONSTER_MOVE opcode
376 void appendPackXYZ(float x
, float y
, float z
)
379 packed
|= ((int)(x
/ 0.25f
) & 0x7FF);
380 packed
|= ((int)(y
/ 0.25f
) & 0x7FF) << 11;
381 packed
|= ((int)(z
/ 0.25f
) & 0x3FF) << 22;
385 void appendPackGUID(uint64 guid
)
387 if (_storage
.size() < _wpos
+ sizeof(guid
) + 1)
388 _storage
.resize(_wpos
+ sizeof(guid
) + 1);
390 size_t mask_position
= wpos();
392 for(uint8 i
= 0; i
< 8; ++i
)
396 _storage
[mask_position
] |= uint8(1 << i
);
397 *this << uint8(guid
& 0xFF);
404 void put(size_t pos
, const uint8
*src
, size_t cnt
)
406 if(pos
+ cnt
> size())
407 throw ByteBufferException(true, pos
, cnt
, size());
408 memcpy(&_storage
[pos
], src
, cnt
);
411 void print_storage() const
413 if(!sLog
.IsOutDebug()) // optimize disabled debug output
416 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
417 for(uint32 i
= 0; i
< size(); ++i
)
418 sLog
.outDebugInLine("%u - ", read
<uint8
>(i
) );
422 void textlike() const
424 if(!sLog
.IsOutDebug()) // optimize disabled debug output
427 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
428 for(uint32 i
= 0; i
< size(); ++i
)
429 sLog
.outDebugInLine("%c", read
<uint8
>(i
) );
435 if(!sLog
.IsOutDebug()) // optimize disabled debug output
439 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
441 if(sLog
.IsIncludeTime())
442 sLog
.outDebugInLine(" ");
444 for(uint32 i
= 0; i
< size(); ++i
)
446 if ((i
== (j
* 8)) && ((i
!= (k
* 16))))
448 if (read
<uint8
>(i
) < 0x10)
450 sLog
.outDebugInLine("| 0%X ", read
<uint8
>(i
) );
454 sLog
.outDebugInLine("| %X ", read
<uint8
>(i
) );
458 else if (i
== (k
* 16))
460 if (read
<uint8
>(i
) < 0x10)
462 sLog
.outDebugInLine("\n");
463 if(sLog
.IsIncludeTime())
464 sLog
.outDebugInLine(" ");
466 sLog
.outDebugInLine("0%X ", read
<uint8
>(i
) );
470 sLog
.outDebugInLine("\n");
471 if(sLog
.IsIncludeTime())
472 sLog
.outDebugInLine(" ");
474 sLog
.outDebugInLine("%X ", read
<uint8
>(i
) );
482 if (read
<uint8
>(i
) < 0x10)
484 sLog
.outDebugInLine("0%X ", read
<uint8
>(i
) );
488 sLog
.outDebugInLine("%X ", read
<uint8
>(i
) );
492 sLog
.outDebugInLine("\n");
497 std::vector
<uint8
> _storage
;
500 template <typename T
>
501 inline ByteBuffer
&operator<<(ByteBuffer
&b
, std::vector
<T
> v
)
503 b
<< (uint32
)v
.size();
504 for (typename
std::vector
<T
>::iterator i
= v
.begin(); i
!= v
.end(); ++i
)
511 template <typename T
>
512 inline ByteBuffer
&operator>>(ByteBuffer
&b
, std::vector
<T
> &v
)
526 template <typename T
>
527 inline ByteBuffer
&operator<<(ByteBuffer
&b
, std::list
<T
> v
)
529 b
<< (uint32
)v
.size();
530 for (typename
std::list
<T
>::iterator i
= v
.begin(); i
!= v
.end(); ++i
)
537 template <typename T
>
538 inline ByteBuffer
&operator>>(ByteBuffer
&b
, std::list
<T
> &v
)
552 template <typename K
, typename V
>
553 inline ByteBuffer
&operator<<(ByteBuffer
&b
, std::map
<K
, V
> &m
)
555 b
<< (uint32
)m
.size();
556 for (typename
std::map
<K
, V
>::iterator i
= m
.begin(); i
!= m
.end(); ++i
)
558 b
<< i
->first
<< i
->second
;
563 template <typename K
, typename V
>
564 inline ByteBuffer
&operator>>(ByteBuffer
&b
, std::map
<K
, V
> &m
)
574 m
.insert(make_pair(k
, v
));
580 inline void ByteBuffer::read_skip
<char*>()
587 inline void ByteBuffer::read_skip
<char const*>()
593 inline void ByteBuffer::read_skip
<std::string
>()