#pragma once #include #include #include #include #include "../util/memory_stream.h" #include #include namespace EQ { namespace Net { class Packet { public: Packet() : m_stream(std::ios::out | std::ios::binary) { } virtual ~Packet() { } virtual const void *Data() const = 0; virtual void *Data() = 0; virtual size_t Length() const = 0; virtual size_t Length() = 0; virtual bool Clear() = 0; virtual bool Resize(size_t new_size) = 0; virtual void Reserve(size_t new_size) = 0; template T GetSerialize(size_t offset) const { T ret; Util::MemoryStreamReader reader(((char*)Data() + offset), Length()); cereal::BinaryInputArchive input(reader); input(ret); return ret; } template void PutSerialize(size_t offset, const T &value) { m_stream.clear(); cereal::BinaryOutputArchive output(m_stream); output(value); auto str = m_stream.str(); if (Length() < offset + str.length()) { if (!Resize(offset + str.length())) { throw std::out_of_range("Packet::PutSerialize(), could not resize packet and would of written past the end."); } } memcpy((char*)Data() + offset, &str[0], str.length()); } void PutInt8(size_t offset, int8_t value); void PutInt16(size_t offset, int16_t value); void PutInt32(size_t offset, int32_t value); void PutInt64(size_t offset, int64_t value); void PutUInt8(size_t offset, uint8_t value); void PutUInt16(size_t offset, uint16_t value); void PutUInt32(size_t offset, uint32_t value); void PutUInt64(size_t offset, uint64_t value); void PutFloat(size_t offset, float value); void PutDouble(size_t offset, double value); void PutString(size_t offset, const std::string &str); void PutCString(size_t offset, const char *str); void PutPacket(size_t offset, const Packet &p); void PutData(size_t offset, void *data, size_t length); int8_t GetInt8(size_t offset) const; int16_t GetInt16(size_t offset) const; int32_t GetInt32(size_t offset) const; int64_t GetInt64(size_t offset) const; uint8_t GetUInt8(size_t offset) const; uint16_t GetUInt16(size_t offset) const; uint32_t GetUInt32(size_t offset) const; uint64_t GetUInt64(size_t offset) const; float GetFloat(size_t offset) const; double GetDouble(size_t offset) const; std::string GetString(size_t offset, size_t length) const; std::string GetCString(size_t offset) const; std::string ToString() const; std::string ToString(size_t line_length) const; protected: std::stringstream m_stream; }; class StaticPacket : public Packet { public: StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; } virtual ~StaticPacket() { } StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; } StaticPacket& operator=(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; } StaticPacket(StaticPacket &&o) { m_data = o.m_data; m_data_length = o.m_data_length; } virtual const void *Data() const { return m_data; } virtual void *Data() { return m_data; } virtual size_t Length() const { return m_data_length; } virtual size_t Length() { return m_data_length; } virtual bool Clear() { return false; } virtual bool Resize(size_t new_size); virtual void Reserve(size_t new_size) { } protected: void *m_data; size_t m_data_length; size_t m_max_data_length; }; class DynamicPacket : public Packet { public: DynamicPacket() { } virtual ~DynamicPacket() { } DynamicPacket(DynamicPacket &&o) { m_data = std::move(o.m_data); } DynamicPacket(const DynamicPacket &o) { m_data = o.m_data; } DynamicPacket& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; } virtual const void *Data() const { return &m_data[0]; } virtual void *Data() { return &m_data[0]; } virtual size_t Length() const { return m_data.size(); } virtual size_t Length() { return m_data.size(); } virtual bool Clear() { m_data.clear(); return true; } virtual bool Resize(size_t new_size) { m_data.resize(new_size, 0); return true; } virtual void Reserve(size_t new_size) { m_data.reserve(new_size); } protected: std::vector m_data; }; } }