#ifndef SOPHIAR2_VERSATILE_BUFFER2_HPP #define SOPHIAR2_VERSATILE_BUFFER2_HPP #include "utility/bit_operations.hpp" #include "utility/dynamic_pool.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sophiar { template struct static_memory : private boost::noncopyable { char *data() { return buf.data(); } const char *data() const { return buf.data(); } constexpr size_t size() { return Length; } static auto new_instance() { using this_type = static_memory; return std::make_unique(); } private: std::array buf; }; struct dynamic_memory : private boost::noncopyable { static constexpr size_t DYNAMIC_MEMORY_DEFAULT_SIZE = 32; using pointer = std::unique_ptr; ~dynamic_memory() { DEALLOCATE_DYNAMIC_MEMORY((void *) buf, capacity_length); } char *data() { return buf; } const char *data() const { return buf; } size_t size() const { return used_length; } void resize(size_t req_size) { if (req_size > capacity_length) [[unlikely]] { auto ext_buf = (char *) ALLOCATE_DYNAMIC_MEMORY(req_size); memcpy(ext_buf, buf, used_length); DEALLOCATE_DYNAMIC_MEMORY((void *) buf, capacity_length); buf = ext_buf; capacity_length = ACTUAL_DYNAMIC_MEMORY_SIZE(req_size); } used_length = req_size; } void increase_size(ptrdiff_t extra_size) { assert(extra_size >= 0 || size() > -extra_size); resize(size() + extra_size); } static auto new_instance(size_t req_size = DYNAMIC_MEMORY_DEFAULT_SIZE) { return pointer{new dynamic_memory{req_size}}; } private: char *buf; size_t used_length; size_t capacity_length; explicit dynamic_memory(size_t req_size) { buf = (char *) ALLOCATE_DYNAMIC_MEMORY(req_size); used_length = req_size; capacity_length = ACTUAL_DYNAMIC_MEMORY_SIZE(req_size); } }; struct extern_memory { extern_memory(char *extern_buf, size_t buf_length) : buf(extern_buf), length(buf_length) {} extern_memory(const extern_memory &) = default; char *data() { return buf; } const char *data() const { return buf; } size_t size() const { return length; } private: char *buf; size_t length; }; struct const_extern_memory { const_extern_memory(const char *extern_buf, size_t buf_length) : buf(extern_buf), length(buf_length) {} explicit const_extern_memory(const extern_memory &other) : buf(other.data()), length(other.size()) {} const_extern_memory(const const_extern_memory &) = default; const char *data() const { return buf; } size_t size() const { return length; } private: const char *buf; size_t length; }; template concept ReadableMemory = requires(T a) { { a.data() } -> std::convertible_to; { a.size() } -> std::convertible_to; }; template concept WriteableMemory = requires(T a) { { a.data() } -> std::convertible_to; { a.size() } -> std::convertible_to; }; // 分多次读取数据 template class versatile_reader : private boost::noncopyable { public: template explicit versatile_reader(const MemoryType &mem, size_t offset = 0) :buf(mem.data(), mem.size()), pos(buf.begin() + offset) { } template std::enable_if_t, T> read_value() { assert(pos + sizeof(T) <= buf.end()); T tmp_val; std::copy_n(pos, sizeof(T), (char *) &tmp_val); swap_net_loc_endian(tmp_val); pos += sizeof(T); return tmp_val; } template std::enable_if_t> read_value(T &val) { val = read_value(); } template void read_value(Eigen::MatrixBase &matrix) { for (Eigen::Index i = 0; i < matrix.size(); ++i) { read_value(matrix(i)); } } template void read_value(std::array &arr) { for (auto &val: arr) { read_value(val); } } std::string_view read_string(size_t read_length) { auto end_pos = pos + read_length; assert(end_pos <= buf.end()); auto ret = std::string_view{pos, end_pos}; pos = end_pos; return ret; } void read_string(std::string &str, size_t length) { str = read_string(length); } std::string_view read_string_until(char sep) { auto end_pos = pos; while (*end_pos != sep && end_pos != buf.end()) ++end_pos; auto ret = std::string_view{pos, end_pos}; pos = end_pos; if (pos != buf.end()) ++pos; // skip the separator return ret; } void read_string_until(std::string &str, char sep) { str = read_string_until(sep); } template auto &operator>>(T &val) { read_value(val); return *this; } // 从当前位置开始调整 offset void manual_offset(ptrdiff_t offset) { pos += offset; assert(pos >= buf.begin()); assert(pos <= buf.end()); } auto current_offset() const { return pos - buf.begin(); } bool empty() const { return pos == buf.end(); } private: using buffer_type = std::span; using iterator_type = buffer_type::iterator; buffer_type buf; iterator_type pos; }; // 分多次写入数据 template class versatile_writer { public: template explicit versatile_writer(MemoryType &mem, size_t offset = 0) :buf(mem.data(), mem.size()), pos(buf.begin() + offset) { } template std::enable_if_t> write_value(T val) { assert(pos + sizeof(T) <= buf.end()); swap_net_loc_endian(val); std::copy_n((char *) &val, sizeof(T), pos); pos += sizeof(T); } void write_value(std::string_view str) { assert(pos + str.length() <= buf.end()); std::copy(str.begin(), str.end(), pos); pos += str.length(); } template void write_value(const Eigen::MatrixBase &matrix) { for (Eigen::Index i = 0; i < matrix.size(); ++i) { write_value(matrix(i)); } } template void write_value(const std::array &arr) { for (auto val: arr) { write_value(val); } } template auto &operator<<(const T &val) { write_value(val); return *this; } // 从当前位置开始调整 offset void manual_offset(ptrdiff_t offset) { pos += offset; assert(pos >= buf.begin()); assert(pos <= buf.end()); } auto current_offset() const { return pos - buf.begin(); } auto remaining_bytes() const { return buf.end() - pos; } private: using buffer_type = std::span; using iterator_type = buffer_type::iterator; buffer_type buf; iterator_type pos; }; template class dynamic_memory_writer { public: explicit dynamic_memory_writer(dynamic_memory *mem, size_t offset = 0) : buf(mem) { buf->resize(offset); } template std::enable_if_t> write_value(T val) { swap_net_loc_endian(val); auto ptr = end_ptr(); buf->increase_size(sizeof(T)); memcpy(ptr, &val, sizeof(T)); } void write_value(std::string_view str) { auto ptr = end_ptr(); buf->increase_size(str.length()); std::copy(str.begin(), str.end(), ptr); } template void write_value(const Eigen::MatrixBase &matrix) { for (Eigen::Index i = 0; i < matrix.size(); ++i) { write_value(matrix(i)); } } template void write_value(const std::array &arr) { for (auto val: arr) { write_value(val); } } template auto &operator<<(const T &val) { write_value(val); return *this; } private: dynamic_memory *buf; char *end_ptr() { return buf->data() + buf->size(); } }; template std::enable_if_t, T> read_binary_value(const char *data) { T tmp_val; memcpy(&tmp_val, data, sizeof(T)); swap_net_loc_endian(tmp_val); return tmp_val; } template std::enable_if_t> read_binary_value(const char *data, T &val) { val = read_binary_value(data); } template std::enable_if_t> write_binary_value(char *data, T val) { swap_net_loc_endian(val); memcpy(data, &val, sizeof(T)); } template auto async_fill_memory_from(AsyncReadStream &s, MemoryType &mem) { return boost::asio::async_read(s, boost::asio::buffer(mem.data(), mem.size()), boost::asio::use_awaitable); } template auto async_write_memory_to(AsyncWriteStream &s, const MemoryType &mem) { return boost::asio::async_write(s, boost::asio::buffer(mem.data(), mem.size()), boost::asio::use_awaitable); } template std::enable_if_t, boost::asio::awaitable> inline async_write_value(AsyncWriteStream &s, T val) { swap_net_loc_endian(val); co_await boost::asio::async_write(s, boost::asio::buffer(&val, sizeof(T)), boost::asio::use_awaitable); co_return; } template std::enable_if_t, boost::asio::awaitable> inline async_read_value(AsyncReadStream &s) { T tmp_val; co_await boost::asio::async_read(s, boost::asio::buffer(&tmp_val, sizeof(T)), boost::asio::use_awaitable); swap_net_loc_endian(tmp_val); co_return tmp_val; } template std::enable_if_t, boost::asio::awaitable> inline async_read_value(AsyncReadStream &s, T &val) { val = co_await async_read_value(s); co_return; } } #endif //SOPHIAR2_VERSATILE_BUFFER2_HPP