18#ifndef TRINITYCORE_BYTE_BUFFER_H
19#define TRINITYCORE_BYTE_BUFFER_H
37 char const*
what() const noexcept
override {
return msg_.c_str(); }
57 || std::same_as<T, int16> || std::same_as<T, uint16>
58 || std::same_as<T, int32> || std::same_as<T, uint32>
59 || std::same_as<T, int64> || std::same_as<T, uint64>
60 || std::same_as<T, float> || std::same_as<T, double>
61 || std::same_as<T, char> || std::is_enum_v<T>;
66 constexpr static size_t DEFAULT_SIZE = 0x1000;
67 constexpr static uint8 InitialBitPos = 8;
76 explicit ByteBuffer(
size_t size,
Reserve) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
78 _storage.reserve(size);
81 explicit ByteBuffer(
size_t size,
Resize) : _rpos(0), _wpos(size), _bitpos(InitialBitPos), _curbitval(0)
83 _storage.resize(size);
89 _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(std::move(buf).
Release()) { }
91 explicit ByteBuffer(std::vector<uint8>&& buffer) noexcept : _rpos(0), _wpos(buffer.size()),
92 _bitpos(InitialBitPos), _curbitval(0), _storage(std::move(buffer)) { }
94 std::vector<uint8>&&
Release() &&
noexcept
98 _bitpos = InitialBitPos;
100 return std::move(_storage);
111 _bitpos = right._bitpos;
112 _curbitval = right._curbitval;
113 _storage = std::move(right).Release();
125 _bitpos = InitialBitPos;
130 template <ByteBufferNumeric T>
134 append(
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
149 append(&_curbitval,
sizeof(
uint8));
163 _curbitval |= (1 << (_bitpos));
168 append(&_curbitval,
sizeof(_curbitval));
179 read(&_curbitval, 1);
183 return ((_curbitval >> (8 - ++_bitpos)) & 1) != 0;
189 value &= (
UI64LIT(1) << bits) - 1;
191 if (bits >
int32(_bitpos))
194 _curbitval |= value >> (bits - _bitpos);
197 append(&_curbitval,
sizeof(_curbitval));
203 append<uint8>(value >> bits);
208 _curbitval = (value & ((
UI64LIT(1) << bits) - 1)) << _bitpos;
214 _curbitval |= value << _bitpos;
219 append(&_curbitval,
sizeof(_curbitval));
228 if (bits > 8 -
int32(_bitpos))
231 int32 bitsInBuffer = 8 - _bitpos;
232 value = (_curbitval & ((
UI64LIT(1) << bitsInBuffer) - 1)) << (bits - bitsInBuffer);
233 bits -= bitsInBuffer;
239 value |= read<uint8>() << bits;
245 read(&_curbitval, 1);
246 value |= (_curbitval >> (8 - bits)) & ((
UI64LIT(1) << bits) - 1);
253 value = (_curbitval >> (8 - _bitpos - bits)) & ((
UI64LIT(1) << bits) - 1);
260 template <ByteBufferNumeric T>
261 void put(std::size_t pos, T value)
264 put(pos,
reinterpret_cast<uint8 const*
>(&value),
sizeof(value));
279 void PutBits(std::size_t pos, std::size_t value,
uint32 bitCount);
291 append<uint8>(value);
297 append<uint16>(value);
303 append<uint32>(value);
309 append<uint64>(value);
322 append<int16>(value);
328 append<int32>(value);
334 append<int64>(value);
341 append<float>(value);
347 append<double>(value);
353 if (
size_t len = value.length())
354 append(
reinterpret_cast<uint8 const*
>(value.data()), len);
355 append(
static_cast<uint8>(0));
366 return operator<<(std::string_view(str ? str :
""));
431 value = ReadCString(
true);
437 if (pos >= _storage.size())
438 OnInvalidPosition(pos, 1);
439 return _storage[pos];
444 if (pos >= _storage.size())
445 OnInvalidPosition(pos, 1);
446 return _storage[pos];
449 size_t rpos()
const {
return _rpos; }
462 size_t wpos()
const {
return _wpos; }
471 size_t bitwpos()
const {
return _wpos * 8 + 8 - _bitpos; }
476 _bitpos = 8 - (newPos % 8);
477 return _wpos * 8 + 8 - _bitpos;
480 template <ByteBufferNumeric T>
485 if (_rpos + skip > _storage.size())
486 OnInvalidPosition(_rpos, skip);
492 template <ByteBufferNumeric T>
496 T r = read<T>(_rpos);
501 template <ByteBufferNumeric T>
504 if (pos +
sizeof(T) > _storage.size())
505 OnInvalidPosition(pos,
sizeof(T));
508 std::memcpy(&val, &_storage[pos],
sizeof(T));
513 template <ByteBufferNumeric T>
514 void read(T* dest,
size_t count)
516 static_assert(std::is_trivially_copyable_v<T>,
"read(T*, size_t) must be used with trivially copyable types");
517 read(
reinterpret_cast<uint8*
>(dest), count *
sizeof(T));
518#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
519 for (
size_t i = 0; i < count; ++i)
526 if (_rpos + len > _storage.size())
527 OnInvalidPosition(_rpos, len);
530 std::memcpy(dest, &_storage[_rpos], len);
534 template <ByteBufferNumeric T,
size_t Size>
535 void read(std::array<T, Size>& arr)
537 read(arr.data(), Size);
544 if (
size_t len = str.length())
545 append(str.c_str(), len);
550 if (
size_t len = str.length())
551 append(str.data(), len);
560 void ReadSkipCString(
bool requireValidUtf8 =
true) { (void)ReadCString(requireValidUtf8); }
562 std::string_view ReadCString(
bool requireValidUtf8 =
true);
564 std::string_view ReadString(
uint32 length,
bool requireValidUtf8 =
true);
568 if (_rpos + length > _storage.size())
569 OnInvalidPosition(_rpos, length);
572 uint8* data = _storage.data() + _rpos;
574 return { data, length };
580 size_t size()
const {
return _storage.size(); }
581 bool empty()
const {
return _storage.empty(); }
585 _storage.resize(newsize, 0);
587 _wpos = _storage.size();
592 if (ressize > _storage.size())
593 _storage.reserve(ressize);
598 _storage.shrink_to_fit();
601 template <ByteBufferNumeric T>
604#if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN
605 append(
reinterpret_cast<uint8 const*
>(src), cnt *
sizeof(T));
607 for (
size_t i = 0; i < cnt; ++i)
612 void append(
uint8 const* src,
size_t cnt);
617 append(buffer.
data(), buffer.
size());
620 template <ByteBufferNumeric T, std::
size_t Size>
621 void append(std::array<T, Size>
const& arr)
623 append(arr.data(), Size);
626 void put(
size_t pos,
uint8 const* src,
size_t cnt);
628 void print_storage()
const;
630 void textlike()
const;
632 void hexlike()
const;
634 [[noreturn]]
void OnInvalidPosition(
size_t pos,
size_t valueSize)
const;
643extern template char ByteBuffer::read<char>();
644extern template uint8 ByteBuffer::read<uint8>();
645extern template uint16 ByteBuffer::read<uint16>();
646extern template uint32 ByteBuffer::read<uint32>();
647extern template uint64 ByteBuffer::read<uint64>();
648extern template int8 ByteBuffer::read<int8>();
649extern template int16 ByteBuffer::read<int16>();
650extern template int32 ByteBuffer::read<int32>();
651extern template int64 ByteBuffer::read<int64>();
652extern template float ByteBuffer::read<float>();
653extern template double ByteBuffer::read<double>();
657 &&
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)
std::span< uint8 > ReadBytes(size_t length)
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)