Created
July 18, 2018 03:17
-
-
Save Langerz82/9ca298d9b8a7dacd7535b045527fc0ff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> | |
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> | |
* | |
* This program is free software; you can redistribute it and/or modify it | |
* under the terms of the GNU General Public License as published by the | |
* Free Software Foundation; either version 2 of the License, or (at your | |
* option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, but WITHOUT | |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
* more details. | |
* | |
* You should have received a copy of the GNU General Public License along | |
* with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#ifndef _BYTEBUFFERNEW_H | |
#define _BYTEBUFFERNEW_H | |
#include "Define.h" | |
#include "Errors.h" | |
#include "ByteConverter.h" | |
#include "Log.h" | |
#include <string> | |
#include <vector> | |
#include <cstring> | |
class MessageBuffer; | |
// Root of ByteBufferNew exception hierarchy | |
class TC_SHARED_API ByteBufferNewException : public std::exception | |
{ | |
public: | |
~ByteBufferNewException() throw() { } | |
char const* what() const throw() override { return msg_.c_str(); } | |
protected: | |
std::string & message() throw() { return msg_; } | |
private: | |
std::string msg_; | |
}; | |
class TC_SHARED_API ByteBufferNewPositionException : public ByteBufferNewException | |
{ | |
public: | |
ByteBufferNewPositionException(bool add, size_t pos, size_t size, size_t valueSize); | |
~ByteBufferNewPositionException() throw() { } | |
}; | |
class TC_SHARED_API ByteBufferNewSourceException : public ByteBufferNewException | |
{ | |
public: | |
ByteBufferNewSourceException(size_t pos, size_t size, size_t valueSize); | |
~ByteBufferNewSourceException() throw() { } | |
}; | |
class TC_SHARED_API ByteBufferNew | |
{ | |
public: | |
const static size_t DEFAULT_SIZE = 64; | |
// constructor | |
ByteBufferNew() : _rpos(0), _wpos(0), _storage(nullptr) | |
{ | |
maxSize = DEFAULT_SIZE; | |
_storage = new uint8[DEFAULT_SIZE]; | |
} | |
ByteBufferNew(size_t reserve) : _rpos(0), _wpos(0), _storage(nullptr) | |
{ | |
if (reserve == 0) | |
{ | |
maxSize = DEFAULT_SIZE; | |
_storage = new uint8[DEFAULT_SIZE](); | |
return; | |
} | |
maxSize = reserve; | |
_storage = new uint8[reserve]; | |
} | |
ByteBufferNew(ByteBufferNew&& buf) : _rpos(buf._rpos), _wpos(buf._wpos)//, _storage(buf._storage) | |
{ | |
buf._rpos = 0; | |
buf._wpos = 0; | |
maxSize = buf.maxSize; | |
if (maxSize > 0) | |
{ | |
_storage = new uint8[maxSize](); | |
if (_wpos > 0) | |
std::memcpy(_storage, buf._storage, _wpos); | |
delete[] buf._storage; | |
buf._storage = NULL; | |
buf.maxSize = 0; | |
} | |
} | |
ByteBufferNew(ByteBufferNew const& right) : _rpos(right._rpos), _wpos(right._wpos), maxSize(right.maxSize)//, _storage(right._storage) | |
{ | |
if (maxSize > 0) | |
{ | |
_storage = new uint8[maxSize](); | |
if (_wpos > 0) | |
std::memcpy(_storage, right._storage, _wpos); | |
} | |
} | |
ByteBufferNew(MessageBuffer&& buffer); | |
ByteBufferNew& operator=(ByteBufferNew const& right) | |
{ | |
if (this != &right) | |
{ | |
_rpos = right._rpos; | |
_wpos = right._wpos; | |
maxSize = right.maxSize; | |
if (maxSize > 0) | |
{ | |
_storage = new uint8[right.maxSize](); | |
if (_wpos > 0) | |
std::memcpy(_storage, right._storage, _wpos); | |
} | |
} | |
return *this; | |
} | |
ByteBufferNew& operator=(ByteBufferNew&& right) | |
{ | |
if (this != &right) | |
{ | |
_rpos = right._rpos; | |
right._rpos = 0; | |
_wpos = right._wpos; | |
right._wpos = 0; | |
if (maxSize > 0) | |
{ | |
delete[] _storage; | |
} | |
maxSize = right.maxSize; | |
if (maxSize > 0) | |
{ | |
_storage = new uint8[maxSize]; | |
if (_wpos > 0) | |
std::memcpy(_storage, right._storage, _wpos); | |
} | |
} | |
return *this; | |
} | |
void destroy() { | |
if (_storage != nullptr) | |
{ | |
if (maxSize > 0) | |
delete[] _storage; | |
} | |
} | |
~ByteBufferNew() | |
{ | |
destroy(); | |
} | |
void clear() | |
{ | |
if (_storage != nullptr) | |
{ | |
if (maxSize > 0) | |
delete[] _storage; | |
} | |
maxSize = DEFAULT_SIZE; | |
_storage = new uint8[DEFAULT_SIZE](); | |
_rpos = _wpos = 0; | |
} | |
template <typename T> void append(T value) | |
{ | |
static_assert(std::is_fundamental<T>::value, "append(compound)"); | |
EndianConvert(value); | |
append((uint8 *)&value, sizeof(value)); | |
} | |
template <typename T> | |
void put(std::size_t pos, T value) | |
{ | |
static_assert(std::is_fundamental<T>::value, "append(compound)"); | |
EndianConvert(value); | |
put(pos, (uint8 *)&value, sizeof(value)); | |
} | |
size_t size() const | |
{ | |
return _wpos; | |
} | |
ByteBufferNew &operator<<(uint8 value) | |
{ | |
append<uint8>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(uint16 value) | |
{ | |
append<uint16>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(uint32 value) | |
{ | |
append<uint32>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(uint64 value) | |
{ | |
append<uint64>(value); | |
return *this; | |
} | |
// signed as in 2e complement | |
ByteBufferNew &operator<<(int8 value) | |
{ | |
append<int8>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(int16 value) | |
{ | |
append<int16>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(int32 value) | |
{ | |
append<int32>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(int64 value) | |
{ | |
append<int64>(value); | |
return *this; | |
} | |
// floating points | |
ByteBufferNew &operator<<(float value) | |
{ | |
append<float>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(double value) | |
{ | |
append<double>(value); | |
return *this; | |
} | |
ByteBufferNew &operator<<(const std::string &value) | |
{ | |
if (size_t len = value.length()) | |
append((uint8 const*)value.c_str(), len); | |
append((uint8)0); | |
return *this; | |
} | |
ByteBufferNew &operator<<(const char *str) | |
{ | |
if (size_t len = (str ? strlen(str) : 0)) | |
append((uint8 const*)str, len); | |
append((uint8)0); | |
return *this; | |
} | |
ByteBufferNew &operator>>(bool &value) | |
{ | |
value = read<char>() > 0 ? true : false; | |
return *this; | |
} | |
ByteBufferNew &operator>>(uint8 &value) | |
{ | |
value = read<uint8>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(uint16 &value) | |
{ | |
value = read<uint16>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(uint32 &value) | |
{ | |
value = read<uint32>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(uint64 &value) | |
{ | |
value = read<uint64>(); | |
return *this; | |
} | |
//signed as in 2e complement | |
ByteBufferNew &operator>>(int8 &value) | |
{ | |
value = read<int8>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(int16 &value) | |
{ | |
value = read<int16>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(int32 &value) | |
{ | |
value = read<int32>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(int64 &value) | |
{ | |
value = read<int64>(); | |
return *this; | |
} | |
ByteBufferNew &operator>>(float &value); | |
ByteBufferNew &operator>>(double &value); | |
ByteBufferNew &operator>>(std::string& value) | |
{ | |
value.clear(); | |
while (rpos() < size()) // prevent crash at wrong string format in packet | |
{ | |
char c = read<char>(); | |
if (c == 0) | |
break; | |
value += c; | |
} | |
return *this; | |
} | |
uint8& operator[](size_t const pos) | |
{ | |
if (pos >= size()) | |
throw ByteBufferNewPositionException(false, pos, 1, size()); | |
return _storage[pos]; | |
} | |
uint8 const& operator[](size_t const pos) const | |
{ | |
if (pos >= size()) | |
throw ByteBufferNewPositionException(false, pos, 1, size()); | |
return _storage[pos]; | |
} | |
size_t rpos() const { return _rpos; } | |
size_t rpos(size_t rpos_) | |
{ | |
_rpos = rpos_; | |
return _rpos; | |
} | |
void rfinish() | |
{ | |
_rpos = wpos(); | |
} | |
size_t wpos() const { return _wpos; } | |
size_t wpos(size_t wpos_) | |
{ | |
_wpos = wpos_; | |
return _wpos; | |
} | |
template<typename T> | |
void read_skip() { read_skip(sizeof(T)); } | |
void read_skip(size_t skip) | |
{ | |
if (_rpos + skip > size()) | |
throw ByteBufferNewPositionException(false, _rpos, skip, size()); | |
_rpos += skip; | |
} | |
template <typename T> T read() | |
{ | |
T r = read<T>(_rpos); | |
_rpos += sizeof(T); | |
return r; | |
} | |
template <typename T> T read(size_t pos) const | |
{ | |
if (pos + sizeof(T) > maxSize) | |
throw ByteBufferNewPositionException(false, pos, sizeof(T), size()); | |
T val = *((T const*)&_storage[pos]); | |
EndianConvert(val); | |
return val; | |
} | |
void read(uint8 *dest, size_t len) | |
{ | |
if (_rpos + len > size()) | |
throw ByteBufferNewPositionException(false, _rpos, len, size()); | |
std::memcpy(dest, &_storage[_rpos], len); | |
_rpos += len; | |
} | |
void readPackGUID(uint64& guid) | |
{ | |
if (rpos() + 1 > size()) | |
throw ByteBufferNewPositionException(false, _rpos, 1, size()); | |
guid = 0; | |
uint8 guidmark = 0; | |
(*this) >> guidmark; | |
for (int i = 0; i < 8; ++i) | |
{ | |
if (guidmark & (uint8(1) << i)) | |
{ | |
if (rpos() + 1 > size()) | |
throw ByteBufferNewPositionException(false, _rpos, 1, size()); | |
uint8 bit; | |
(*this) >> bit; | |
guid |= (uint64(bit) << (i * 8)); | |
} | |
} | |
} | |
uint32 ReadPackedTime(); | |
ByteBufferNew& ReadPackedTime(uint32& time) | |
{ | |
time = ReadPackedTime(); | |
return *this; | |
} | |
uint8* contents() | |
{ | |
if (maxSize == 0) | |
throw ByteBufferNewException(); | |
return _storage; | |
} | |
uint8 const* contents() const | |
{ | |
if (maxSize == 0) | |
throw ByteBufferNewException(); | |
return _storage; | |
} | |
bool empty() const { return size() == 0; } | |
void reserve(size_t newsize) | |
{ | |
resizeMem(newsize); | |
} | |
void resizeMem(size_t newsize) | |
{ | |
//ASSERT(newsize > maxSize, "Tried to resize smaller than original size."); | |
if (newsize < maxSize) | |
return; | |
uint8* _storage2 = new uint8[newsize](); | |
if (_storage && maxSize > 0) | |
{ | |
if (_wpos > 0) | |
std::memcpy(&_storage2[0], &_storage[0], _wpos); | |
delete[] _storage; | |
} | |
_storage = _storage2; | |
_rpos = 0; | |
maxSize = newsize; | |
} | |
void resize(size_t newsize) | |
{ | |
resizeMem(newsize); | |
_wpos = newsize; | |
} | |
void append(const char *src, size_t cnt) | |
{ | |
return append((const uint8 *)src, cnt); | |
} | |
template<class T> void append(const T *src, size_t cnt) | |
{ | |
return append((const uint8 *)src, cnt * sizeof(T)); | |
} | |
void append(uint8 const* src, size_t cnt); | |
void append(ByteBufferNew const& buffer) | |
{ | |
if (buffer.wpos()) | |
append(buffer.contents(), buffer.wpos()); | |
} | |
// can be used in SMSG_MONSTER_MOVE opcode | |
void appendPackXYZ(float x, float y, float z) | |
{ | |
uint32 packed = 0; | |
packed |= ((int)(x / 0.25f) & 0x7FF); | |
packed |= ((int)(y / 0.25f) & 0x7FF) << 11; | |
packed |= ((int)(z / 0.25f) & 0x3FF) << 22; | |
*this << packed; | |
} | |
void appendPackGUID(uint64 guid) | |
{ | |
uint8 packGUID[8+1]; | |
packGUID[0] = 0; | |
size_t size = 1; | |
for (uint8 i = 0;guid != 0;++i) | |
{ | |
if (guid & 0xFF) | |
{ | |
packGUID[0] |= uint8(1 << i); | |
packGUID[size] = uint8(guid & 0xFF); | |
++size; | |
} | |
guid >>= 8; | |
} | |
append(packGUID, size); | |
} | |
void AppendPackedTime(time_t time); | |
void put(size_t pos, const uint8 *src, size_t cnt); | |
void print_storage() const; | |
void textlike() const; | |
void hexlike() const; | |
protected: | |
size_t _rpos, _wpos; | |
size_t maxSize; | |
uint8* _storage; | |
}; | |
/// @todo Make a ByteBufferNew.cpp and move all this inlining to it. | |
template<> inline std::string ByteBufferNew::read<std::string>() | |
{ | |
std::string tmp; | |
*this >> tmp; | |
return tmp; | |
} | |
template<> | |
inline void ByteBufferNew::read_skip<char*>() | |
{ | |
std::string temp; | |
*this >> temp; | |
} | |
template<> | |
inline void ByteBufferNew::read_skip<char const*>() | |
{ | |
read_skip<char*>(); | |
} | |
template<> | |
inline void ByteBufferNew::read_skip<std::string>() | |
{ | |
read_skip<char*>(); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment