141 lines
3.7 KiB
C++
141 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include "data.hpp"
|
|
#include "../data/mem.hpp"
|
|
|
|
namespace net {
|
|
|
|
//TODO: preallocate static data pool
|
|
|
|
/// Helper to write allocated packets
|
|
class PacketWriter final {
|
|
public:
|
|
PacketWriter(size_t size): buffer((uint8_t*)malloc(size), size) { }
|
|
PacketWriter(uint8_t type, size_t data_size): PacketWriter(sizeof(type) + data_size) {
|
|
write(type);
|
|
}
|
|
PacketWriter(net::client_packet_type type, size_t data_size): PacketWriter((uint8_t)type, data_size) { }
|
|
PacketWriter(net::server_packet_type type, size_t data_size): PacketWriter((uint8_t)type, data_size) { }
|
|
~PacketWriter() {
|
|
if (buffer.ptr != nullptr)
|
|
free(buffer.ptr);
|
|
}
|
|
|
|
void write(const void* data, size_t len) {
|
|
buffer.write((uint8_t*)data, len);
|
|
}
|
|
template<typename D>
|
|
void write(const D& d) {
|
|
write(&d, sizeof(d));
|
|
}
|
|
|
|
struct varying_part {
|
|
varying_part(data::in_view &buffer): buffer(buffer), visible_size(0) { }
|
|
~varying_part() {
|
|
buffer.siz = buffer.cur + visible_size;
|
|
buffer.cur = buffer.siz;
|
|
}
|
|
|
|
data::in_view &buffer;
|
|
size_t visible_size;
|
|
|
|
constexpr size_t size() const { return visible_size; }
|
|
void* data() { return buffer.writeTo(0); }
|
|
void reserve(size_t target) {
|
|
if (target >= buffer.siz - buffer.cur) {
|
|
auto old = buffer.ptr;
|
|
buffer.ptr = (uint8_t*)malloc(target);
|
|
memcpy(buffer.ptr, old, buffer.siz);
|
|
free(old);
|
|
buffer.siz = target;
|
|
}
|
|
}
|
|
void resize(size_t target) {
|
|
reserve(target);
|
|
visible_size = target;
|
|
}
|
|
};
|
|
/// Only from resize, write, resize down
|
|
varying_part varying() {
|
|
return varying_part(buffer);
|
|
}
|
|
|
|
bool isFull() const {
|
|
return buffer.isDone();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
data::out_buffer finish() {
|
|
assert(isFull());
|
|
data::out_buffer cpy(buffer.ptr, buffer.siz);
|
|
buffer.ptr = nullptr;
|
|
buffer.siz = 0;
|
|
return cpy;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
static data::out_buffer Of(net::client_packet_type type, const void* data, size_t size) {
|
|
auto packet = PacketWriter(type, size);
|
|
packet.write(data, size);
|
|
return packet.finish();
|
|
}
|
|
[[nodiscard]]
|
|
static data::out_buffer Of(net::server_packet_type type, const void* data, size_t size) {
|
|
auto packet = PacketWriter(type, size);
|
|
packet.write(data, size);
|
|
return packet.finish();
|
|
}
|
|
template<typename D>
|
|
[[nodiscard]]
|
|
static data::out_buffer Of(net::client_packet_type type, const D& data) {
|
|
return Of(type, &data, sizeof(data));
|
|
}
|
|
template<typename D>
|
|
[[nodiscard]]
|
|
static data::out_buffer Of(net::server_packet_type type, const D& data) {
|
|
return Of(type, &data, sizeof(data));
|
|
}
|
|
|
|
private:
|
|
data::in_view buffer;
|
|
};
|
|
|
|
/// Helper to read out_view
|
|
class PacketReader final {
|
|
public:
|
|
PacketReader(const data::out_view& buf): buffer(buf) { }
|
|
|
|
template<typename D>
|
|
const D* read() {
|
|
return buffer.cur + sizeof(D) <= buffer.size() ?
|
|
(const D*)buffer.readFrom(sizeof(D)) : nullptr;
|
|
}
|
|
template<typename D>
|
|
bool read(D& out) {
|
|
const auto ptr = read<D>();
|
|
if (ptr == nullptr)
|
|
return false;
|
|
|
|
out = *ptr;
|
|
return true;
|
|
}
|
|
|
|
bool skip(size_t size) {
|
|
buffer.readFrom(size);
|
|
return !isFull();
|
|
}
|
|
|
|
data::out_view readAll() {
|
|
const size_t remain = buffer.size() - buffer.cur;
|
|
return data::out_view(buffer.readFrom(remain), remain);
|
|
}
|
|
|
|
bool isFull() const {
|
|
return buffer.isDone();
|
|
}
|
|
|
|
private:
|
|
data::out_view buffer;
|
|
};
|
|
|
|
} |