blob: 7dc47ef771d14c86987dd868012e83a4ca285fe1 [file] [log] [blame]
#pragma once
#include <stdplus/fd/dupable.hpp>
#include <stdplus/fd/intf.hpp>
#include <stdplus/net/addr/sock.hpp>
#include <stdplus/raw.hpp>
#include <span>
#include <utility>
namespace stdplus
{
namespace fd
{
namespace detail
{
void readExact(Fd& fd, std::span<std::byte> data);
void recvExact(Fd& fd, std::span<std::byte> data, RecvFlags flags);
void writeExact(Fd& fd, std::span<const std::byte> data);
void sendExact(Fd& fd, std::span<const std::byte> data, SendFlags flags);
void sendtoExact(Fd& fd, std::span<const std::byte> data, SendFlags flags,
std::span<const std::byte> addr);
std::span<std::byte> readAligned(Fd& fd, size_t align,
std::span<std::byte> buf);
std::span<std::byte> recvAligned(Fd& fd, size_t align, std::span<std::byte> buf,
RecvFlags flags);
std::span<const std::byte> writeAligned(Fd& fd, size_t align,
std::span<const std::byte> data);
std::span<const std::byte> sendAligned(Fd& fd, size_t align,
std::span<const std::byte> data,
SendFlags flags);
template <typename Fun, typename Container, typename... Args>
auto alignedOp(Fun&& fun, Fd& fd, Container&& c, Args&&... args)
{
using Data = raw::detail::dataType<Container>;
auto ret = fun(fd, sizeof(Data), raw::asSpan<std::byte>(c),
std::forward<Args>(args)...);
return std::span<Data>(std::begin(c), ret.size() / sizeof(Data));
}
} // namespace detail
template <typename Container>
inline auto read(Fd& fd, Container&& c)
{
return detail::alignedOp(detail::readAligned, fd,
std::forward<Container>(c));
}
template <typename Container>
inline auto recv(Fd& fd, Container&& c, RecvFlags flags = {})
{
return detail::alignedOp(detail::recvAligned, fd,
std::forward<Container>(c), flags);
}
template <typename Container>
auto recvfrom(Fd& fd, Container&& c, SockAddrBuf& addr, RecvFlags flags = {})
{
using Data = raw::detail::dataType<Container>;
auto ret = fd.recvfrom(
raw::asSpan<std::byte>(c), flags,
std::span(reinterpret_cast<std::byte*>(&addr), addr.maxLen));
addr.len = std::get<1>(ret).size();
return std::span<Data>(std::begin(c),
std::get<0>(ret).size() / sizeof(Data));
}
template <typename Container>
inline auto write(Fd& fd, Container&& c)
{
return detail::alignedOp(detail::writeAligned, fd,
std::forward<Container>(c));
}
template <typename Container>
inline auto send(Fd& fd, Container&& c, SendFlags flags = {})
{
return detail::alignedOp(detail::sendAligned, fd,
std::forward<Container>(c), flags);
}
template <typename Container>
auto sendto(Fd& fd, Container&& c, const SockAddrBuf& addr,
SendFlags flags = {})
{
using Data = raw::detail::dataType<Container>;
auto ret = fd.sendto(
raw::asSpan<std::byte>(c), flags,
std::span(reinterpret_cast<const std::byte*>(&addr), addr.len));
return std::span<Data>(std::begin(c), ret.size() / sizeof(Data));
}
template <typename T>
inline void readExact(Fd& fd, T&& t)
{
detail::readExact(fd, raw::asSpan<std::byte>(t));
}
template <typename T>
inline void recvExact(Fd& fd, T&& t, RecvFlags flags = {})
{
detail::recvExact(fd, raw::asSpan<std::byte>(t), flags);
}
template <typename T>
inline void writeExact(Fd& fd, T&& t)
{
detail::writeExact(fd, raw::asSpan<std::byte>(t));
}
template <typename T>
inline void sendExact(Fd& fd, T&& t, SendFlags flags = {})
{
detail::sendExact(fd, raw::asSpan<std::byte>(t), flags);
}
template <typename Container>
inline void sendtoExact(Fd& fd, Container&& c, const SockAddrBuf& addr,
SendFlags flags = {})
{
detail::sendtoExact(
fd, raw::asSpan<std::byte>(c), flags,
std::span(reinterpret_cast<const std::byte*>(&addr), addr.len));
}
inline size_t lseek(Fd& fd, off_t offset, Whence whence)
{
return fd.lseek(offset, whence);
}
inline void truncate(Fd& fd, off_t size)
{
return fd.truncate(size);
}
inline void bind(Fd& fd, const SockAddrBuf& addr)
{
return fd.bind({reinterpret_cast<const std::byte*>(&addr), addr.len});
}
inline void bind(Fd& fd, const SockAddr auto& addr)
{
return bind(fd, addr.buf());
}
inline void bind(Fd& fd, const auto& sockaddr)
{
return fd.bind(raw::asSpan<std::byte>(sockaddr));
}
inline void connect(Fd& fd, const SockAddrBuf& addr)
{
return fd.connect({reinterpret_cast<const std::byte*>(&addr), addr.len});
}
inline void connect(Fd& fd, const SockAddr auto& addr)
{
return connect(fd, addr.buf());
}
inline void connect(Fd& fd, const auto& sockaddr)
{
return fd.connect(raw::asSpan<std::byte>(sockaddr));
}
inline void listen(Fd& fd, int backlog)
{
return fd.listen(backlog);
}
inline std::optional<DupableFd> accept(Fd& fd)
{
auto ret = fd.accept(std::span<std::byte>{});
if (!ret)
{
return std::nullopt;
}
return DupableFd(std::move(std::get<0>(*ret)));
}
template <typename Opt>
inline void setsockopt(Fd& fd, SockLevel level, SockOpt optname, Opt&& opt)
{
return fd.setsockopt(level, optname, raw::asSpan<std::byte>(opt));
}
template <typename Data>
inline int constIoctl(const Fd& fd, unsigned long id, Data&& data)
{
return fd.constIoctl(id, raw::asSpan<std::byte>(data).data());
}
template <typename Data>
inline int ioctl(Fd& fd, unsigned long id, Data&& data)
{
return fd.ioctl(id, raw::asSpan<std::byte>(data).data());
}
inline FdFlags getFdFlags(const Fd& fd)
{
return fd.fcntlGetfd();
}
inline void setFdFlags(Fd& fd, FdFlags flags)
{
return fd.fcntlSetfd(flags);
}
inline FileFlags getFileFlags(const Fd& fd)
{
return fd.fcntlGetfl();
}
inline void setFileFlags(Fd& fd, FileFlags flags)
{
return fd.fcntlSetfl(flags);
}
} // namespace fd
} // namespace stdplus