36 char const* what() const noexcept
override {
return msg_.c_str(); }
39 std::string &
message() noexcept {
return msg_; }
64 constexpr static size_t DEFAULT_SIZE = 0x1000;
65 constexpr static uint8 InitialBitPos = 8;
68 ByteBuffer() : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
70 _storage.reserve(DEFAULT_SIZE);
77 ByteBuffer(
size_t size,
Reserve) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
79 _storage.reserve(size);
82 ByteBuffer(
size_t size,
Resize) : _rpos(0), _wpos(size), _bitpos(InitialBitPos), _curbitval(0)
84 _storage.resize(size);
88 _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf.Move()) { }
94 std::vector<uint8>&&
Move() noexcept
98 _bitpos = InitialBitPos;
100 return std::move(_storage);
123 _bitpos = right._bitpos;
124 _curbitval = right._curbitval;
125 _storage = right.Move();
137 _bitpos = InitialBitPos;
142 template <
typename T>
145 static_assert(std::is_trivially_copyable<T>::value,
"append(T) must be used with trivially copyable types");
147 append((
uint8 *)&value,
sizeof(value));
179 _curbitval |= (1 << (_bitpos));
184 append((
uint8 *)&_curbitval,
sizeof(_curbitval));
196 _curbitval = read<uint8>();
200 return ((_curbitval >> (7-_bitpos)) & 1) != 0;
205 for (
int32 i = bits - 1; i >= 0; --i)
206 WriteBit((value >> i) & 1);
212 for (
int32 i = bits - 1; i >= 0; --i)
219 template <
typename T>
220 void put(std::size_t pos, T value)
222 static_assert(std::is_trivially_copyable<T>::value,
"put(size_t, T) must be used with trivially copyable types");
224 put(pos, (
uint8 *)&value,
sizeof(value));
239 void PutBits(std::size_t pos, std::size_t value,
uint32 bitCount);
243 append<uint8>(value);
249 append<uint16>(value);
255 append<uint32>(value);
261 append<uint64>(value);
274 append<int16>(value);
280 append<int32>(value);
286 append<int64>(value);
293 append<float>(value);
299 append<double>(value);
305 if (
size_t len = value.length())
306 append(
reinterpret_cast<uint8 const*
>(value.data()), len);
307 append(
static_cast<uint8>(0));
318 return operator<<(std::string_view(str ? str :
""));
323 value = read<char>() > 0 ? true :
false;
329 value = read<uint8>();
335 value = read<uint16>();
341 value = read<uint32>();
347 value = read<uint64>();
354 value = read<int8>();
360 value = read<int16>();
366 value = read<int32>();
372 value = read<int64>();
381 value = ReadCString(
true);
389 return _storage[pos];
396 return _storage[pos];
399 size_t rpos()
const {
return _rpos; }
412 size_t wpos()
const {
return _wpos; }
421 size_t bitwpos()
const {
return _wpos * 8 + 8 - _bitpos; }
426 _bitpos = 8 - (newPos % 8);
427 return _wpos * 8 + 8 - _bitpos;
435 if (_rpos + skip > size())
442 template <
typename T,
typename Underlying = T>
446 T r = read<T, Underlying>(_rpos);
447 _rpos +=
sizeof(Underlying);
451 template <
typename T,
typename Underlying = T>
454 if (pos +
sizeof(Underlying) > size())
457 std::memcpy(&val, &_storage[pos],
sizeof(Underlying));
459 return static_cast<T
>(val);
463 void read(T* dest,
size_t count)
465 static_assert(std::is_trivially_copyable<T>::value,
"read(T*, size_t) must be used with trivially copyable types");
466 return read(
reinterpret_cast<uint8*
>(dest), count *
sizeof(T));
471 if (_rpos + len > size())
475 std::memcpy(dest, &_storage[_rpos], len);
479 template <
size_t Size>
480 void read(std::array<uint8, Size>& arr)
482 read(arr.data(), Size);
488 ReadPackedUInt64(read<uint8>(), guid);
493 for (
uint32 i = 0; i < 8; ++i)
494 if (mask & (
uint8(1) << i))
495 value |= (
uint64(read<uint8>()) << (i * 8));
502 if (
size_t len = str.length())
503 append(str.c_str(), len);
508 if (
size_t len = str.length())
509 append(str.data(), len);
518 std::string ReadCString(
bool requireValidUtf8 =
true);
520 std::string ReadString(
uint32 length,
bool requireValidUtf8 =
true);
526 if (_storage.empty())
528 return _storage.data();
533 if (_storage.empty())
535 return _storage.data();
538 size_t size()
const {
return _storage.size(); }
539 bool empty()
const {
return _storage.empty(); }
543 _storage.resize(newsize, 0);
550 if (ressize > size())
551 _storage.reserve(ressize);
556 _storage.shrink_to_fit();
561 return append((
const uint8 *)src, cnt);
567 return append((
const uint8 *)src, cnt *
sizeof(T));
570 void append(
uint8 const* src,
size_t cnt);
578 template <
size_t Size>
579 void append(std::array<uint8, Size>
const& arr)
581 append(arr.data(), Size);
588 packed |= ((int)(x / 0.25f) & 0x7FF);
589 packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
590 packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
598 *
this <<
uint8(mask);
601 if (
size_t packedSize = PackUInt64(guid, &mask, packed))
602 append(packed, packedSize);
604 put<uint8>(pos, mask);
609 size_t resultSize = 0;
611 memset(result, 0, 8);
613 for (
uint8 i = 0; value != 0; ++i)
617 *mask |=
uint8(1 << i);
618 result[resultSize++] =
uint8(value & 0xFF);
627 void AppendPackedTime(time_t time);
629 void put(
size_t pos,
uint8 const* src,
size_t cnt);
631 void print_storage()
const;
633 void textlike()
const;
635 void hexlike()
const;
644template<>
inline std::string ByteBuffer::read<std::string>()
652inline void ByteBuffer::read_skip<char*>()
659inline void ByteBuffer::read_skip<char const*>()
665inline void ByteBuffer::read_skip<std::string>()
void EndianConvert(T &val)
ByteBuffer & operator<<(ByteBuffer &buf, ObjectGuid const &guid)
ByteBuffer & operator>>(ByteBuffer &buf, ObjectGuid &guid)
~ByteBufferException() noexcept=default
std::string & message() noexcept
~ByteBufferInvalidValueException() noexcept=default
~ByteBufferPositionException() noexcept=default
void append(std::array< uint8, Size > const &arr)
uint32 ReadBits(int32 bits)
void read(std::array< uint8, Size > &arr)
ByteBuffer & operator<<(uint32 value)
ByteBuffer & operator>>(int64 &value)
ByteBuffer & operator<<(double value)
ByteBuffer & operator<<(std::string const &str)
void appendPackXYZ(float x, float y, float z)
ByteBuffer & operator>>(uint32 &value)
ByteBuffer & operator<<(uint8 value)
size_t bitwpos() const
Returns position of last written bit.
std::vector< uint8 > _storage
ByteBuffer & operator<<(int32 value)
void reserve(size_t ressize)
uint8 const * contents() const
void WriteString(std::string const &str)
ByteBuffer & operator=(ByteBuffer const &right)
void WriteString(char const *str, size_t len)
void ReadPackedUInt64(uint8 mask, uint64 &value)
ByteBuffer & operator<<(int64 value)
ByteBuffer & operator<<(std::string_view value)
void resize(size_t newsize)
std::vector< uint8 > && Move() noexcept
static size_t PackUInt64(uint64 value, uint8 *mask, uint8 *result)
ByteBuffer & operator>>(int16 &value)
void read_skip(size_t skip)
ByteBuffer & operator>>(uint8 &value)
ByteBuffer & operator<<(float value)
void append(const T *src, size_t cnt)
ByteBuffer & operator>>(int8 &value)
ByteBuffer & operator>>(uint16 &value)
uint8 & operator[](size_t const pos)
uint8 const & operator[](size_t const pos) const
void WriteString(std::string_view str)
ByteBuffer & operator<<(uint16 value)
void append(ByteBuffer const &buffer)
ByteBuffer & operator>>(std::string &value)
void WriteBits(std::size_t value, int32 bits)
ByteBuffer & operator=(ByteBuffer &&right) noexcept
size_t rpos(size_t rpos_)
ByteBuffer(size_t size, Resize)
void ReadPackedUInt64(uint64 &guid)
void put(std::size_t pos, T value)
ByteBuffer(ByteBuffer &&buf) noexcept
ByteBuffer & operator>>(int32 &value)
ByteBuffer & operator<<(uint64 value)
ByteBuffer & operator<<(int16 value)
void read(T *dest, size_t count)
void AppendPackedUInt64(uint64 guid)
ByteBuffer(ByteBuffer const &right)=default
size_t bitwpos(size_t newPos)
size_t wpos(size_t wpos_)
ByteBuffer & operator<<(int8 value)
bool HasUnfinishedBitPack() const
void append(const char *src, size_t cnt)
ByteBuffer & operator>>(bool &value)
ByteBuffer(size_t size, Reserve)
ByteBuffer & operator>>(uint64 &value)
ByteBuffer & operator<<(char const *str)
virtual ~ByteBuffer()=default
void read(uint8 *dest, size_t len)