versatile_buffer2.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. #ifndef SOPHIAR2_VERSATILE_BUFFER2_HPP
  2. #define SOPHIAR2_VERSATILE_BUFFER2_HPP
  3. #include "utility/bit_operations.hpp"
  4. #include "utility/dynamic_pool.hpp"
  5. #include <boost/noncopyable.hpp>
  6. #include <boost/asio/awaitable.hpp>
  7. #include <boost/asio/read.hpp>
  8. #include <boost/asio/use_awaitable.hpp>
  9. #include <boost/asio/write.hpp>
  10. #include <Eigen/Core>
  11. #include <algorithm>
  12. #include <cassert>
  13. #include <concepts>
  14. #include <span>
  15. #include <string>
  16. #include <string_view>
  17. #include <type_traits>
  18. namespace sophiar {
  19. template<size_t Length>
  20. struct static_memory : private boost::noncopyable {
  21. char *data() { return buf.data(); }
  22. const char *data() const { return buf.data(); }
  23. constexpr size_t size() { return Length; }
  24. static auto new_instance() {
  25. using this_type = static_memory<Length>;
  26. return std::make_unique<this_type>();
  27. }
  28. private:
  29. std::array<char, Length> buf;
  30. };
  31. struct dynamic_memory : private boost::noncopyable {
  32. static constexpr size_t DYNAMIC_MEMORY_DEFAULT_SIZE = 32;
  33. using pointer = std::unique_ptr<dynamic_memory>;
  34. ~dynamic_memory() {
  35. DEALLOCATE_DYNAMIC_MEMORY((void *) buf, capacity_length);
  36. }
  37. char *data() { return buf; }
  38. const char *data() const { return buf; }
  39. size_t size() const { return used_length; }
  40. void resize(size_t req_size) {
  41. if (req_size > capacity_length) [[unlikely]] {
  42. auto ext_buf = (char *) ALLOCATE_DYNAMIC_MEMORY(req_size);
  43. memcpy(ext_buf, buf, used_length);
  44. DEALLOCATE_DYNAMIC_MEMORY((void *) buf, capacity_length);
  45. buf = ext_buf;
  46. capacity_length = ACTUAL_DYNAMIC_MEMORY_SIZE(req_size);
  47. }
  48. used_length = req_size;
  49. }
  50. void increase_size(ptrdiff_t extra_size) {
  51. assert(extra_size >= 0 || size() > -extra_size);
  52. resize(size() + extra_size);
  53. }
  54. static auto new_instance(size_t req_size = DYNAMIC_MEMORY_DEFAULT_SIZE) {
  55. return pointer{new dynamic_memory{req_size}};
  56. }
  57. private:
  58. char *buf;
  59. size_t used_length;
  60. size_t capacity_length;
  61. explicit dynamic_memory(size_t req_size) {
  62. buf = (char *) ALLOCATE_DYNAMIC_MEMORY(req_size);
  63. used_length = req_size;
  64. capacity_length = ACTUAL_DYNAMIC_MEMORY_SIZE(req_size);
  65. }
  66. };
  67. struct extern_memory {
  68. extern_memory(char *extern_buf, size_t buf_length)
  69. : buf(extern_buf), length(buf_length) {}
  70. extern_memory(const extern_memory &) = default;
  71. char *data() { return buf; }
  72. const char *data() const { return buf; }
  73. size_t size() const { return length; }
  74. private:
  75. char *buf;
  76. size_t length;
  77. };
  78. struct const_extern_memory {
  79. const_extern_memory(const char *extern_buf, size_t buf_length)
  80. : buf(extern_buf), length(buf_length) {}
  81. explicit const_extern_memory(const extern_memory &other)
  82. : buf(other.data()), length(other.size()) {}
  83. const_extern_memory(const const_extern_memory &) = default;
  84. const char *data() const { return buf; }
  85. size_t size() const { return length; }
  86. private:
  87. const char *buf;
  88. size_t length;
  89. };
  90. template<typename T>
  91. concept ReadableMemory = requires(T a) {
  92. { a.data() } -> std::convertible_to<const char *>;
  93. { a.size() } -> std::convertible_to<size_t>;
  94. };
  95. template<typename T>
  96. concept WriteableMemory = requires(T a) {
  97. { a.data() } -> std::convertible_to<char *>;
  98. { a.size() } -> std::convertible_to<size_t>;
  99. };
  100. // 分多次读取数据
  101. template<boost::endian::order net_order>
  102. class versatile_reader : private boost::noncopyable {
  103. public:
  104. template<ReadableMemory MemoryType>
  105. explicit versatile_reader(const MemoryType &mem, size_t offset = 0)
  106. :buf(mem.data(), mem.size()),
  107. pos(buf.begin() + offset) {
  108. }
  109. template<typename T>
  110. std::enable_if_t<std::is_arithmetic_v<T>, T>
  111. read_value() {
  112. assert(pos + sizeof(T) <= buf.end());
  113. T tmp_val;
  114. std::copy_n(pos, sizeof(T), (char *) &tmp_val);
  115. swap_net_loc_endian<net_order>(tmp_val);
  116. pos += sizeof(T);
  117. return tmp_val;
  118. }
  119. template<typename T>
  120. std::enable_if_t<std::is_arithmetic_v<T>>
  121. read_value(T &val) {
  122. val = read_value<T>();
  123. }
  124. template<typename Derived>
  125. void read_value(Eigen::MatrixBase<Derived> &matrix) {
  126. for (Eigen::Index i = 0; i < matrix.size(); ++i) {
  127. read_value(matrix(i));
  128. }
  129. }
  130. template<typename T, size_t Length>
  131. void read_value(std::array<T, Length> &arr) {
  132. for (auto &val: arr) {
  133. read_value(val);
  134. }
  135. }
  136. std::string_view read_string(size_t read_length) {
  137. auto end_pos = pos + read_length;
  138. assert(end_pos <= buf.end());
  139. auto ret = std::string_view{pos, end_pos};
  140. pos = end_pos;
  141. return ret;
  142. }
  143. void read_string(std::string &str, size_t length) {
  144. str = read_string(length);
  145. }
  146. std::string_view read_string_until(char sep) {
  147. auto end_pos = pos;
  148. while (*end_pos != sep && end_pos != buf.end()) ++end_pos;
  149. auto ret = std::string_view{pos, end_pos};
  150. pos = end_pos;
  151. if (pos != buf.end()) ++pos; // skip the separator
  152. return ret;
  153. }
  154. void read_string_until(std::string &str, char sep) {
  155. str = read_string_until(sep);
  156. }
  157. template<typename T>
  158. auto &operator>>(T &val) {
  159. read_value(val);
  160. return *this;
  161. }
  162. // 从当前位置开始调整 offset
  163. void manual_offset(ptrdiff_t offset) {
  164. pos += offset;
  165. assert(pos >= buf.begin());
  166. assert(pos <= buf.end());
  167. }
  168. auto current_offset() const {
  169. return pos - buf.begin();
  170. }
  171. bool empty() const {
  172. return pos == buf.end();
  173. }
  174. private:
  175. using buffer_type = std::span<const char>;
  176. using iterator_type = buffer_type::iterator;
  177. buffer_type buf;
  178. iterator_type pos;
  179. };
  180. // 分多次写入数据
  181. template<boost::endian::order net_order>
  182. class versatile_writer {
  183. public:
  184. template<WriteableMemory MemoryType>
  185. explicit versatile_writer(MemoryType &mem, size_t offset = 0)
  186. :buf(mem.data(), mem.size()),
  187. pos(buf.begin() + offset) {
  188. }
  189. template<typename T>
  190. std::enable_if_t<std::is_arithmetic_v<T>>
  191. write_value(T val) {
  192. assert(pos + sizeof(T) <= buf.end());
  193. swap_net_loc_endian<net_order>(val);
  194. std::copy_n((char *) &val, sizeof(T), pos);
  195. pos += sizeof(T);
  196. }
  197. void write_value(std::string_view str) {
  198. assert(pos + str.length() <= buf.end());
  199. std::copy(str.begin(), str.end(), pos);
  200. pos += str.length();
  201. }
  202. template<typename Derived>
  203. void write_value(const Eigen::MatrixBase<Derived> &matrix) {
  204. for (Eigen::Index i = 0; i < matrix.size(); ++i) {
  205. write_value(matrix(i));
  206. }
  207. }
  208. template<typename T, size_t Length>
  209. void write_value(const std::array<T, Length> &arr) {
  210. for (auto val: arr) {
  211. write_value(val);
  212. }
  213. }
  214. template<typename T>
  215. auto &operator<<(const T &val) {
  216. write_value(val);
  217. return *this;
  218. }
  219. // 从当前位置开始调整 offset
  220. void manual_offset(ptrdiff_t offset) {
  221. pos += offset;
  222. assert(pos >= buf.begin());
  223. assert(pos <= buf.end());
  224. }
  225. auto current_offset() const {
  226. return pos - buf.begin();
  227. }
  228. auto remaining_bytes() const {
  229. return buf.end() - pos;
  230. }
  231. private:
  232. using buffer_type = std::span<char>;
  233. using iterator_type = buffer_type::iterator;
  234. buffer_type buf;
  235. iterator_type pos;
  236. };
  237. template<boost::endian::order net_order>
  238. class dynamic_memory_writer {
  239. public:
  240. explicit dynamic_memory_writer(dynamic_memory *mem,
  241. size_t offset = 0)
  242. : buf(mem) {
  243. buf->resize(offset);
  244. }
  245. template<typename T>
  246. std::enable_if_t<std::is_arithmetic_v<T>>
  247. write_value(T val) {
  248. swap_net_loc_endian<net_order>(val);
  249. auto ptr = end_ptr();
  250. buf->increase_size(sizeof(T));
  251. memcpy(ptr, &val, sizeof(T));
  252. }
  253. void write_value(std::string_view str) {
  254. auto ptr = end_ptr();
  255. buf->increase_size(str.length());
  256. std::copy(str.begin(), str.end(), ptr);
  257. }
  258. template<typename Derived>
  259. void write_value(const Eigen::MatrixBase<Derived> &matrix) {
  260. for (Eigen::Index i = 0; i < matrix.size(); ++i) {
  261. write_value(matrix(i));
  262. }
  263. }
  264. template<typename T, size_t Length>
  265. void write_value(const std::array<T, Length> &arr) {
  266. for (auto val: arr) {
  267. write_value(val);
  268. }
  269. }
  270. template<typename T>
  271. auto &operator<<(const T &val) {
  272. write_value(val);
  273. return *this;
  274. }
  275. private:
  276. dynamic_memory *buf;
  277. char *end_ptr() {
  278. return buf->data() + buf->size();
  279. }
  280. };
  281. template<boost::endian::order net_order,
  282. typename T>
  283. std::enable_if_t<std::is_arithmetic_v<T>, T>
  284. read_binary_value(const char *data) {
  285. T tmp_val;
  286. memcpy(&tmp_val, data, sizeof(T));
  287. swap_net_loc_endian<net_order>(tmp_val);
  288. return tmp_val;
  289. }
  290. template<boost::endian::order net_order,
  291. typename T>
  292. std::enable_if_t<std::is_arithmetic_v<T>>
  293. read_binary_value(const char *data, T &val) {
  294. val = read_binary_value<net_order>(data);
  295. }
  296. template<boost::endian::order net_order,
  297. typename T>
  298. std::enable_if_t<std::is_arithmetic_v<T>>
  299. write_binary_value(char *data, T val) {
  300. swap_net_loc_endian<net_order>(val);
  301. memcpy(data, &val, sizeof(T));
  302. }
  303. template<WriteableMemory MemoryType, typename AsyncReadStream>
  304. auto async_fill_memory_from(AsyncReadStream &s, MemoryType &mem) {
  305. return boost::asio::async_read(s,
  306. boost::asio::buffer(mem.data(), mem.size()),
  307. boost::asio::use_awaitable);
  308. }
  309. template<ReadableMemory MemoryType, typename AsyncWriteStream>
  310. auto async_write_memory_to(AsyncWriteStream &s, const MemoryType &mem) {
  311. return boost::asio::async_write(s,
  312. boost::asio::buffer(mem.data(), mem.size()),
  313. boost::asio::use_awaitable);
  314. }
  315. template<boost::endian::order net_order,
  316. typename AsyncWriteStream, typename T>
  317. std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<void>>
  318. inline async_write_value(AsyncWriteStream &s, T val) {
  319. swap_net_loc_endian<net_order>(val);
  320. co_await boost::asio::async_write(s,
  321. boost::asio::buffer(&val, sizeof(T)),
  322. boost::asio::use_awaitable);
  323. co_return;
  324. }
  325. template<boost::endian::order net_order,
  326. typename T, typename AsyncReadStream>
  327. std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<T>>
  328. inline async_read_value(AsyncReadStream &s) {
  329. T tmp_val;
  330. co_await boost::asio::async_read(s,
  331. boost::asio::buffer(&tmp_val, sizeof(T)),
  332. boost::asio::use_awaitable);
  333. swap_net_loc_endian<net_order>(tmp_val);
  334. co_return tmp_val;
  335. }
  336. template<boost::endian::order net_order,
  337. typename T, typename AsyncReadStream>
  338. std::enable_if_t<std::is_arithmetic_v<T>, boost::asio::awaitable<void>>
  339. inline async_read_value(AsyncReadStream &s, T &val) {
  340. val = co_await async_read_value<net_order, T>(s);
  341. co_return;
  342. }
  343. }
  344. #endif //SOPHIAR2_VERSATILE_BUFFER2_HPP