| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- #ifndef SOPHIAR2_VERSATILE_BUFFER2_HPP
- #define SOPHIAR2_VERSATILE_BUFFER2_HPP
- #include "utility/bit_operations.hpp"
- #include "utility/dynamic_pool.hpp"
- #include <boost/noncopyable.hpp>
- #include <boost/asio/awaitable.hpp>
- #include <boost/asio/read.hpp>
- #include <boost/asio/use_awaitable.hpp>
- #include <boost/asio/write.hpp>
- #include <Eigen/Core>
- #include <algorithm>
- #include <cassert>
- #include <concepts>
- #include <span>
- #include <string>
- #include <string_view>
- #include <type_traits>
- namespace sophiar {
- template<size_t Length>
- 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<Length>;
- return std::make_unique<this_type>();
- }
- private:
- std::array<char, Length> buf;
- };
- struct dynamic_memory : private boost::noncopyable {
- static constexpr size_t DYNAMIC_MEMORY_DEFAULT_SIZE = 32;
- using pointer = std::unique_ptr<dynamic_memory>;
- ~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<typename T>
- concept ReadableMemory = requires(T a) {
- { a.data() } -> std::convertible_to<const char *>;
- { a.size() } -> std::convertible_to<size_t>;
- };
- template<typename T>
- concept WriteableMemory = requires(T a) {
- { a.data() } -> std::convertible_to<char *>;
- { a.size() } -> std::convertible_to<size_t>;
- };
- // 分多次读取数据
- template<boost::endian::order net_order>
- class versatile_reader : private boost::noncopyable {
- public:
- template<ReadableMemory MemoryType>
- explicit versatile_reader(const MemoryType &mem, size_t offset = 0)
- :buf(mem.data(), mem.size()),
- pos(buf.begin() + offset) {
- }
- template<typename T>
- std::enable_if_t<std::is_arithmetic_v<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<net_order>(tmp_val);
- pos += sizeof(T);
- return tmp_val;
- }
- template<typename T>
- std::enable_if_t<std::is_arithmetic_v<T>>
- read_value(T &val) {
- val = read_value<T>();
- }
- template<typename Derived>
- void read_value(Eigen::MatrixBase<Derived> &matrix) {
- for (Eigen::Index i = 0; i < matrix.size(); ++i) {
- read_value(matrix(i));
- }
- }
- template<typename T, size_t Length>
- void read_value(std::array<T, Length> &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<typename T>
- 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<const char>;
- using iterator_type = buffer_type::iterator;
- buffer_type buf;
- iterator_type pos;
- };
- // 分多次写入数据
- template<boost::endian::order net_order>
- class versatile_writer {
- public:
- template<WriteableMemory MemoryType>
- explicit versatile_writer(MemoryType &mem, size_t offset = 0)
- :buf(mem.data(), mem.size()),
- pos(buf.begin() + offset) {
- }
- template<typename T>
- std::enable_if_t<std::is_arithmetic_v<T>>
- write_value(T val) {
- assert(pos + sizeof(T) <= buf.end());
- swap_net_loc_endian<net_order>(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<typename Derived>
- void write_value(const Eigen::MatrixBase<Derived> &matrix) {
- for (Eigen::Index i = 0; i < matrix.size(); ++i) {
- write_value(matrix(i));
- }
- }
- template<typename T, size_t Length>
- void write_value(const std::array<T, Length> &arr) {
- for (auto val: arr) {
- write_value(val);
- }
- }
- template<typename T>
- 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<char>;
- using iterator_type = buffer_type::iterator;
- buffer_type buf;
- iterator_type pos;
- };
- template<boost::endian::order net_order>
- class dynamic_memory_writer {
- public:
- explicit dynamic_memory_writer(dynamic_memory *mem,
- size_t offset = 0)
- : buf(mem) {
- buf->resize(offset);
- }
- template<typename T>
- std::enable_if_t<std::is_arithmetic_v<T>>
- write_value(T val) {
- swap_net_loc_endian<net_order>(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<typename Derived>
- void write_value(const Eigen::MatrixBase<Derived> &matrix) {
- for (Eigen::Index i = 0; i < matrix.size(); ++i) {
- write_value(matrix(i));
- }
- }
- template<typename T, size_t Length>
- void write_value(const std::array<T, Length> &arr) {
- for (auto val: arr) {
- write_value(val);
- }
- }
- template<typename T>
- auto &operator<<(const T &val) {
- write_value(val);
- return *this;
- }
- private:
- dynamic_memory *buf;
- char *end_ptr() {
- return buf->data() + buf->size();
- }
- };
- template<boost::endian::order net_order,
- typename T>
- std::enable_if_t<std::is_arithmetic_v<T>, T>
- read_binary_value(const char *data) {
- T tmp_val;
- memcpy(&tmp_val, data, sizeof(T));
- swap_net_loc_endian<net_order>(tmp_val);
- return tmp_val;
- }
- template<boost::endian::order net_order,
- typename T>
- std::enable_if_t<std::is_arithmetic_v<T>>
- read_binary_value(const char *data, T &val) {
- val = read_binary_value<net_order>(data);
- }
- template<boost::endian::order net_order,
- typename T>
- std::enable_if_t<std::is_arithmetic_v<T>>
- write_binary_value(char *data, T val) {
- swap_net_loc_endian<net_order>(val);
- memcpy(data, &val, sizeof(T));
- }
- template<WriteableMemory MemoryType, typename AsyncReadStream>
- 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<ReadableMemory MemoryType, typename AsyncWriteStream>
- 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<boost::endian::order net_order,
- typename AsyncWriteStream, typename T>
- std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<void>>
- inline async_write_value(AsyncWriteStream &s, T val) {
- swap_net_loc_endian<net_order>(val);
- co_await boost::asio::async_write(s,
- boost::asio::buffer(&val, sizeof(T)),
- boost::asio::use_awaitable);
- co_return;
- }
- template<boost::endian::order net_order,
- typename T, typename AsyncReadStream>
- std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<T>>
- 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<net_order>(tmp_val);
- co_return tmp_val;
- }
- template<boost::endian::order net_order,
- typename T, typename AsyncReadStream>
- std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<void>>
- inline async_read_value(AsyncReadStream &s, T &val) {
- val = co_await async_read_value<net_order, T>(s);
- co_return;
- }
- }
- #endif //SOPHIAR2_VERSATILE_BUFFER2_HPP
|