TrinityCore
Loading...
Searching...
No Matches
ByteBuffer.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "Define.h"
22#include "ByteConverter.h"
23#include <array>
24#include <string>
25#include <vector>
26#include <cstring>
27
28class MessageBuffer;
29
30// Root of ByteBuffer exception hierarchy
31class TC_SHARED_API ByteBufferException : public std::exception
32{
33public:
34 ~ByteBufferException() noexcept = default;
35
36 char const* what() const noexcept override { return msg_.c_str(); }
37
38protected:
39 std::string & message() noexcept { return msg_; }
40
41private:
42 std::string msg_;
43};
44
46{
47public:
48 ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize);
49
50 ~ByteBufferPositionException() noexcept = default;
51};
52
54{
55public:
56 ByteBufferSourceException(size_t pos, size_t size, size_t valueSize);
57
58 ~ByteBufferSourceException() noexcept = default;
59};
60
62{
63public:
64 ByteBufferInvalidValueException(char const* type, char const* value);
65
67};
68
70{
71 public:
72 constexpr static size_t DEFAULT_SIZE = 0x1000;
73
74 // constructor
75 ByteBuffer() : _rpos(0), _wpos(0)
76 {
77 _storage.reserve(DEFAULT_SIZE);
78 }
79
80 ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
81 {
82 _storage.reserve(reserve);
83 }
84
85 ByteBuffer(ByteBuffer&& buf) noexcept : _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf.Move())
86 {
87 }
88
89 ByteBuffer(ByteBuffer const& right) = default;
90
91 ByteBuffer(MessageBuffer&& buffer);
92
93 std::vector<uint8>&& Move()
94 {
95 _rpos = 0;
96 _wpos = 0;
97 return std::move(_storage);
98 }
99
101 {
102 if (this != &right)
103 {
104 _rpos = right._rpos;
105 _wpos = right._wpos;
106 _storage = right._storage;
107 }
108
109 return *this;
110 }
111
112 ByteBuffer& operator=(ByteBuffer&& right) noexcept
113 {
114 if (this != &right)
115 {
116 _rpos = right._rpos;
117 _wpos = right._wpos;
118 _storage = right.Move();
119 }
120
121 return *this;
122 }
123
124 virtual ~ByteBuffer() = default;
125
126 void clear()
127 {
128 _rpos = 0;
129 _wpos = 0;
130 _storage.clear();
131 }
132
133 template <typename T> void append(T value)
134 {
135 static_assert(std::is_fundamental<T>::value, "append(compound)");
136 EndianConvert(value);
137 append((uint8 *)&value, sizeof(value));
138 }
139
140 template <typename T>
141 void put(std::size_t pos, T value)
142 {
143 static_assert(std::is_fundamental<T>::value, "append(compound)");
144 EndianConvert(value);
145 put(pos, (uint8 *)&value, sizeof(value));
146 }
147
149 {
150 append<uint8>(value ? 1 : 0);
151 return *this;
152 }
153
155 {
156 append<uint8>(value);
157 return *this;
158 }
159
161 {
162 append<uint16>(value);
163 return *this;
164 }
165
167 {
168 append<uint32>(value);
169 return *this;
170 }
171
173 {
174 append<uint64>(value);
175 return *this;
176 }
177
178 // signed as in 2e complement
180 {
181 append<int8>(value);
182 return *this;
183 }
184
186 {
187 append<int16>(value);
188 return *this;
189 }
190
192 {
193 append<int32>(value);
194 return *this;
195 }
196
198 {
199 append<int64>(value);
200 return *this;
201 }
202
203 // floating points
204 ByteBuffer &operator<<(float value)
205 {
206 append<float>(value);
207 return *this;
208 }
209
210 ByteBuffer &operator<<(double value)
211 {
212 append<double>(value);
213 return *this;
214 }
215
216 ByteBuffer &operator<<(std::string_view value)
217 {
218 if (size_t len = value.length())
219 append(reinterpret_cast<uint8 const*>(value.data()), len);
220 append(static_cast<uint8>(0));
221 return *this;
222 }
223
224 ByteBuffer& operator<<(std::string const& str)
225 {
226 return operator<<(std::string_view(str));
227 }
228
229 ByteBuffer &operator<<(char const* str)
230 {
231 return operator<<(std::string_view(str ? str : ""));
232 }
233
234 ByteBuffer &operator>>(bool &value)
235 {
236 value = read<char>() > 0 ? true : false;
237 return *this;
238 }
239
241 {
242 value = read<uint8>();
243 return *this;
244 }
245
247 {
248 value = read<uint16>();
249 return *this;
250 }
251
253 {
254 value = read<uint32>();
255 return *this;
256 }
257
259 {
260 value = read<uint64>();
261 return *this;
262 }
263
264 //signed as in 2e complement
266 {
267 value = read<int8>();
268 return *this;
269 }
270
272 {
273 value = read<int16>();
274 return *this;
275 }
276
278 {
279 value = read<int32>();
280 return *this;
281 }
282
284 {
285 value = read<int64>();
286 return *this;
287 }
288
289 ByteBuffer &operator>>(float &value);
290 ByteBuffer &operator>>(double &value);
291
292 ByteBuffer& operator>>(std::string& value)
293 {
294 value = ReadCString(true);
295 return *this;
296 }
297
298 uint8& operator[](size_t const pos)
299 {
300 if (pos >= size())
301 throw ByteBufferPositionException(false, pos, 1, size());
302 return _storage[pos];
303 }
304
305 uint8 const& operator[](size_t const pos) const
306 {
307 if (pos >= size())
308 throw ByteBufferPositionException(false, pos, 1, size());
309 return _storage[pos];
310 }
311
312 size_t rpos() const { return _rpos; }
313
314 size_t rpos(size_t rpos_)
315 {
316 _rpos = rpos_;
317 return _rpos;
318 }
319
320 void rfinish()
321 {
322 _rpos = wpos();
323 }
324
325 size_t wpos() const { return _wpos; }
326
327 size_t wpos(size_t wpos_)
328 {
329 _wpos = wpos_;
330 return _wpos;
331 }
332
333 template<typename T>
334 void read_skip() { read_skip(sizeof(T)); }
335
336 void read_skip(size_t skip)
337 {
338 if (_rpos + skip > size())
339 throw ByteBufferPositionException(false, _rpos, skip, size());
340 _rpos += skip;
341 }
342
343 template <typename T> T read()
344 {
345 T r = read<T>(_rpos);
346 _rpos += sizeof(T);
347 return r;
348 }
349
350 template <typename T> T read(size_t pos) const
351 {
352 if (pos + sizeof(T) > size())
353 throw ByteBufferPositionException(false, pos, sizeof(T), size());
354 T val = *((T const*)&_storage[pos]);
355 EndianConvert(val);
356 return val;
357 }
358
359 void read(uint8 *dest, size_t len)
360 {
361 if (_rpos + len > size())
362 throw ByteBufferPositionException(false, _rpos, len, size());
363 std::memcpy(dest, &_storage[_rpos], len);
364 _rpos += len;
365 }
366
367 template <size_t Size>
368 void read(std::array<uint8, Size>& arr)
369 {
370 read(arr.data(), Size);
371 }
372
374 {
375 if (rpos() + 1 > size())
376 throw ByteBufferPositionException(false, _rpos, 1, size());
377
378 guid = 0;
379
380 uint8 guidmark = 0;
381 (*this) >> guidmark;
382
383 for (int i = 0; i < 8; ++i)
384 {
385 if (guidmark & (uint8(1) << i))
386 {
387 if (rpos() + 1 > size())
388 throw ByteBufferPositionException(false, _rpos, 1, size());
389
390 uint8 bit;
391 (*this) >> bit;
392 guid |= (uint64(bit) << (i * 8));
393 }
394 }
395 }
396
397 std::string ReadCString(bool requireValidUtf8 = true);
398
400 {
401 if (_storage.empty())
402 throw ByteBufferException();
403 return _storage.data();
404 }
405
406 uint8 const* contents() const
407 {
408 if (_storage.empty())
409 throw ByteBufferException();
410 return _storage.data();
411 }
412
413 size_t size() const { return _storage.size(); }
414 bool empty() const { return _storage.empty(); }
415
416 void resize(size_t newsize)
417 {
418 _storage.resize(newsize, 0);
419 _rpos = 0;
420 _wpos = size();
421 }
422
423 void reserve(size_t ressize)
424 {
425 if (ressize > size())
426 _storage.reserve(ressize);
427 }
428
430 {
431 _storage.shrink_to_fit();
432 }
433
434 void append(const char *src, size_t cnt)
435 {
436 return append((const uint8 *)src, cnt);
437 }
438
439 template<class T> void append(const T *src, size_t cnt)
440 {
441 return append((const uint8 *)src, cnt * sizeof(T));
442 }
443
444 void append(uint8 const* src, size_t cnt);
445
446 void append(ByteBuffer const& buffer)
447 {
448 if (buffer.wpos())
449 append(buffer.contents(), buffer.wpos());
450 }
451
452 template <size_t Size>
453 void append(std::array<uint8, Size> const& arr)
454 {
455 append(arr.data(), Size);
456 }
457
458 // can be used in SMSG_MONSTER_MOVE opcode
459 void appendPackXYZ(float x, float y, float z)
460 {
461 uint32 packed = 0;
462 packed |= ((int)(x / 0.25f) & 0x7FF);
463 packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
464 packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
465 *this << packed;
466 }
467
469 {
470 uint8 packGUID[8+1];
471 packGUID[0] = 0;
472 size_t size = 1;
473 for (uint8 i = 0;guid != 0;++i)
474 {
475 if (guid & 0xFF)
476 {
477 packGUID[0] |= uint8(1 << i);
478 packGUID[size] = uint8(guid & 0xFF);
479 ++size;
480 }
481
482 guid >>= 8;
483 }
484 append(packGUID, size);
485 }
486
487 void put(size_t pos, const uint8 *src, size_t cnt);
488
489 void print_storage() const;
490
491 void textlike() const;
492
493 void hexlike() const;
494
495 protected:
496 size_t _rpos, _wpos;
497 std::vector<uint8> _storage;
498};
499
501template<> inline std::string ByteBuffer::read<std::string>()
502{
503 std::string tmp;
504 *this >> tmp;
505 return tmp;
506}
507
508template<>
509inline void ByteBuffer::read_skip<char*>()
510{
511 std::string temp;
512 *this >> temp;
513}
514
515template<>
516inline void ByteBuffer::read_skip<char const*>()
517{
518 read_skip<char*>();
519}
520
521template<>
522inline void ByteBuffer::read_skip<std::string>()
523{
524 read_skip<char*>();
525}
526
527#endif
void EndianConvert(T &val)
uint8_t uint8
Definition Define.h:135
#define TC_SHARED_API
Definition Define.h:108
int64_t int64
Definition Define.h:128
int16_t int16
Definition Define.h:130
int8_t int8
Definition Define.h:131
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
ByteBuffer & operator<<(ByteBuffer &buf, ObjectGuid const &guid)
ByteBuffer & operator>>(ByteBuffer &buf, ObjectGuid &guid)
std::string msg_
Definition ByteBuffer.h:42
~ByteBufferException() noexcept=default
std::string & message() noexcept
Definition ByteBuffer.h:39
~ByteBufferInvalidValueException() noexcept=default
~ByteBufferPositionException() noexcept=default
~ByteBufferSourceException() noexcept=default
ByteBuffer & operator<<(bool value)
Definition ByteBuffer.h:148
void append(std::array< uint8, Size > const &arr)
Definition ByteBuffer.h:453
size_t _wpos
Definition ByteBuffer.h:496
void read(std::array< uint8, Size > &arr)
Definition ByteBuffer.h:368
ByteBuffer & operator<<(uint32 value)
Definition ByteBuffer.h:166
ByteBuffer & operator>>(int64 &value)
Definition ByteBuffer.h:283
void read_skip()
Definition ByteBuffer.h:334
ByteBuffer & operator<<(double value)
Definition ByteBuffer.h:210
ByteBuffer & operator<<(std::string const &str)
Definition ByteBuffer.h:224
ByteBuffer(size_t reserve)
Definition ByteBuffer.h:80
void appendPackXYZ(float x, float y, float z)
Definition ByteBuffer.h:459
ByteBuffer & operator>>(uint32 &value)
Definition ByteBuffer.h:252
size_t rpos() const
Definition ByteBuffer.h:312
ByteBuffer & operator<<(uint8 value)
Definition ByteBuffer.h:154
std::vector< uint8 > _storage
Definition ByteBuffer.h:497
ByteBuffer & operator<<(int32 value)
Definition ByteBuffer.h:191
void reserve(size_t ressize)
Definition ByteBuffer.h:423
uint8 const * contents() const
Definition ByteBuffer.h:406
ByteBuffer & operator=(ByteBuffer const &right)
Definition ByteBuffer.h:100
void appendPackGUID(uint64 guid)
Definition ByteBuffer.h:468
ByteBuffer & operator<<(int64 value)
Definition ByteBuffer.h:197
ByteBuffer & operator<<(std::string_view value)
Definition ByteBuffer.h:216
T read(size_t pos) const
Definition ByteBuffer.h:350
std::vector< uint8 > && Move()
Definition ByteBuffer.h:93
void resize(size_t newsize)
Definition ByteBuffer.h:416
ByteBuffer & operator>>(int16 &value)
Definition ByteBuffer.h:271
void read_skip(size_t skip)
Definition ByteBuffer.h:336
void shrink_to_fit()
Definition ByteBuffer.h:429
ByteBuffer & operator>>(uint8 &value)
Definition ByteBuffer.h:240
void append(T value)
Definition ByteBuffer.h:133
ByteBuffer & operator<<(float value)
Definition ByteBuffer.h:204
void append(const T *src, size_t cnt)
Definition ByteBuffer.h:439
ByteBuffer & operator>>(int8 &value)
Definition ByteBuffer.h:265
ByteBuffer & operator>>(uint16 &value)
Definition ByteBuffer.h:246
void rfinish()
Definition ByteBuffer.h:320
uint8 & operator[](size_t const pos)
Definition ByteBuffer.h:298
uint8 const & operator[](size_t const pos) const
Definition ByteBuffer.h:305
ByteBuffer & operator<<(uint16 value)
Definition ByteBuffer.h:160
size_t wpos() const
Definition ByteBuffer.h:325
void append(ByteBuffer const &buffer)
Definition ByteBuffer.h:446
ByteBuffer & operator>>(std::string &value)
Definition ByteBuffer.h:292
ByteBuffer & operator=(ByteBuffer &&right) noexcept
Definition ByteBuffer.h:112
size_t rpos(size_t rpos_)
Definition ByteBuffer.h:314
void put(std::size_t pos, T value)
Definition ByteBuffer.h:141
ByteBuffer(ByteBuffer &&buf) noexcept
Definition ByteBuffer.h:85
ByteBuffer & operator>>(int32 &value)
Definition ByteBuffer.h:277
void clear()
Definition ByteBuffer.h:126
ByteBuffer & operator<<(uint64 value)
Definition ByteBuffer.h:172
ByteBuffer & operator<<(int16 value)
Definition ByteBuffer.h:185
size_t size() const
Definition ByteBuffer.h:413
bool empty() const
Definition ByteBuffer.h:414
ByteBuffer(ByteBuffer const &right)=default
size_t _rpos
Definition ByteBuffer.h:496
void readPackGUID(uint64 &guid)
Definition ByteBuffer.h:373
size_t wpos(size_t wpos_)
Definition ByteBuffer.h:327
ByteBuffer & operator<<(int8 value)
Definition ByteBuffer.h:179
void append(const char *src, size_t cnt)
Definition ByteBuffer.h:434
ByteBuffer & operator>>(bool &value)
Definition ByteBuffer.h:234
uint8 * contents()
Definition ByteBuffer.h:399
ByteBuffer & operator>>(uint64 &value)
Definition ByteBuffer.h:258
ByteBuffer & operator<<(char const *str)
Definition ByteBuffer.h:229
virtual ~ByteBuffer()=default
void read(uint8 *dest, size_t len)
Definition ByteBuffer.h:359