18#ifndef TRINITYCORE_BYTE_BUFFER_H
19#define TRINITYCORE_BYTE_BUFFER_H
36 char const*
what() const noexcept
override {
return msg_.c_str(); }
56 || std::same_as<T, int16> || std::same_as<T, uint16>
57 || std::same_as<T, int32> || std::same_as<T, uint32>
58 || std::same_as<T, int64> || std::same_as<T, uint64>
59 || std::same_as<T, float> || std::same_as<T, double>
60 || std::same_as<T, char> || std::is_enum_v<T>;
65 constexpr static size_t DEFAULT_SIZE = 0x1000;
66 constexpr static uint8 InitialBitPos = 8;
75 explicit ByteBuffer(
size_t size,
Reserve) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
77 _storage.reserve(size);
80 explicit ByteBuffer(
size_t size,
Resize) : _rpos(0), _wpos(size), _bitpos(InitialBitPos), _curbitval(0)
82 _storage.resize(size);
88 _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(std::move(buf).
Release()) { }
90 explicit ByteBuffer(std::vector<uint8>&& buffer) noexcept : _rpos(0), _wpos(buffer.size()),
91 _bitpos(InitialBitPos), _curbitval(0), _storage(std::move(buffer)) { }
93 std::vector<uint8>&&
Release() &&
noexcept
97 _bitpos = InitialBitPos;
99 return std::move(_storage);
110 _bitpos = right._bitpos;
111 _curbitval = right._curbitval;
112 _storage = std::move(right).Release();
124 _bitpos = InitialBitPos;
129 template <ByteBufferNumeric T>
133 append(
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
148 append(&_curbitval,
sizeof(
uint8));
162 _curbitval |= (1 << (_bitpos));
167 append(&_curbitval,
sizeof(_curbitval));
178 read(&_curbitval, 1);
182 return ((_curbitval >> (8 - ++_bitpos)) & 1) != 0;
188 value &= (
UI64LIT(1) << bits) - 1;
190 if (bits >
int32(_bitpos))
193 _curbitval |= value >> (bits - _bitpos);
196 append(&_curbitval,
sizeof(_curbitval));
202 append<uint8>(value >> bits);
207 _curbitval = (value & ((
UI64LIT(1) << bits) - 1)) << _bitpos;
213 _curbitval |= value << _bitpos;
218 append(&_curbitval,
sizeof(_curbitval));
227 if (bits > 8 -
int32(_bitpos))
230 int32 bitsInBuffer = 8 - _bitpos;
231 value = (_curbitval & ((
UI64LIT(1) << bitsInBuffer) - 1)) << (bits - bitsInBuffer);
232 bits -= bitsInBuffer;
238 value |= read<uint8>() << bits;
244 read(&_curbitval, 1);
245 value |= (_curbitval >> (8 - bits)) & ((
UI64LIT(1) << bits) - 1);
252 value = (_curbitval >> (8 - _bitpos - bits)) & ((
UI64LIT(1) << bits) - 1);
259 template <ByteBufferNumeric T>
260 void put(std::size_t pos, T value)
263 put(pos,
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
278 void PutBits(std::size_t pos, std::size_t value,
uint32 bitCount);
290 append<uint8>(value);
296 append<uint16>(value);
302 append<uint32>(value);
308 append<uint64>(value);
321 append<int16>(value);
327 append<int32>(value);
333 append<int64>(value);
340 append<float>(value);
346 append<double>(value);
352 if (
size_t len = value.length())
353 append(
reinterpret_cast<uint8 const*
>(value.data()), len);
354 append(
static_cast<uint8>(0));
365 return operator<<(std::string_view(str ? str :
""));
430 value = ReadCString(
true);
436 if (pos >= _storage.size())
437 OnInvalidPosition(pos, 1);
438 return _storage[pos];
443 if (pos >= _storage.size())
444 OnInvalidPosition(pos, 1);
445 return _storage[pos];
448 size_t rpos()
const {
return _rpos; }
461 size_t wpos()
const {
return _wpos; }
470 size_t bitwpos()
const {
return _wpos * 8 + 8 - _bitpos; }
475 _bitpos = 8 - (newPos % 8);
476 return _wpos * 8 + 8 - _bitpos;
479 template <ByteBufferNumeric T>
484 if (_rpos + skip > _storage.size())
485 OnInvalidPosition(_rpos, skip);
491 template <ByteBufferNumeric T>
495 T r = read<T>(_rpos);
500 template <ByteBufferNumeric T>
503 if (pos +
sizeof(T) > _storage.size())
504 OnInvalidPosition(pos,
sizeof(T));
507 std::memcpy(&val, &_storage[pos],
sizeof(T));
512 template <ByteBufferNumeric T>
513 void read(T* dest,
size_t count)
515 static_assert(std::is_trivially_copyable_v<T>,
"read(T*, size_t) must be used with trivially copyable types");
516 read(
reinterpret_cast<uint8*
>(dest), count *
sizeof(T));
517#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
518 for (
size_t i = 0; i < count; ++i)
525 if (_rpos + len > _storage.size())
526 OnInvalidPosition(_rpos, len);
529 std::memcpy(dest, &_storage[_rpos], len);
533 template <ByteBufferNumeric T,
size_t Size>
534 void read(std::array<T, Size>& arr)
536 read(arr.data(), Size);
543 if (
size_t len = str.length())
544 append(str.c_str(), len);
549 if (
size_t len = str.length())
550 append(str.data(), len);
559 void ReadSkipCString(
bool requireValidUtf8 =
true) { (void)ReadCString(requireValidUtf8); }
561 std::string_view ReadCString(
bool requireValidUtf8 =
true);
563 std::string_view ReadString(
uint32 length,
bool requireValidUtf8 =
true);
568 size_t size()
const {
return _storage.size(); }
569 bool empty()
const {
return _storage.empty(); }
573 _storage.resize(newsize, 0);
575 _wpos = _storage.size();
580 if (ressize > _storage.size())
581 _storage.reserve(ressize);
586 _storage.shrink_to_fit();
589 template <ByteBufferNumeric T>
592#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
593 append(
reinterpret_cast<uint8 const*
>(src), cnt *
sizeof(T));
595 for (
size_t i = 0; i < cnt; ++i)
600 void append(
uint8 const* src,
size_t cnt);
605 append(buffer.
data(), buffer.
size());
608 template <ByteBufferNumeric T, std::
size_t Size>
609 void append(std::array<T, Size>
const& arr)
611 append(arr.data(), Size);
614 void put(
size_t pos,
uint8 const* src,
size_t cnt);
616 void print_storage()
const;
618 void textlike()
const;
620 void hexlike()
const;
622 [[noreturn]]
void OnInvalidPosition(
size_t pos,
size_t valueSize)
const;
631extern template char ByteBuffer::read<char>();
632extern template uint8 ByteBuffer::read<uint8>();
633extern template uint16 ByteBuffer::read<uint16>();
634extern template uint32 ByteBuffer::read<uint32>();
635extern template uint64 ByteBuffer::read<uint64>();
636extern template int8 ByteBuffer::read<int8>();
637extern template int16 ByteBuffer::read<int16>();
638extern template int32 ByteBuffer::read<int32>();
639extern template int64 ByteBuffer::read<int64>();
640extern template float ByteBuffer::read<float>();
641extern template double ByteBuffer::read<double>();
645 &&
requires(
ByteBuffer& data, T& value) { { data >> value } -> std::convertible_to<ByteBuffer&>; };
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
uint32 ReadBits(int32 bits)
ByteBuffer & operator<<(uint32 value)
ByteBuffer & operator>>(int64 &value)
ByteBuffer & operator<<(double value)
ByteBuffer & operator<<(std::string const &str)
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)
void WriteString(std::string const &str)
void WriteString(char const *str, size_t len)
ByteBuffer & operator<<(int64 value)
ByteBuffer & operator<<(std::string_view value)
void resize(size_t newsize)
ByteBuffer & operator>>(int16 &value)
void read_skip(size_t skip)
ByteBuffer & operator>>(uint8 &value)
void append(T const *src, size_t cnt)
std::vector< uint8 > && Release() &&noexcept
ByteBuffer & operator<<(float value)
ByteBuffer & operator>>(int8 &value)
ByteBuffer & operator>>(uint16 &value)
ByteBuffer(std::vector< uint8 > &&buffer) noexcept
uint8 & operator[](size_t const pos)
ByteBuffer & operator>>(bool &)=delete
uint8 const & operator[](size_t const pos) const
void WriteString(std::string_view str)
ByteBuffer & operator=(ByteBuffer const &right)=default
ByteBuffer & operator<<(uint16 value)
void append(ByteBuffer const &buffer)
void ReadSkipCString(bool requireValidUtf8=true)
ByteBuffer & operator<<(bool)=delete
ByteBuffer & operator>>(std::string &value)
ByteBuffer & operator=(ByteBuffer &&right) noexcept
size_t rpos(size_t rpos_)
void read(std::array< T, Size > &arr)
ByteBuffer(size_t size, Resize)
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 append(std::array< T, Size > const &arr)
ByteBuffer(ByteBuffer const &right)=default
uint8 const * data() const
size_t bitwpos(size_t newPos)
size_t wpos(size_t wpos_)
ByteBuffer & operator<<(int8 value)
bool HasUnfinishedBitPack() const
ByteBuffer & operator>>(char &value)
ByteBuffer & operator<<(char 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)