rcpp_framework/libs/brynet/base/Packet.hpp

433 lines
9.2 KiB
C++
Raw Normal View History

2020-11-24 15:41:18 +01:00
#pragma once
2021-04-30 16:10:14 +02:00
#include <brynet/base/NonCopyable.hpp>
#include <brynet/base/endian/Endian.hpp>
2020-11-24 15:41:18 +01:00
#include <cstdint>
#include <cstring>
2021-04-30 16:10:14 +02:00
#include <stdexcept>
2020-11-24 15:41:18 +01:00
#include <string>
namespace brynet { namespace base {
2021-04-30 16:10:14 +02:00
class BasePacketWriter : public NonCopyable
{
public:
BasePacketWriter(char* buffer,
size_t len,
bool useBigEndian = false,
bool isAutoMalloc = false)
: mIsAutoMalloc(isAutoMalloc),
mBigEndian(useBigEndian)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
mMaxLen = len;
mPos = 0;
mBuffer = buffer;
mMallocBuffer = nullptr;
}
virtual ~BasePacketWriter()
{
if (mMallocBuffer != nullptr)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
free(mMallocBuffer);
2020-11-24 15:41:18 +01:00
mMallocBuffer = nullptr;
}
2021-04-30 16:10:14 +02:00
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void init()
{
mPos = 0;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
size_t getMaxLen() const
{
return mMaxLen;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
size_t getPos() const
{
return mPos;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const char* getData() const
{
return mBuffer;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool isAutoGrow() const
{
return mIsAutoMalloc;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool writeBool(bool value)
{
static_assert(sizeof(bool) == sizeof(int8_t), "");
return writeBuffer((char*) &value, sizeof(value));
}
bool writeINT8(int8_t value)
{
return writeBuffer((char*) &value, sizeof(value));
}
bool writeUINT8(uint8_t value)
{
return writeBuffer((char*) &value, sizeof(value));
}
bool writeINT16(int16_t value)
{
value = endian::hostToNetwork16(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
bool writeUINT16(uint16_t value)
{
value = endian::hostToNetwork16(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
bool writeINT32(int32_t value)
{
value = endian::hostToNetwork32(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
bool writeUINT32(uint32_t value)
{
value = endian::hostToNetwork32(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
bool writeINT64(int64_t value)
{
value = endian::hostToNetwork64(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
bool writeUINT64(uint64_t value)
{
value = endian::hostToNetwork64(value, mBigEndian);
return writeBuffer((char*) &value, sizeof(value));
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool writeBinary(const std::string& binary)
{
return writeBuffer(binary.c_str(), binary.size());
}
bool writeBinary(const char* binary, size_t binaryLen)
{
return writeBuffer(binary, binaryLen);
}
bool writeBuffer(const char* buffer, size_t len)
{
growBuffer(len);
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
if (mMaxLen < (mPos + len))
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return false;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
memcpy(mBuffer + mPos, buffer, len);
mPos += len;
return true;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
BasePacketWriter& operator<<(const bool& v)
{
writeBool(v);
return *this;
}
BasePacketWriter& operator<<(const uint8_t& v)
{
writeUINT8(v);
return *this;
}
BasePacketWriter& operator<<(const int8_t& v)
{
writeINT8(v);
return *this;
}
BasePacketWriter& operator<<(const int16_t& v)
{
writeINT16(v);
return *this;
}
BasePacketWriter& operator<<(const uint16_t& v)
{
writeUINT16(v);
return *this;
}
BasePacketWriter& operator<<(const int32_t& v)
{
writeINT32(v);
return *this;
}
BasePacketWriter& operator<<(const uint32_t& v)
{
writeUINT32(v);
return *this;
}
BasePacketWriter& operator<<(const int64_t& v)
{
writeINT64(v);
return *this;
}
BasePacketWriter& operator<<(const uint64_t& v)
{
writeUINT64(v);
return *this;
}
BasePacketWriter& operator<<(const char* const& v)
{
writeBinary(v);
return *this;
}
BasePacketWriter& operator<<(const std::string& v)
{
writeBinary(v);
return *this;
}
private:
// 为了避免直接<<导致没有指定字节序导致隐藏BUG,因为此函数设置为私有
template<typename T>
BasePacketWriter& operator<<(const T& v)
{
static_assert(!std::is_pointer<T>::value, "T must is't a pointer");
static_assert(std::is_class<T>::value, "T must a class or struct type");
static_assert(std::is_pod<T>::value, "T must a pod type");
writeBuffer((const char*) &v, sizeof(v));
return *this;
}
template<typename Arg1, typename... Args>
void writev(const Arg1& arg1, const Args&... args)
{
this->operator<<(arg1);
writev(args...);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void writev()
{
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
protected:
void growBuffer(size_t len)
{
if (!mIsAutoMalloc || (mPos + len) <= mMaxLen)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
auto newBuffer = (char*) malloc(mMaxLen + len);
if (newBuffer == nullptr)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
return;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
memcpy(newBuffer, mBuffer, mPos);
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
if (mMallocBuffer != nullptr)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
free(mMallocBuffer);
mMallocBuffer = nullptr;
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
mMaxLen += len;
mMallocBuffer = newBuffer;
mBuffer = newBuffer;
}
protected:
const bool mIsAutoMalloc;
bool mBigEndian;
size_t mPos;
size_t mMaxLen;
char* mBuffer;
char* mMallocBuffer;
};
class BasePacketReader
{
public:
BasePacketReader(const char* buffer,
size_t len,
bool useBigEndian = false)
: mBigEndian(useBigEndian),
mSize(len)
{
mPos = 0;
mSavedPos = 0;
mBuffer = buffer;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
virtual ~BasePacketReader() = default;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void useBigEndian()
{
mBigEndian = true;
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
void useLittleEndian()
{
mBigEndian = false;
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
void savePos()
{
mSavedPos = mPos;
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
size_t savedPos() const
{
return mSavedPos;
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
size_t getLeft() const
{
if (mPos > mSize)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
throw std::out_of_range("current pos is greater than max len");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
return mSize - mPos;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool enough(size_t len) const
{
if (mPos > mSize)
2021-01-29 17:26:17 +01:00
{
2021-04-30 16:10:14 +02:00
return false;
2021-01-29 17:26:17 +01:00
}
2021-04-30 16:10:14 +02:00
return (mSize - mPos) >= len;
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
const char* begin() const
{
return mBuffer;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
const char* currentBuffer() const
{
return mBuffer + mPos;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void consumeAll()
{
mPos = mSize;
savePos();
}
2021-01-29 17:26:17 +01:00
2021-04-30 16:10:14 +02:00
size_t currentPos() const
{
return mPos;
}
size_t size() const
{
return mSize;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void addPos(size_t diff)
{
const auto tmpPos = mPos + diff;
if (tmpPos > mSize)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
throw std::out_of_range("diff is to big");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
mPos = tmpPos;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
bool readBool()
{
static_assert(sizeof(bool) == sizeof(int8_t), "");
bool value = false;
read(value);
return value;
}
int8_t readINT8()
{
int8_t value = 0;
read(value);
return value;
}
uint8_t readUINT8()
{
uint8_t value = 0;
read(value);
return value;
}
int16_t readINT16()
{
int16_t value = 0;
read(value);
return endian::networkToHost16(value, mBigEndian);
}
uint16_t readUINT16()
{
uint16_t value = 0;
read(value);
return endian::networkToHost16(value, mBigEndian);
}
int32_t readINT32()
{
int32_t value = 0;
read(value);
return endian::networkToHost32(value, mBigEndian);
}
uint32_t readUINT32()
{
uint32_t value = 0;
read(value);
return endian::networkToHost32(value, mBigEndian);
}
int64_t readINT64()
{
int64_t value = 0;
read(value);
return endian::networkToHost64(value, mBigEndian);
}
uint64_t readUINT64()
{
uint64_t value = 0;
read(value);
return endian::networkToHost64(value, mBigEndian);
}
private:
// 为了避免直接read(uintXXX)导致没有指定字节序造成隐患BUG,因为此函数设置为私有
template<typename T>
void read(T& value)
{
static_assert(std::is_same<T, typename std::remove_pointer<T>::type>::value,
"T must a normal type");
static_assert(std::is_pod<T>::value,
"T must a pod type");
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
if ((mPos + sizeof(value)) > mSize)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
throw std::out_of_range("T size is to big");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
value = *(T*) (mBuffer + mPos);
mPos += sizeof(value);
}
protected:
bool mBigEndian;
const size_t mSize;
const char* mBuffer;
size_t mPos;
size_t mSavedPos;
};
template<size_t SIZE>
class AutoMallocPacket : public BasePacketWriter
{
public:
explicit AutoMallocPacket(bool useBigEndian = false,
bool isAutoMalloc = false)
: BasePacketWriter(mData, SIZE, useBigEndian, isAutoMalloc)
{}
private:
char mData[SIZE];
};
using BigPacket = AutoMallocPacket<32 * 1024>;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
}}// namespace brynet::base