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"
30 const static size_t DEFAULT_SIZE
= 0x1000;
33 ByteBuffer(): _rpos(0), _wpos(0)
35 _storage
.reserve(DEFAULT_SIZE
);
38 ByteBuffer(size_t res
): _rpos(0), _wpos(0)
40 _storage
.reserve(res
);
43 ByteBuffer(const ByteBuffer
&buf
): _rpos(buf
._rpos
), _wpos(buf
._wpos
), _storage(buf
._storage
) { }
51 template <typename T
> void append(T value
)
54 append((uint8
*)&value
, sizeof(value
));
57 template <typename T
> void put(size_t pos
,T value
)
60 put(pos
,(uint8
*)&value
,sizeof(value
));
63 ByteBuffer
&operator<<(uint8 value
)
68 ByteBuffer
&operator<<(uint16 value
)
70 append
<uint16
>(value
);
73 ByteBuffer
&operator<<(uint32 value
)
75 append
<uint32
>(value
);
78 ByteBuffer
&operator<<(uint64 value
)
80 append
<uint64
>(value
);
84 // signed as in 2e complement
85 ByteBuffer
&operator<<(int8 value
)
90 ByteBuffer
&operator<<(int16 value
)
95 ByteBuffer
&operator<<(int32 value
)
100 ByteBuffer
&operator<<(int64 value
)
102 append
<int64
>(value
);
107 ByteBuffer
&operator<<(float value
)
109 append
<float>(value
);
112 ByteBuffer
&operator<<(double value
)
114 append
<double>(value
);
117 ByteBuffer
&operator<<(const std::string
&value
)
119 append((uint8
const *)value
.c_str(), value
.length());
123 ByteBuffer
&operator<<(const char *str
)
125 append((uint8
const *)str
, str
? strlen(str
) : 0);
130 ByteBuffer
&operator>>(bool &value
)
132 value
= read
<char>() > 0 ? true : false;
136 ByteBuffer
&operator>>(uint8
&value
)
138 value
= read
<uint8
>();
141 ByteBuffer
&operator>>(uint16
&value
)
143 value
= read
<uint16
>();
146 ByteBuffer
&operator>>(uint32
&value
)
148 value
= read
<uint32
>();
151 ByteBuffer
&operator>>(uint64
&value
)
153 value
= read
<uint64
>();
157 //signed as in 2e complement
158 ByteBuffer
&operator>>(int8
&value
)
160 value
= read
<int8
>();
163 ByteBuffer
&operator>>(int16
&value
)
165 value
= read
<int16
>();
168 ByteBuffer
&operator>>(int32
&value
)
170 value
= read
<int32
>();
173 ByteBuffer
&operator>>(int64
&value
)
175 value
= read
<int64
>();
179 ByteBuffer
&operator>>(float &value
)
181 value
= read
<float>();
184 ByteBuffer
&operator>>(double &value
)
186 value
= read
<double>();
189 ByteBuffer
&operator>>(std::string
& value
)
192 while (rpos() < size()) // prevent crash at wrong string format in packet
202 uint8
operator[](size_t pos
) const
204 return read
<uint8
>(pos
);
207 size_t rpos() const { return _rpos
; }
209 size_t rpos(size_t rpos_
)
215 size_t wpos() const { return _wpos
; }
217 size_t wpos(size_t wpos_
)
223 template <typename T
> T
read()
229 template <typename T
> T
read(size_t pos
) const
231 ASSERT(pos
+ sizeof(T
) <= size() || PrintPosError(false,pos
,sizeof(T
)));
232 T val
= *((T
const*)&_storage
[pos
]);
237 void read(uint8
*dest
, size_t len
)
239 ASSERT(_rpos
+ len
<= size() || PrintPosError(false,_rpos
,len
));
240 memcpy(dest
, &_storage
[_rpos
], len
);
244 bool readPackGUID(uint64
& guid
)
246 if(rpos()+1 > size())
256 if(guidmark
& (uint8(1) << i
))
258 if(rpos()+1 > size())
263 guid
|= (uint64(bit
) << (i
*8));
270 const uint8
*contents() const { return &_storage
[0]; }
272 size_t size() const { return _storage
.size(); }
273 bool empty() const { return _storage
.empty(); }
275 void resize(size_t newsize
)
277 _storage
.resize(newsize
);
281 void reserve(size_t ressize
)
283 if (ressize
> size()) _storage
.reserve(ressize
);
286 void append(const std::string
& str
)
288 append((uint8
const*)str
.c_str(),str
.size() + 1);
290 void append(const char *src
, size_t cnt
)
292 return append((const uint8
*)src
, cnt
);
295 void append(const T
*src
, size_t cnt
)
297 return append((const uint8
*)src
, cnt
*sizeof(T
));
299 void append(const uint8
*src
, size_t cnt
)
303 ASSERT(size() < 10000000);
305 if (_storage
.size() < _wpos
+ cnt
)
306 _storage
.resize(_wpos
+ cnt
);
307 memcpy(&_storage
[_wpos
], src
, cnt
);
310 void append(const ByteBuffer
& buffer
)
312 if(buffer
.size()) append(buffer
.contents(),buffer
.wpos());
315 void appendPackGUID(uint64 guid
)
317 if (_storage
.size() < _wpos
+ sizeof(guid
) + 1)
318 _storage
.resize(_wpos
+ sizeof(guid
) + 1);
320 size_t mask_position
= wpos();
322 for(uint8 i
= 0; i
< 8; i
++)
326 _storage
[mask_position
] |= uint8(1<<i
);
327 *this << uint8(guid
& 0xFF);
334 void put(size_t pos
, const uint8
*src
, size_t cnt
)
336 ASSERT(pos
+ cnt
<= size() || PrintPosError(true,pos
,cnt
));
337 memcpy(&_storage
[pos
], src
, cnt
);
339 void print_storage() const
341 if(!sLog
.IsOutDebug()) // optimize disabled debug output
344 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
345 for(uint32 i
= 0; i
< size(); i
++)
346 sLog
.outDebugInLine("%u - ", read
<uint8
>(i
) );
350 void textlike() const
352 if(!sLog
.IsOutDebug()) // optimize disabled debug output
355 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
356 for(uint32 i
= 0; i
< size(); i
++)
357 sLog
.outDebugInLine("%c", read
<uint8
>(i
) );
363 if(!sLog
.IsOutDebug()) // optimize disabled debug output
367 sLog
.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
369 if(sLog
.IsIncludeTime())
370 sLog
.outDebugInLine(" ");
372 for(uint32 i
= 0; i
< size(); i
++)
374 if ((i
== (j
*8)) && ((i
!= (k
*16))))
376 if (read
<uint8
>(i
) < 0x10)
378 sLog
.outDebugInLine("| 0%X ", read
<uint8
>(i
) );
382 sLog
.outDebugInLine("| %X ", read
<uint8
>(i
) );
386 else if (i
== (k
*16))
388 if (read
<uint8
>(i
) < 0x10)
390 sLog
.outDebugInLine("\n");
391 if(sLog
.IsIncludeTime())
392 sLog
.outDebugInLine(" ");
394 sLog
.outDebugInLine("0%X ", read
<uint8
>(i
) );
398 sLog
.outDebugInLine("\n");
399 if(sLog
.IsIncludeTime())
400 sLog
.outDebugInLine(" ");
402 sLog
.outDebugInLine("%X ", read
<uint8
>(i
) );
410 if (read
<uint8
>(i
) < 0x10)
412 sLog
.outDebugInLine("0%X ", read
<uint8
>(i
) );
416 sLog
.outDebugInLine("%X ", read
<uint8
>(i
) );
420 sLog
.outDebugInLine("\n");
424 bool PrintPosError(bool add
, size_t pos
, size_t esize
) const
426 sLog
.outError("ERROR: Attempt %s in ByteBuffer (pos: %lu size: %lu) value with size: %lu",(add
? "put" : "get"),(unsigned long)pos
, (unsigned long)size(), (unsigned long)esize
);
428 // assert must fail after function call
433 std::vector
<uint8
> _storage
;
436 template <typename T
> ByteBuffer
&operator<<(ByteBuffer
&b
, std::vector
<T
> v
)
438 b
<< (uint32
)v
.size();
439 for (typename
std::vector
<T
>::iterator i
= v
.begin(); i
!= v
.end(); i
++)
446 template <typename T
> ByteBuffer
&operator>>(ByteBuffer
&b
, std::vector
<T
> &v
)
460 template <typename T
> ByteBuffer
&operator<<(ByteBuffer
&b
, std::list
<T
> v
)
462 b
<< (uint32
)v
.size();
463 for (typename
std::list
<T
>::iterator i
= v
.begin(); i
!= v
.end(); i
++)
470 template <typename T
> ByteBuffer
&operator>>(ByteBuffer
&b
, std::list
<T
> &v
)
484 template <typename K
, typename V
> ByteBuffer
&operator<<(ByteBuffer
&b
, std::map
<K
, V
> &m
)
486 b
<< (uint32
)m
.size();
487 for (typename
std::map
<K
, V
>::iterator i
= m
.begin(); i
!= m
.end(); i
++)
489 b
<< i
->first
<< i
->second
;
494 template <typename K
, typename V
> ByteBuffer
&operator>>(ByteBuffer
&b
, std::map
<K
, V
> &m
)
504 m
.insert(make_pair(k
, v
));