initial
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "Read.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <vector>
|
||||
|
||||
namespace tw::net {
|
||||
|
||||
template<typename T>
|
||||
class BufferReader : public Read<T> {
|
||||
Read<T>* m_readable;
|
||||
|
||||
std::vector<T> m_buffer;
|
||||
|
||||
size_t m_head;
|
||||
size_t m_tail;
|
||||
|
||||
size_t remaining_size() {
|
||||
return m_head - m_tail;
|
||||
}
|
||||
|
||||
public:
|
||||
BufferReader(Read<T>* readable, size_t buffer_size) :
|
||||
m_readable(readable),
|
||||
m_buffer(buffer_size),
|
||||
m_head(0),
|
||||
m_tail(0) {
|
||||
|
||||
}
|
||||
|
||||
size_t read(std::span<T> target) override {
|
||||
size_t read_size = std::min(remaining_size(), target.size());
|
||||
std::copy(m_buffer.begin() + m_tail,
|
||||
m_buffer.begin() + m_tail + read_size,
|
||||
target.begin());
|
||||
|
||||
spdlog::info("Read {} bytes", read_size);
|
||||
|
||||
m_tail += read_size;
|
||||
|
||||
// read next chunk
|
||||
if(m_tail == m_head && read_size < target.size()) {
|
||||
spdlog::info("Reading next chunk");
|
||||
m_head = m_readable->read(std::span<T>(m_buffer.begin(), m_buffer.end()));
|
||||
m_tail = 0;
|
||||
}
|
||||
|
||||
if(target.size() > read_size && m_head > 0) {
|
||||
read_size += read(std::span<T>(target.begin() + read_size, target.end()));
|
||||
}
|
||||
|
||||
return read_size;
|
||||
}
|
||||
|
||||
std::optional<T> peek() {
|
||||
if(remaining_size() > 0) {
|
||||
return m_buffer[m_tail];
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include "Write.hpp"
|
||||
|
||||
namespace tw::net {
|
||||
|
||||
template<typename T>
|
||||
class BufferWriter : public Write<T> {
|
||||
private:
|
||||
Write<T>* m_writeable;
|
||||
std::vector<T> m_buffer;
|
||||
uint32_t m_head;
|
||||
|
||||
public:
|
||||
size_t remaining_size() {
|
||||
return m_buffer.size() - m_head;
|
||||
}
|
||||
|
||||
BufferWriter(Write<T>* writeable, size_t buffer_size) :
|
||||
m_writeable(writeable),
|
||||
m_buffer(buffer_size),
|
||||
m_head(0)
|
||||
{ }
|
||||
|
||||
virtual size_t write(std::span<T> data) override {
|
||||
if(remaining_size() < data.size()) {
|
||||
size_t write_size = flush();
|
||||
write_size += m_writeable->write_into(data);
|
||||
m_head = 0;
|
||||
|
||||
return write_size;
|
||||
}
|
||||
|
||||
std::copy(data.begin(), data.end(), m_buffer.begin() + m_head);
|
||||
size_t write_size = data.size();
|
||||
|
||||
m_head += data.size();
|
||||
|
||||
return write_size;
|
||||
}
|
||||
|
||||
virtual size_t flush() override {
|
||||
m_writeable->write_into(std::span<T>(m_buffer.begin(), m_buffer.begin() + m_head));
|
||||
size_t write_size = m_head;
|
||||
m_head = 0;
|
||||
|
||||
return write_size;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "NetworkError.hpp"
|
||||
#include "tl/expected.hpp"
|
||||
#include <span>
|
||||
|
||||
namespace tw::net {
|
||||
|
||||
template<typename T>
|
||||
class Read {
|
||||
public:
|
||||
virtual ~Read() = default;
|
||||
virtual tl::expected<size_t, NetworkError> read_into(std::span<T> target) = 0;
|
||||
|
||||
tl::expected<size_t, NetworkError> read_exact_into(std::span<std::byte> data) {
|
||||
size_t total_read = 0;
|
||||
while (total_read < data.size()) {
|
||||
auto read = this->read_into(data.subspan(total_read));
|
||||
if(!read.has_value()) {
|
||||
if(read.error().m_type == NetworkErrorType::WOULD_BLOCK) {
|
||||
continue;
|
||||
} else {
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
total_read += read.value();
|
||||
}
|
||||
return total_read;
|
||||
}
|
||||
|
||||
tl::expected<std::vector<std::byte>, NetworkError> read_exact(size_t size) {
|
||||
std::vector<std::byte> buffer(size);
|
||||
auto result = this->read_exact_into(std::span{buffer});
|
||||
|
||||
if(result.has_value()) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return tl::make_unexpected(result.error());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "NetworkError.hpp"
|
||||
#include <tl/expected.hpp>
|
||||
#include <limits>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace tw::net {
|
||||
|
||||
template<typename T>
|
||||
class Write {
|
||||
public:
|
||||
virtual ~Write() = default;
|
||||
|
||||
virtual tl::expected<size_t, NetworkError> write(std::span<T> data) = 0;
|
||||
|
||||
tl::expected<size_t, NetworkError> write(const std::string& data) {
|
||||
return write(std::span<std::byte>((std::byte*)(data.c_str()), data.size()));
|
||||
}
|
||||
|
||||
template<typename TNum,
|
||||
typename std::enable_if_t<std::is_integral<TNum>::value || std::is_enum<TNum>::value, bool> = true>
|
||||
tl::expected<size_t, NetworkError> write(TNum data) {
|
||||
return write(std::as_writable_bytes(std::span{&data, 1}));
|
||||
}
|
||||
|
||||
virtual size_t flush() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user