blob: d5991c6008659daafb60f714fd71aab4f77d9d38 [file] [log] [blame]
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07001#include <stdplus/exception.hpp>
2#include <stdplus/fd/ops.hpp>
Patrick Williamsd1984dd2023-05-10 16:12:44 -05003
William A. Kennington III6417c632023-07-17 02:56:52 -07004#include <format>
William A. Kennington IIIeac9d472020-08-03 13:57:14 -07005#include <utility>
6
7namespace stdplus
8{
9namespace fd
10{
11namespace detail
12{
13
14template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050015static void opExact(const char* name, Fun&& fun, Fd& fd, std::span<Byte> data,
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070016 Args&&... args)
17{
William A. Kennington III93ae9702023-12-22 16:41:17 -080018 std::size_t total = 0;
19 try
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070020 {
William A. Kennington III93ae9702023-12-22 16:41:17 -080021 while (total < data.size())
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070022 {
William A. Kennington III93ae9702023-12-22 16:41:17 -080023 auto r = (fd.*fun)(data.subspan(total),
24 std::forward<Args>(args)...);
25 if (r.size() == 0)
26 {
27 throw exception::WouldBlock(
28 std::format("{} missing", name, data.size()));
29 }
30 total += r.size();
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070031 }
William A. Kennington III93ae9702023-12-22 16:41:17 -080032 }
33 catch (const std::system_error&)
34 {
35 if (total != 0)
36 {
37 throw exception::Incomplete(
38 std::format("{} is {}B/{}B", name, total, data.size()));
39 }
40 throw;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070041 }
42}
43
Patrick Williams68975b92022-04-27 16:00:26 -050044void readExact(Fd& fd, std::span<std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070045{
46 opExact("readExact", &Fd::read, fd, data);
47}
48
Patrick Williams68975b92022-04-27 16:00:26 -050049void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070050{
51 opExact("recvExact", &Fd::recv, fd, data, flags);
52}
53
Patrick Williams68975b92022-04-27 16:00:26 -050054void writeExact(Fd& fd, std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070055{
56 opExact("writeExact", &Fd::write, fd, data);
57}
58
Patrick Williams68975b92022-04-27 16:00:26 -050059void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070060{
61 opExact("sendExact", &Fd::send, fd, data, flags);
62}
63
64template <typename Fun, typename Byte, typename... Args>
Patrick Williams68975b92022-04-27 16:00:26 -050065static std::span<Byte> opAligned(const char* name, Fun&& fun, Fd& fd,
66 size_t align, std::span<Byte> data,
67 Args&&... args)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070068{
Patrick Williams68975b92022-04-27 16:00:26 -050069 std::span<Byte> ret;
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070070 do
71 {
Patrick Williamsd1984dd2023-05-10 16:12:44 -050072 auto r = (fd.*fun)(data.subspan(ret.size()),
73 std::forward<Args>(args)...);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070074 if (ret.size() != 0 && r.size() == 0)
75 {
76 throw exception::WouldBlock(
William A. Kennington III6417c632023-07-17 02:56:52 -070077 std::format("{} is {}B/{}B", name, ret.size() % align, align));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070078 }
79 ret = data.subspan(0, ret.size() + r.size());
80 } while (ret.size() % align != 0);
81 return ret;
82}
83
Patrick Williams68975b92022-04-27 16:00:26 -050084std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070085{
86 return opAligned("readAligned", &Fd::read, fd, align, buf);
87}
88
Patrick Williams68975b92022-04-27 16:00:26 -050089std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
90 RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070091{
92 return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
93}
94
Patrick Williams68975b92022-04-27 16:00:26 -050095std::span<const std::byte> writeAligned(Fd& fd, size_t align,
96 std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070097{
98 return opAligned("writeAligned", &Fd::write, fd, align, data);
99}
100
Patrick Williams68975b92022-04-27 16:00:26 -0500101std::span<const std::byte> sendAligned(Fd& fd, size_t align,
102 std::span<const std::byte> data,
103 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700104{
105 return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
106}
107
108} // namespace detail
109} // namespace fd
110} // namespace stdplus