18#ifndef TRINITYCORE_BYTE_BUFFER_H
19#define TRINITYCORE_BYTE_BUFFER_H
37 char const*
what() const noexcept
override {
return msg_.c_str(); }
58 constexpr static size_t DEFAULT_SIZE = 0x1000;
59 constexpr static uint8 InitialBitPos = 8;
62 ByteBuffer() : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
64 _storage.reserve(DEFAULT_SIZE);
73 _storage.reserve(
size);
78 _storage.resize(
size);
82 _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf.Move()) { }
88 std::vector<uint8>&&
Move() noexcept
92 _bitpos = InitialBitPos;
94 return std::move(_storage);
117 _bitpos = right._bitpos;
118 _curbitval = right._curbitval;
119 _storage = right.Move();
131 _bitpos = InitialBitPos;
136 template <
typename T>
139 static_assert(std::is_trivially_copyable_v<T>,
"append(T) must be used with trivially copyable types");
141 append(
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
156 append(&_curbitval,
sizeof(
uint8));
173 _curbitval |= (1 << (_bitpos));
178 append(&_curbitval,
sizeof(_curbitval));
190 _curbitval = read<uint8>();
194 return ((_curbitval >> (7 - _bitpos)) & 1) != 0;
200 value &= (
UI64LIT(1) << bits) - 1;
202 if (bits >
int32(_bitpos))
205 _curbitval |= value >> (bits - _bitpos);
208 append(&_curbitval,
sizeof(_curbitval));
214 append<uint8>(value >> bits);
219 _curbitval = (value & ((
UI64LIT(1) << bits) - 1)) << _bitpos;
225 _curbitval |= value << _bitpos;
230 append(&_curbitval,
sizeof(_curbitval));
239 for (
int32 i = bits - 1; i >= 0; --i)
240 value |=
uint32(ReadBit()) << i;
245 template <
typename T>
246 void put(std::size_t pos, T value)
248 static_assert(std::is_trivially_copyable_v<T>,
"put(size_t, T) must be used with trivially copyable types");
250 put(pos,
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
265 void PutBits(std::size_t pos, std::size_t value,
uint32 bitCount);
269 append<uint8>(value);
275 append<uint16>(value);
281 append<uint32>(value);
287 append<uint64>(value);
300 append<int16>(value);
306 append<int32>(value);
312 append<int64>(value);
319 append<float>(value);
325 append<double>(value);
331 if (
size_t len = value.length())
332 append(
reinterpret_cast<uint8 const*
>(value.data()), len);
333 append(
static_cast<uint8>(0));
344 return operator<<(std::string_view(str ? str :
""));
349 value = read<char>() > 0;
407 value = ReadCString(
true);
415 return _storage[pos];
422 return _storage[pos];
425 size_t rpos()
const {
return _rpos; }
438 size_t wpos()
const {
return _wpos; }
447 size_t bitwpos()
const {
return _wpos * 8 + 8 - _bitpos; }
452 _bitpos = 8 - (newPos % 8);
453 return _wpos * 8 + 8 - _bitpos;
456 template <
typename T>
461 if (_rpos + skip >
size())
468 template <
typename T>
472 T r = read<T>(_rpos);
477 template <
typename T>
480 if (pos +
sizeof(T) >
size())
483 std::memcpy(&val, &_storage[pos],
sizeof(T));
488 template <
typename T>
489 void read(T* dest,
size_t count)
491 static_assert(std::is_trivially_copyable_v<T>,
"read(T*, size_t) must be used with trivially copyable types");
492 read(
reinterpret_cast<uint8*
>(dest), count *
sizeof(T));
493#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
494 for (
size_t i = 0; i < count; ++i)
501 if (_rpos + len >
size())
505 std::memcpy(dest, &_storage[_rpos], len);
509 template <
size_t Size>
510 void read(std::array<uint8, Size>& arr)
512 read(arr.data(), Size);
518 ReadPackedUInt64(read<uint8>(), guid);
523 for (
uint32 i = 0; i < 8; ++i)
524 if (mask & (
uint8(1) << i))
525 value |= (
uint64(read<uint8>()) << (i * 8));
532 if (
size_t len = str.length())
533 append(str.c_str(), len);
538 if (
size_t len = str.length())
539 append(str.data(), len);
548 std::string_view ReadCString(
bool requireValidUtf8 =
true);
550 std::string_view ReadString(
uint32 length,
bool requireValidUtf8 =
true);
554 if (_storage.empty())
556 return _storage.data();
561 if (_storage.empty())
563 return _storage.data();
566 size_t size()
const {
return _storage.size(); }
567 bool empty()
const {
return _storage.empty(); }
571 _storage.resize(newsize, 0);
578 if (ressize >
size())
579 _storage.reserve(ressize);
584 _storage.shrink_to_fit();
587 template <
typename T>
590#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
591 append(
reinterpret_cast<uint8 const*
>(src), cnt *
sizeof(T));
593 for (
size_t i = 0; i < cnt; ++i)
598 void append(
uint8 const* src,
size_t cnt);
606 template <
size_t Size>
607 void append(std::array<uint8, Size>
const& arr)
609 append(arr.data(), Size);
616 packed |= ((int)(x / 0.25f) & 0x7FF);
617 packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
618 packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
626 *
this <<
uint8(mask);
629 if (
size_t packedSize = PackUInt64(guid, &mask, packed))
630 append(packed, packedSize);
632 put<uint8>(pos, mask);
637 size_t resultSize = 0;
639 memset(result, 0, 8);
641 for (
uint8 i = 0; value != 0; ++i)
645 *mask |=
uint8(1 << i);
646 result[resultSize++] =
uint8(value & 0xFF);
655 void put(
size_t pos,
uint8 const* src,
size_t cnt);
657 void print_storage()
const;
659 void textlike()
const;
661 void hexlike()
const;
671template <>
inline std::string ByteBuffer::read<std::string>()
673 return std::string(ReadCString());
677inline void ByteBuffer::read_skip<char*>()
683inline void ByteBuffer::read_skip<char const*>()
689inline void ByteBuffer::read_skip<std::string>()
void EndianConvert(T &val)
ByteBuffer & operator<<(ByteBuffer &buf, ObjectGuid const &guid)
ByteBuffer & operator>>(ByteBuffer &buf, ObjectGuid &guid)
ByteBufferException(std::string &&message) noexcept
char const * what() const noexcept override
ByteBufferException()=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)
void append(T const *src, size_t cnt)
ByteBuffer & operator<<(float value)
ByteBuffer & operator>>(int8 &value)
std::string_view ReadCString(bool requireValidUtf8=true)
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)
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
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)
void WriteBits(uint64 value, int32 bits)
constexpr std::size_t size()