blob: d18e8553488030137028f9b45016d62182c86d34 [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{
William A. Kennington IIIb88c4572023-12-22 16:43:42 -080069 std::size_t total = 0;
70 try
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070071 {
William A. Kennington IIIb88c4572023-12-22 16:43:42 -080072 do
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070073 {
William A. Kennington IIIb88c4572023-12-22 16:43:42 -080074 auto r = (fd.*fun)(data.subspan(total),
75 std::forward<Args>(args)...);
76 if (total != 0 && r.size() == 0)
77 {
78 throw exception::Incomplete(
79 std::format("{} is {}B/{}B", name, total % align, align));
80 }
81 total += r.size();
82 } while (total % align != 0);
83 }
84 catch (const std::system_error&)
85 {
86 if (total % align)
87 {
88 throw exception::Incomplete(
89 std::format("{} is {}B/{}B", name, total % align, align));
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070090 }
William A. Kennington IIIb88c4572023-12-22 16:43:42 -080091 throw;
92 }
93 return std::span<Byte>(data.data(), total);
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070094}
95
Patrick Williams68975b92022-04-27 16:00:26 -050096std::span<std::byte> readAligned(Fd& fd, size_t align, std::span<std::byte> buf)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -070097{
98 return opAligned("readAligned", &Fd::read, fd, align, buf);
99}
100
Patrick Williams68975b92022-04-27 16:00:26 -0500101std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
102 RecvFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700103{
104 return opAligned("recvAligned", &Fd::recv, fd, align, buf, flags);
105}
106
Patrick Williams68975b92022-04-27 16:00:26 -0500107std::span<const std::byte> writeAligned(Fd& fd, size_t align,
108 std::span<const std::byte> data)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700109{
110 return opAligned("writeAligned", &Fd::write, fd, align, data);
111}
112
Patrick Williams68975b92022-04-27 16:00:26 -0500113std::span<const std::byte> sendAligned(Fd& fd, size_t align,
114 std::span<const std::byte> data,
115 SendFlags flags)
William A. Kennington IIIeac9d472020-08-03 13:57:14 -0700116{
117 return opAligned("sendAligned", &Fd::send, fd, align, data, flags);
118}
119
120} // namespace detail
121} // namespace fd
122} // namespace stdplus