build: Refactor directory structure to separate headers
This makes the structure similar to other OpenBMC projects.
Change-Id: I5b76fe7439dba9b68244ee1494f2266b6351e498
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/stdplus/dl.cpp b/src/dl.cpp
similarity index 100%
rename from src/stdplus/dl.cpp
rename to src/dl.cpp
diff --git a/src/stdplus/exception.cpp b/src/exception.cpp
similarity index 100%
rename from src/stdplus/exception.cpp
rename to src/exception.cpp
diff --git a/src/stdplus/fd/create.cpp b/src/fd/create.cpp
similarity index 100%
rename from src/stdplus/fd/create.cpp
rename to src/fd/create.cpp
diff --git a/src/stdplus/fd/dupable.cpp b/src/fd/dupable.cpp
similarity index 100%
rename from src/stdplus/fd/dupable.cpp
rename to src/fd/dupable.cpp
diff --git a/src/stdplus/fd/impl.cpp b/src/fd/impl.cpp
similarity index 100%
rename from src/stdplus/fd/impl.cpp
rename to src/fd/impl.cpp
diff --git a/src/stdplus/fd/managed.cpp b/src/fd/managed.cpp
similarity index 100%
rename from src/stdplus/fd/managed.cpp
rename to src/fd/managed.cpp
diff --git a/src/stdplus/fd/mmap.cpp b/src/fd/mmap.cpp
similarity index 100%
rename from src/stdplus/fd/mmap.cpp
rename to src/fd/mmap.cpp
diff --git a/src/stdplus/fd/ops.cpp b/src/fd/ops.cpp
similarity index 100%
rename from src/stdplus/fd/ops.cpp
rename to src/fd/ops.cpp
diff --git a/src/stdplus/io_uring.cpp b/src/io_uring.cpp
similarity index 100%
rename from src/stdplus/io_uring.cpp
rename to src/io_uring.cpp
diff --git a/src/meson.build b/src/meson.build
index af7399c..1492655 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,5 +1,3 @@
-stdplus_headers = include_directories('.')
-
fmt_dep = dependency('fmt', required: false)
if not fmt_dep.found()
fmt_opts = import('cmake').subproject_options()
@@ -20,79 +18,39 @@
]
stdplus_srcs = [
- 'stdplus/exception.cpp',
- 'stdplus/signal.cpp',
+ 'exception.cpp',
+ 'signal.cpp',
]
-has_dl = false
-if not get_option('dl').disabled()
- dl_dep = meson.get_compiler('cpp').find_library('dl', required: false)
- has_dl = meson.get_compiler('cpp').links('''
- #include <dlfcn.h>
- int main() { dlopen("", 0); }
- ''', dependencies: dl_dep)
-endif
if has_dl
stdplus_deps += [
dl_dep,
]
stdplus_srcs += [
- 'stdplus/dl.cpp',
+ 'dl.cpp',
]
-
- install_headers(
- 'stdplus/dl.hpp',
- subdir: 'stdplus')
-elif get_option('dl').enabled()
- error('libdl support required')
endif
-has_fd = false
-if not get_option('fd').disabled()
- has_fd = true
-
+if has_fd
stdplus_srcs += [
- 'stdplus/fd/create.cpp',
- 'stdplus/fd/dupable.cpp',
- 'stdplus/fd/impl.cpp',
- 'stdplus/fd/managed.cpp',
- 'stdplus/fd/mmap.cpp',
- 'stdplus/fd/ops.cpp',
+ 'fd/create.cpp',
+ 'fd/dupable.cpp',
+ 'fd/impl.cpp',
+ 'fd/managed.cpp',
+ 'fd/mmap.cpp',
+ 'fd/ops.cpp',
]
-
- install_headers(
- 'stdplus/fd/create.hpp',
- 'stdplus/fd/dupable.hpp',
- 'stdplus/fd/gmock.hpp',
- 'stdplus/fd/impl.hpp',
- 'stdplus/fd/intf.hpp',
- 'stdplus/fd/managed.hpp',
- 'stdplus/fd/mmap.hpp',
- 'stdplus/fd/ops.hpp',
- subdir: 'stdplus/fd')
-elif get_option('fd').enabled()
- error('File descriptor support required')
endif
-io_uring_dep = dependency('liburing', required: get_option('io_uring'))
-has_io_uring = false
-if not get_option('io_uring').disabled() and has_fd and io_uring_dep.found()
- has_io_uring = true
-
+if has_io_uring
stdplus_deps += [
io_uring_dep,
]
stdplus_srcs += [
- 'stdplus/io_uring.cpp',
+ 'io_uring.cpp',
]
-
- install_headers(
- 'stdplus/io_uring.hpp',
- subdir: 'stdplus')
-elif get_option('io_uring').enabled()
- error('File descriptor support required')
endif
stdplus_lib = library(
@@ -121,21 +79,3 @@
description: 'C++ helper utilities',
version: meson.project_version(),
requires: stdplus_reqs)
-
-install_headers(
- 'stdplus/cancel.hpp',
- 'stdplus/exception.hpp',
- 'stdplus/flags.hpp',
- 'stdplus/raw.hpp',
- 'stdplus/signal.hpp',
- subdir: 'stdplus')
-
-install_headers(
- 'stdplus/handle/copyable.hpp',
- 'stdplus/handle/managed.hpp',
- subdir: 'stdplus/handle')
-
-install_headers(
- 'stdplus/util/cexec.hpp',
- 'stdplus/util/string.hpp',
- subdir: 'stdplus/util')
diff --git a/src/stdplus/signal.cpp b/src/signal.cpp
similarity index 100%
rename from src/stdplus/signal.cpp
rename to src/signal.cpp
diff --git a/src/stdplus/cancel.hpp b/src/stdplus/cancel.hpp
deleted file mode 100644
index cb40c87..0000000
--- a/src/stdplus/cancel.hpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#pragma once
-#include <stdplus/handle/managed.hpp>
-
-#include <tuple>
-#include <utility>
-
-namespace stdplus
-{
-
-struct Cancelable
-{
- virtual ~Cancelable() = default;
- virtual void cancel() noexcept = 0;
-};
-
-namespace detail
-{
-
-struct CancelableF
-{
- inline void operator()(Cancelable* c) noexcept
- {
- c->cancel();
- }
-};
-
-using CancelHandle = stdplus::Managed<Cancelable*>::HandleF<CancelableF>;
-
-} // namespace detail
-
-struct Cancel : detail::CancelHandle
-{
- Cancel() : detail::CancelHandle(std::nullopt)
- {
- }
- template <typename T>
- explicit Cancel(T&& t) : detail::CancelHandle(t)
- {
- }
-};
-
-namespace detail
-{
-
-struct fAny
-{
-};
-struct fPtr : fAny
-{
-};
-
-template <typename>
-struct validator
-{
- typedef int type;
-};
-
-template <typename F,
- typename validator<decltype(std::declval<F>() == nullptr)>::type = 0>
-inline bool fPop(const F& f, fPtr)
-{
- return !(f == nullptr);
-}
-
-template <typename F>
-inline bool fPop(const F&, fAny)
-{
- return true;
-}
-
-template <typename F>
-inline bool fPop(const F& f)
-{
- return fPop(f, fPtr());
-}
-
-} // namespace detail
-
-template <typename F, typename... DefaultArgs>
-class AlwaysCallOnce
-{
- public:
- template <typename Fi, typename... Vs>
- explicit AlwaysCallOnce(Fi&& fi, Vs&&... default_args) :
- f(std::forward<Fi>(fi)), default_args(std::forward<Vs>(default_args)...)
- {
- }
- AlwaysCallOnce(const AlwaysCallOnce&) = delete;
- AlwaysCallOnce(AlwaysCallOnce&& other) noexcept :
- f(std::move(other.f)), default_args(std::move(other.default_args)),
- called(std::exchange(other.called, true))
- {
- }
- AlwaysCallOnce& operator=(const AlwaysCallOnce&) = delete;
- AlwaysCallOnce& operator=(AlwaysCallOnce&& other) noexcept
- {
- finalCall();
- f = std::move(other.f);
- default_args = std::move(other.default_args);
- called = std::exchange(other.called, true);
- return *this;
- }
- ~AlwaysCallOnce()
- {
- finalCall();
- }
-
- template <typename... Args>
- auto operator()(Args&&... args) noexcept
- {
- called = true;
- return f(std::forward<Args>(args)...);
- }
-
- private:
- F f;
- std::tuple<DefaultArgs...> default_args;
- bool called = false;
-
- void finalCall() noexcept
- {
- if (!called && detail::fPop(f))
- {
- std::apply(f, default_args);
- }
- }
-};
-
-template <typename... Args>
-inline auto alwaysCallOnce(Args&&... args)
-{
- return AlwaysCallOnce<std::remove_cv_t<std::remove_reference_t<Args>>...>(
- std::forward<Args>(args)...);
-}
-
-} // namespace stdplus
diff --git a/src/stdplus/dl.hpp b/src/stdplus/dl.hpp
deleted file mode 100644
index 0526391..0000000
--- a/src/stdplus/dl.hpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-#include <dlfcn.h>
-#include <link.h>
-
-#include <stdplus/flags.hpp>
-#include <stdplus/handle/managed.hpp>
-
-namespace stdplus
-{
-
-enum class DlOpenType : int
-{
- Lazy = RTLD_LAZY,
- Now = RTLD_NOW,
-};
-
-enum class DlOpenFlag : int
-{
- Global = RTLD_GLOBAL,
- Local = RTLD_LOCAL,
- NoDelete = RTLD_NODELETE,
- NoLoad = RTLD_NOLOAD,
- DeepBind = RTLD_DEEPBIND,
-};
-
-class DlOpenFlags : public stdplus::BitFlags<int, DlOpenFlag>
-{
- public:
- inline DlOpenFlags(DlOpenType type) :
- BitFlags<int, DlOpenFlag>(static_cast<int>(type))
- {
- }
-
- inline DlOpenFlags(BitFlags<int, DlOpenFlag> flags) :
- BitFlags<int, DlOpenFlag>(flags)
- {
- }
-};
-
-class Dl
-{
- public:
- Dl(const char* filename, DlOpenFlags flags);
-
- struct link_map* linkMap();
-
- private:
- void info(int request, void* info);
-
- static void* open(const char* filename, int flags);
- static void close(void*&& handle);
- stdplus::Managed<void*>::Handle<close> handle;
-};
-
-} // namespace stdplus
diff --git a/src/stdplus/exception.hpp b/src/stdplus/exception.hpp
deleted file mode 100644
index a7dbe8b..0000000
--- a/src/stdplus/exception.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#pragma once
-#include <fmt/format.h>
-#include <system_error>
-#include <utility>
-
-// Forward declare builtins in case they are unsupported
-#if !__has_builtin(__builtin_LINE)
-int __builtin_LINE();
-const char* __builtin_FILE();
-const char* __builtin_FUNCTION();
-#endif
-
-namespace stdplus
-{
-namespace exception
-{
-
-struct WouldBlock : public std::system_error
-{
- WouldBlock(const char* what);
- WouldBlock(const std::string& what);
-};
-
-struct Eof : public std::system_error
-{
- Eof(const char* what);
- Eof(const std::string& what);
-};
-
-template <typename F>
-auto ignore(F&& f, const char* file = __builtin_FILE(),
- int line = __builtin_LINE(),
- const char* func = __builtin_FUNCTION()) noexcept
-{
- return
- [f = std::move(f), file, line, func](auto&&... args) mutable noexcept {
- try
- {
- return f(std::forward<decltype(args)>(args)...);
- }
- catch (const std::exception& e)
- {
- fmt::print(stderr, "Ignoring({}:{} {}): {}\n", file, line, func,
- e.what());
- }
- catch (...)
- {
- fmt::print(stderr, "Ignoring({}:{} {}): Invalid Error\n", file,
- line, func);
- }
- using Ret = std::invoke_result_t<decltype(f), decltype(args)...>;
- if constexpr (!std::is_same_v<void, Ret>)
- {
- return Ret();
- }
- };
-}
-
-template <typename F>
-auto ignoreQuiet(F&& f) noexcept
-{
- return [f = std::move(f)](auto&&... args) mutable noexcept {
- try
- {
- return f(std::forward<decltype(args)>(args)...);
- }
- catch (...)
- {
- }
- using Ret = std::invoke_result_t<decltype(f), decltype(args)...>;
- if constexpr (!std::is_same_v<void, Ret>)
- {
- return Ret();
- }
- };
-}
-
-} // namespace exception
-} // namespace stdplus
diff --git a/src/stdplus/fd/create.hpp b/src/stdplus/fd/create.hpp
deleted file mode 100644
index 83aa2ba..0000000
--- a/src/stdplus/fd/create.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-#include <fcntl.h>
-#include <netinet/ip.h>
-#include <stdplus/fd/dupable.hpp>
-#include <stdplus/flags.hpp>
-#include <string>
-
-namespace stdplus
-{
-namespace fd
-{
-
-enum class OpenAccess : int
-{
- ReadOnly = O_RDONLY,
- WriteOnly = O_WRONLY,
- ReadWrite = O_RDWR,
-};
-
-enum class OpenFlag : int
-{
- Append = O_APPEND,
- Async = O_ASYNC,
- CloseOnExec = O_CLOEXEC,
- Create = O_CREAT,
- Direct = O_DIRECT,
- Directory = O_DIRECTORY,
- Dsync = O_DSYNC,
- EnsureCreate = O_EXCL,
- LargeFile = O_LARGEFILE,
- NoAtime = O_NOATIME,
- NoCtty = O_NOCTTY,
- NoFollow = O_NOFOLLOW,
- NonBlock = O_NONBLOCK,
- Path = O_PATH,
- Sync = O_SYNC,
- TmpFile = O_TMPFILE,
- Trunc = O_TRUNC,
-};
-
-class OpenFlags : public BitFlags<int, OpenFlag>
-{
- public:
- inline OpenFlags(OpenAccess access) :
- BitFlags<int, OpenFlag>(static_cast<int>(access))
- {
- }
-
- inline OpenFlags(BitFlags<int, OpenFlag> flags) :
- BitFlags<int, OpenFlag>(flags)
- {
- }
-};
-
-DupableFd open(const char* pathname, OpenFlags flags, mode_t mode = 0);
-inline DupableFd open(const std::string& pathname, OpenFlags flags,
- mode_t mode = 0)
-{
- return open(pathname.c_str(), flags, mode);
-}
-
-enum class SocketDomain : int
-{
- INet = AF_INET,
- INet6 = AF_INET6,
- Netlink = AF_NETLINK,
- Packet = AF_PACKET,
- UNIX = AF_UNIX,
-};
-
-enum class SocketType : int
-{
- Datagram = SOCK_DGRAM,
- Raw = SOCK_RAW,
- Stream = SOCK_STREAM,
-};
-
-enum class SocketProto : int
-{
- ICMP = IPPROTO_ICMP,
- IP = IPPROTO_IP,
- Raw = IPPROTO_RAW,
- TCP = IPPROTO_TCP,
- UDP = IPPROTO_UDP,
-};
-
-DupableFd socket(SocketDomain domain, SocketType type, SocketProto protocol);
-
-} // namespace fd
-} // namespace stdplus
diff --git a/src/stdplus/fd/dupable.hpp b/src/stdplus/fd/dupable.hpp
deleted file mode 100644
index 0f810cf..0000000
--- a/src/stdplus/fd/dupable.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-#include <stdplus/fd/impl.hpp>
-#include <stdplus/fd/managed.hpp>
-#include <stdplus/handle/copyable.hpp>
-
-namespace stdplus
-{
-namespace fd
-{
-namespace detail
-{
-
-int ref(const int& fd);
-
-using DupableFdHandle = Copyable<int>::Handle<drop, ref>;
-
-} // namespace detail
-
-/** @class DupableFd
- * @brief Holds references to file descriptors which can be dup'd
- * @details Provides RAII semantics for file descriptors
- */
-class DupableFd : public FdImpl
-{
- public:
- /** @brief Constructs an empty file descriptor */
- DupableFd() noexcept;
-
- /** @brief Duplicates and holds a file descriptor
- * Does not automatically close the input descriptor
- *
- * @param[in] fd - File descriptor being duplicated
- * @throws std::system_error for underlying syscall failures
- */
- explicit DupableFd(const int& fd);
-
- /** @brief Holds the input file descriptor
- * Becomes the sole owner of the file descriptor
- *
- * @param[in] fd - File descriptor to hold
- */
- explicit DupableFd(int&& fd);
-
- /** @brief Unmanages the file descriptor and returns the value with
- * ownership to the caller.
- *
- * @return The file descriptor number
- */
- [[nodiscard]] int release();
-
- int get() const override;
-
- private:
- friend class ManagedFd;
- detail::DupableFdHandle handle;
-};
-
-} // namespace fd
-
-using fd::DupableFd;
-
-} // namespace stdplus
diff --git a/src/stdplus/fd/gmock.hpp b/src/stdplus/fd/gmock.hpp
deleted file mode 100644
index ca3b2af..0000000
--- a/src/stdplus/fd/gmock.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-#include <gmock/gmock.h>
-#include <stdplus/fd/intf.hpp>
-
-namespace stdplus
-{
-namespace fd
-{
-
-class FdMock : public Fd
-{
- public:
- MOCK_METHOD(std::span<std::byte>, read, (std::span<std::byte> buf),
- (override));
- MOCK_METHOD(std::span<std::byte>, recv,
- (std::span<std::byte> buf, RecvFlags flags), (override));
- MOCK_METHOD(std::span<const std::byte>, write,
- (std::span<const std::byte> data), (override));
- MOCK_METHOD(std::span<const std::byte>, send,
- (std::span<const std::byte> data, SendFlags flags), (override));
- MOCK_METHOD(size_t, lseek, (off_t offset, Whence whence), (override));
- MOCK_METHOD(void, truncate, (off_t size), (override));
- MOCK_METHOD(void, bind, (std::span<const std::byte> sockaddr), (override));
- MOCK_METHOD(void, listen, (int backlog), (override));
- MOCK_METHOD((std::tuple<std::optional<int>, std::span<std::byte>>), accept,
- (std::span<std::byte> sockaddr), (override));
- MOCK_METHOD(void, setsockopt,
- (SockLevel level, SockOpt optname,
- std::span<const std::byte> opt),
- (override));
- MOCK_METHOD(int, ioctl, (unsigned long id, void* data), (override));
- MOCK_METHOD(int, constIoctl, (unsigned long id, void* data),
- (const, override));
- MOCK_METHOD(void, fcntlSetfd, (FdFlags flags), (override));
- MOCK_METHOD(FdFlags, fcntlGetfd, (), (const, override));
- MOCK_METHOD(void, fcntlSetfl, (FileFlags flags), (override));
- MOCK_METHOD(FileFlags, fcntlGetfl, (), (const, override));
- MOCK_METHOD(std::span<std::byte>, mmap,
- (std::span<std::byte> window, ProtFlags prot, MMapFlags flags,
- off_t offset),
- (override));
- MOCK_METHOD(void, munmap, (std::span<std::byte> window), (override));
-};
-
-} // namespace fd
-
-using fd::FdMock;
-
-} // namespace stdplus
diff --git a/src/stdplus/fd/impl.hpp b/src/stdplus/fd/impl.hpp
deleted file mode 100644
index 9d5acaf..0000000
--- a/src/stdplus/fd/impl.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-#include <stdplus/fd/intf.hpp>
-
-namespace stdplus
-{
-namespace fd
-{
-
-class FdImpl : public Fd
-{
- public:
- virtual int get() const = 0;
-
- std::span<std::byte> read(std::span<std::byte> buf) override;
- std::span<std::byte> recv(std::span<std::byte> buf,
- RecvFlags flags) override;
- std::span<const std::byte> write(std::span<const std::byte> data) override;
- std::span<const std::byte> send(std::span<const std::byte> data,
- SendFlags flags) override;
- size_t lseek(off_t offset, Whence whence) override;
- void truncate(off_t size) override;
- void bind(std::span<const std::byte> sockaddr) override;
- void listen(int backlog) override;
- std::tuple<std::optional<int>, std::span<std::byte>>
- accept(std::span<std::byte> sockaddr) override;
- void setsockopt(SockLevel level, SockOpt optname,
- std::span<const std::byte> opt) override;
- int ioctl(unsigned long id, void* data) override;
- int constIoctl(unsigned long id, void* data) const override;
- void fcntlSetfd(FdFlags flags) override;
- FdFlags fcntlGetfd() const override;
- void fcntlSetfl(FileFlags flags) override;
- FileFlags fcntlGetfl() const override;
-
- protected:
- std::span<std::byte> mmap(std::span<std::byte> window, ProtFlags prot,
- MMapFlags flags, off_t offset) override;
- void munmap(std::span<std::byte> window) override;
-};
-
-} // namespace fd
-
-using fd::FdImpl;
-
-} // namespace stdplus
diff --git a/src/stdplus/fd/intf.hpp b/src/stdplus/fd/intf.hpp
deleted file mode 100644
index 4d9553d..0000000
--- a/src/stdplus/fd/intf.hpp
+++ /dev/null
@@ -1,157 +0,0 @@
-#pragma once
-#include <cstddef>
-#include <fcntl.h>
-#include <optional>
-#include <span>
-#include <stdplus/flags.hpp>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <tuple>
-
-namespace stdplus
-{
-namespace fd
-{
-
-enum class RecvFlag : int
-{
- DontWait = MSG_DONTWAIT,
- ErrQueue = MSG_ERRQUEUE,
- OutOfBounds = MSG_OOB,
- Peek = MSG_PEEK,
- Trunc = MSG_TRUNC,
- WaitAll = MSG_WAITALL,
-};
-using RecvFlags = BitFlags<int, RecvFlag>;
-
-enum class SendFlag : int
-{
- Confirm = MSG_CONFIRM,
- DontRoute = MSG_DONTROUTE,
- DontWait = MSG_DONTWAIT,
- EndOfRecord = MSG_EOR,
- More = MSG_MORE,
- NoSignal = MSG_NOSIGNAL,
- OutOfBounds = MSG_OOB,
-};
-using SendFlags = BitFlags<int, SendFlag>;
-
-enum class Whence : int
-{
- Set = SEEK_SET,
- Cur = SEEK_CUR,
- End = SEEK_END,
-};
-
-enum class SockLevel : int
-{
- Socket = SOL_SOCKET,
-};
-
-enum class SockOpt : int
-{
- Debug = SO_DEBUG,
- Broadcast = SO_BROADCAST,
- ReuseAddr = SO_REUSEADDR,
- KeepAlive = SO_KEEPALIVE,
- Linger = SO_LINGER,
- OOBInline = SO_OOBINLINE,
- SendBuf = SO_SNDBUF,
- RecvBuf = SO_RCVBUF,
- DontRoute = SO_DONTROUTE,
- RecvLowWait = SO_RCVLOWAT,
- RecvTimeout = SO_RCVTIMEO,
- SendLowWait = SO_SNDLOWAT,
- SendTimeout = SO_SNDTIMEO,
-};
-
-enum class FdFlag : int
-{
- CloseOnExec = FD_CLOEXEC,
-};
-using FdFlags = BitFlags<int, FdFlag>;
-
-enum class FileFlag : int
-{
- Append = O_APPEND,
- Async = O_ASYNC,
- Direct = O_DIRECT,
- NoAtime = O_NOATIME,
- NonBlock = O_NONBLOCK,
-};
-using FileFlags = BitFlags<int, FileFlag>;
-
-enum class ProtFlag : int
-{
- Exec = PROT_EXEC,
- Read = PROT_READ,
- Write = PROT_WRITE,
-};
-using ProtFlags = BitFlags<int, ProtFlag>;
-
-enum class MMapAccess : int
-{
- Shared = MAP_SHARED,
- Private = MAP_PRIVATE,
-};
-
-enum class MMapFlag : int
-{
-};
-
-class MMapFlags : public BitFlags<int, MMapFlag>
-{
- public:
- inline MMapFlags(MMapAccess access) :
- BitFlags<int, MMapFlag>(static_cast<int>(access))
- {
- }
-
- inline MMapFlags(BitFlags<int, MMapFlag> flags) :
- BitFlags<int, MMapFlag>(flags)
- {
- }
-};
-
-class MMap;
-
-class Fd
-{
- public:
- virtual ~Fd() = default;
-
- virtual std::span<std::byte> read(std::span<std::byte> buf) = 0;
- virtual std::span<std::byte> recv(std::span<std::byte> buf,
- RecvFlags flags) = 0;
- virtual std::span<const std::byte>
- write(std::span<const std::byte> data) = 0;
- virtual std::span<const std::byte> send(std::span<const std::byte> data,
- SendFlags flags) = 0;
- virtual size_t lseek(off_t offset, Whence whence) = 0;
- virtual void truncate(off_t size) = 0;
- virtual void bind(std::span<const std::byte> sockaddr) = 0;
- virtual void listen(int backlog) = 0;
- virtual std::tuple<std::optional<int>, std::span<std::byte>>
- accept(std::span<std::byte> sockaddr) = 0;
- virtual void setsockopt(SockLevel level, SockOpt optname,
- std::span<const std::byte> opt) = 0;
- virtual int ioctl(unsigned long id, void* data) = 0;
- virtual int constIoctl(unsigned long id, void* data) const = 0;
- virtual void fcntlSetfd(FdFlags flags) = 0;
- virtual FdFlags fcntlGetfd() const = 0;
- virtual void fcntlSetfl(FileFlags flags) = 0;
- virtual FileFlags fcntlGetfl() const = 0;
-
- protected:
- virtual std::span<std::byte> mmap(std::span<std::byte> window,
- ProtFlags prot, MMapFlags flags,
- off_t offset) = 0;
- virtual void munmap(std::span<std::byte> window) = 0;
- friend class MMap;
-};
-
-} // namespace fd
-
-using fd::Fd;
-
-} // namespace stdplus
diff --git a/src/stdplus/fd/managed.hpp b/src/stdplus/fd/managed.hpp
deleted file mode 100644
index a188421..0000000
--- a/src/stdplus/fd/managed.hpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#pragma once
-#include <stdplus/fd/impl.hpp>
-#include <stdplus/handle/managed.hpp>
-
-namespace stdplus
-{
-namespace fd
-{
-namespace detail
-{
-
-/** @brief Closes the file descriptor when dropping an Fd handle
- *
- * @param[in] fd - File descriptor to close
- */
-void drop(int&& fd);
-
-using ManagedFdHandle = Managed<int>::Handle<drop>;
-
-} // namespace detail
-
-class DupableFd;
-
-/** @class ManagedFd
- * @brief Holds references to unique, non-dupable file descriptors
- * @details Provides RAII semantics for file descriptors
- */
-class ManagedFd : public FdImpl
-{
- public:
- /** @brief Constructs an empty file descriptor */
- ManagedFd() noexcept;
-
- /** @brief Holds the input file descriptor
- * Becomes the sole owner of the file descriptor
- *
- * @param[in] fd - File descriptor to hold
- */
- explicit ManagedFd(int&& fd);
-
- ManagedFd(DupableFd&& other) noexcept;
- ManagedFd(const DupableFd& other);
- ManagedFd& operator=(DupableFd&& other) noexcept;
- ManagedFd& operator=(const DupableFd& other);
-
- /** @brief Unmanages the file descriptor and returns the value with
- * ownership to the caller.
- *
- * @return The file descriptor number
- */
- [[nodiscard]] int release();
-
- int get() const override;
-
- private:
- detail::ManagedFdHandle handle;
-};
-
-} // namespace fd
-
-using fd::ManagedFd;
-
-} // namespace stdplus
diff --git a/src/stdplus/fd/mmap.hpp b/src/stdplus/fd/mmap.hpp
deleted file mode 100644
index 06b7944..0000000
--- a/src/stdplus/fd/mmap.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-#include <cstddef>
-#include <functional>
-#include <span>
-#include <stdplus/fd/intf.hpp>
-#include <stdplus/handle/managed.hpp>
-
-namespace stdplus
-{
-namespace fd
-{
-
-class MMap
-{
- public:
- inline MMap(Fd& fd, size_t window_size, ProtFlags prot, MMapFlags flags,
- off_t offset) :
- MMap(
- fd,
- std::span<std::byte>{static_cast<std::byte*>(nullptr), window_size},
- prot, flags, offset)
- {
- }
- MMap(Fd& fd, std::span<std::byte> window, ProtFlags prot, MMapFlags flags,
- off_t offset);
-
- std::span<std::byte> get() const;
-
- private:
- static void drop(std::span<std::byte>&&, std::reference_wrapper<Fd>&);
- Managed<std::span<std::byte>, std::reference_wrapper<Fd>>::Handle<drop>
- mapping;
-};
-
-} // namespace fd
-} // namespace stdplus
diff --git a/src/stdplus/fd/ops.hpp b/src/stdplus/fd/ops.hpp
deleted file mode 100644
index 8f3735b..0000000
--- a/src/stdplus/fd/ops.hpp
+++ /dev/null
@@ -1,179 +0,0 @@
-#pragma once
-#include <span>
-#include <stdexcept>
-#include <stdplus/fd/dupable.hpp>
-#include <stdplus/fd/intf.hpp>
-#include <stdplus/raw.hpp>
-#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);
-
-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>
-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 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);
-}
-
-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);
-}
-
-template <typename SockAddr>
-inline void bind(Fd& fd, SockAddr&& sockaddr)
-{
- return fd.bind(raw::asSpan<std::byte>(sockaddr));
-}
-
-inline void listen(Fd& fd, int backlog)
-{
- return fd.listen(backlog);
-}
-
-template <typename SockAddr>
-inline std::optional<stdplus::DupableFd> accept(Fd& fd, SockAddr&& sockaddr)
-{
- auto ret = fd.accept(raw::asSpan<std::byte>(sockaddr));
- if (!std::get<0>(ret))
- {
- return std::nullopt;
- }
- if (std::get<1>(ret).size() != sizeof(sockaddr))
- {
- throw std::runtime_error("Invalid sockaddr type for accept");
- }
- return stdplus::DupableFd(std::move(*std::get<0>(ret)));
-}
-
-inline std::optional<stdplus::DupableFd> accept(Fd& fd)
-{
- auto ret = std::get<0>(fd.accept(std::span<std::byte>{}));
- if (!ret)
- {
- return std::nullopt;
- }
- return stdplus::DupableFd(std::move(*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
diff --git a/src/stdplus/flags.hpp b/src/stdplus/flags.hpp
deleted file mode 100644
index 047c776..0000000
--- a/src/stdplus/flags.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-#include <utility>
-
-namespace stdplus
-{
-
-template <typename Int, typename Flag = Int>
-class BitFlags
-{
- public:
- inline explicit BitFlags(Int val = 0) noexcept : val(val)
- {
- }
-
- inline BitFlags& set(Flag flag) & noexcept
- {
- val |= static_cast<Int>(flag);
- return *this;
- }
- inline BitFlags&& set(Flag flag) && noexcept
- {
- val |= static_cast<Int>(flag);
- return std::move(*this);
- }
-
- inline BitFlags& unset(Flag flag) & noexcept
- {
- val &= ~static_cast<Int>(flag);
- return *this;
- }
- inline BitFlags&& unset(Flag flag) && noexcept
- {
- val &= ~static_cast<Int>(flag);
- return std::move(*this);
- }
-
- explicit inline operator Int() const noexcept
- {
- return val;
- }
-
- private:
- Int val;
-};
-
-} // namespace stdplus
diff --git a/src/stdplus/handle/copyable.hpp b/src/stdplus/handle/copyable.hpp
deleted file mode 100644
index 86fc8b7..0000000
--- a/src/stdplus/handle/copyable.hpp
+++ /dev/null
@@ -1,153 +0,0 @@
-#pragma once
-#include <optional>
-#include <stdplus/handle/managed.hpp>
-#include <type_traits>
-#include <utility>
-
-namespace stdplus
-{
-
-/** @brief Similar to the Managed Handle, but also allows for copying
- * and performs an operation during that copy.
- */
-template <typename T, typename... As>
-struct Copyable
-{
- template <typename Drop, typename Ref>
- class HandleF : public Managed<T, As...>::template HandleF<Drop>
- {
- protected:
- static constexpr bool ref_noexcept =
- noexcept(Ref()(std::declval<T>(), std::declval<As&>()...));
-
- public:
- using MHandleF = typename Managed<T, As...>::template HandleF<Drop>;
-
- /** @brief Creates a handle referencing the object
- *
- * @param[in] maybeV - Optional object being managed
- */
- template <typename... Vs>
- constexpr explicit HandleF(const std::optional<T>& maybeV, Vs&&... vs) noexcept(
- noexcept(MHandleF(std::nullopt, std::declval<Vs>()...)) && noexcept(
- std::declval<HandleF>().reset(
- std::declval<const std::optional<T>&>()))) :
- MHandleF(std::nullopt, std::forward<Vs>(vs)...)
- {
- reset(maybeV);
- }
- template <typename... Vs>
- constexpr explicit HandleF(const T& maybeV, Vs&&... vs) noexcept(
- noexcept(MHandleF(std::nullopt, std::declval<Vs>()...)) && noexcept(
- std::declval<HandleF>().reset(std::declval<const T&>()))) :
- MHandleF(std::nullopt, std::forward<Vs>(vs)...)
- {
- reset(maybeV);
- }
-
- /** @brief Creates a handle owning the object
- *
- * @param[in] maybeV - Maybe the object being managed
- */
- template <typename... Vs>
- constexpr explicit HandleF(
- std::optional<T>&& maybeV,
- Vs&&... vs) noexcept(noexcept(MHandleF(std::
- declval<std::optional<
- T>&&>(),
- std::declval<Vs>()...))) :
- MHandleF(std::move(maybeV), std::forward<Vs>(vs)...)
- {
- }
- template <typename... Vs>
- constexpr explicit HandleF(T&& maybeV, Vs&&... vs) noexcept(
- noexcept(MHandleF(std::declval<T&&>(), std::declval<Vs>()...))) :
- MHandleF(std::move(maybeV), std::forward<Vs>(vs)...)
- {
- }
-
- constexpr HandleF(const HandleF& other) noexcept(noexcept(MHandleF(
- std::nullopt,
- std::declval<const std::tuple<
- As...>&>())) && noexcept(std::declval<HandleF>()
- .reset(std::declval<
- const std::optional<
- T>&>()))) :
- MHandleF(std::nullopt, other.as)
- {
- reset(other.maybe_value());
- }
-
- constexpr HandleF(HandleF&& other) noexcept(
- std::is_nothrow_move_constructible_v<MHandleF>) :
- MHandleF(std::move(other))
- {
- }
-
- constexpr HandleF& operator=(const HandleF& other) noexcept(
- noexcept(std::declval<HandleF>().reset()) &&
- std::is_nothrow_copy_constructible_v<std::tuple<As...>>&& noexcept(
- std::declval<HandleF>().reset(
- std::declval<const std::optional<T>&>())))
- {
- if (this != &other)
- {
- reset();
- this->as = other.as;
- reset(other.maybe_value());
- }
- return *this;
- }
-
- constexpr HandleF& operator=(HandleF&& other) noexcept(
- std::is_nothrow_move_assignable_v<MHandleF>)
- {
- MHandleF::operator=(std::move(other));
- return *this;
- }
-
- using MHandleF::reset;
- constexpr void reset(const std::optional<T>& maybeV) noexcept(
- ref_noexcept&& noexcept(std::declval<HandleF>().reset(
- std::declval<T>())) && noexcept(std::declval<HandleF>()
- .reset()))
- {
- if (maybeV)
- {
- reset(doRef(*maybeV, std::index_sequence_for<As...>()));
- }
- else
- {
- reset();
- }
- }
- constexpr void reset(const T& maybeV) noexcept(ref_noexcept&& noexcept(
- std::declval<HandleF>().reset(std::declval<T>())))
- {
- reset(doRef(maybeV, std::index_sequence_for<As...>()));
- }
-
- private:
- template <size_t... Indices>
- T doRef(const T& v,
- std::index_sequence<Indices...>) noexcept(ref_noexcept)
- {
- return Ref()(v, std::get<Indices>(this->as)...);
- }
- };
-
- template <T (*ref)(const T&, As&...)>
- struct Reffer
- {
- T operator()(const T& t, As&... as) noexcept(noexcept(ref))
- {
- return ref(t, as...);
- }
- };
-
- template <void (*drop)(T&&, As&...), T (*ref)(const T&, As&...)>
- using Handle = HandleF<typename Managed<T, As...>::template Dropper<drop>,
- Reffer<ref>>;
-};
-
-} // namespace stdplus
diff --git a/src/stdplus/handle/managed.hpp b/src/stdplus/handle/managed.hpp
deleted file mode 100644
index 08cac4f..0000000
--- a/src/stdplus/handle/managed.hpp
+++ /dev/null
@@ -1,249 +0,0 @@
-#pragma once
-#include <cstdlib>
-#include <optional>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-namespace stdplus
-{
-
-/** @brief An RAII handle which takes an object and calls a user specified
- * function on the object when it should be cleaned up.
- * @details This is useful for adding RAII semantics to non-RAII things like
- * file descriptors, or c structs allocated with special routines.
- * We could make a simple file descriptor wrapper that is
- * automatically closed:
- *
- * struct CloseFd {
- * void operator()(int&& fd) { close(fd); }
- * };
- * using Fd = Managed<int>::HandleF<closefd>;
- *
- * void some_func()
- * {
- * Fd fd(open("somefile", 0));
- * char buf[4096];
- * int amt = read(*fd, buf, sizeof(buf));
- * printf("%.*s\n", amt, data);
- * }
- */
-template <typename T, typename... As>
-struct Managed
-{
-
- template <typename Drop>
- class HandleF
- {
- protected:
- static constexpr bool drop_noexcept =
- noexcept(Drop()(std::declval<T>(), std::declval<As&>()...));
-
- public:
- /** @brief Creates a handle owning the object
- *
- * @param[in] maybeV - Maybe the object being managed
- */
- template <typename... Vs>
- constexpr explicit HandleF(std::optional<T>&& maybeV, Vs&&... vs) noexcept(
- std::is_nothrow_move_constructible_v<std::optional<T>>&& noexcept(
- std::tuple<As...>(std::declval<Vs>()...))) :
- as(std::forward<Vs>(vs)...),
- maybeT(std::move(maybeV))
- {
- }
- template <typename... Vs>
- constexpr explicit HandleF(T&& maybeV, Vs&&... vs) noexcept(
- std::is_nothrow_move_constructible_v<std::optional<T>>&& noexcept(
- std::tuple<As...>(std::declval<Vs>()...))) :
- as(std::forward<Vs>(vs)...),
- maybeT(std::move(maybeV))
- {
- }
-
- HandleF(const HandleF& other) = delete;
- HandleF& operator=(const HandleF& other) = delete;
-
- constexpr HandleF(HandleF&& other) noexcept(
- std::is_nothrow_move_constructible_v<std::tuple<As...>>&&
- std::is_nothrow_move_constructible_v<std::optional<T>>) :
- as(std::move(other.as)),
- maybeT(std::move(other.maybeT))
- {
- other.maybeT = std::nullopt;
- }
-
- constexpr HandleF& operator=(HandleF&& other) noexcept(
- std::is_nothrow_move_assignable_v<std::tuple<As...>>&& noexcept(
- std::declval<HandleF>().reset(
- std::declval<std::optional<T>>())))
- {
- if (this != &other)
- {
- reset(std::move(other.maybeT));
- as = std::move(other.as);
- other.maybeT = std::nullopt;
- }
- return *this;
- }
-
- virtual ~HandleF() noexcept(
- std::is_nothrow_destructible_v<std::tuple<As...>>&&
- std::is_nothrow_destructible_v<std::optional<T>>&& noexcept(
- std::declval<HandleF>().reset()))
- {
- reset();
- }
-
- /** @brief Gets the managed object
- *
- * @return A pointer to the object
- */
- constexpr const T* operator->() const noexcept
- {
- return &(*maybeT);
- }
-
- /** @brief Gets the managed object
- *
- * @return A reference to the object
- */
- constexpr const T& operator*() const& noexcept
- {
- return *maybeT;
- }
-
- /** @brief Determine if we are managing an object
- *
- * @return Do we currently have an object
- */
- constexpr explicit operator bool() const noexcept
- {
- return static_cast<bool>(maybeT);
- }
-
- /** @brief Determine if we are managing an object
- *
- * @return Do we currently have an object
- */
- constexpr bool has_value() const noexcept
- {
- return maybeT.has_value();
- }
-
- /** @brief Gets the managed object
- *
- * @throws std::bad_optional_access if it has no object
- * @return A reference to the managed object
- */
- constexpr const T& value() const&
- {
- return maybeT.value();
- }
-
- /** @brief Gets the managed object if it exists
- *
- * @throws std::bad_optional_access if it has no object
- * @return A reference to the managed object
- */
- constexpr const std::optional<T>& maybe_value() const& noexcept
- {
- return maybeT;
- }
-
- /** @brief Resets the managed value to a new value
- * The container takes ownership of the value
- *
- * @param[in] maybeV - Maybe the new value
- */
- constexpr void reset(std::optional<T>&& maybeV) noexcept(
- drop_noexcept&& std::is_nothrow_move_assignable_v<std::optional<T>>)
- {
- maybeDrop(std::index_sequence_for<As...>());
- maybeT = std::move(maybeV);
- }
- constexpr void reset(T&& maybeV) noexcept(
- drop_noexcept&& std::is_nothrow_move_assignable_v<std::optional<T>>)
- {
- maybeDrop(std::index_sequence_for<As...>());
- maybeT = std::move(maybeV);
- }
-
- /** @brief A shorthand reset function for convenience
- * Same as calling reset(std::nullopt)
- */
- constexpr void reset() noexcept(drop_noexcept)
- {
- reset(std::nullopt);
- }
-
- /** @brief Releases the managed value and transfers ownership
- * to the caller.
- *
- * @throws std::bad_optional_access if it has no object
- * @return The value that was managed
- */
- [[nodiscard]] constexpr T release()
- {
- T ret = std::move(maybeT.value());
- maybeT = std::nullopt;
- return ret;
- }
-
- /** @brief Releases the managed value and transfers ownership
- * to the caller.
- *
- * @return Maybe the value that was managed
- */
- [[nodiscard]] constexpr std::optional<T> maybe_release() noexcept
- {
- std::optional<T> ret = std::move(maybeT);
- maybeT = std::nullopt;
- return ret;
- }
-
- /** @brief Reference the contained data
- *
- * @return A reference to the contained data
- */
- constexpr const std::tuple<As...>& data() const noexcept
- {
- return as;
- }
- constexpr std::tuple<As...>& data() noexcept
- {
- return as;
- }
-
- protected:
- /* Hold the data parameterized for this container */
- std::tuple<As...> as;
-
- private:
- /* Stores the managed object if we have one */
- std::optional<T> maybeT;
-
- template <size_t... Indices>
- void maybeDrop(std::index_sequence<Indices...>) noexcept(drop_noexcept)
- {
- if (maybeT)
- {
- Drop()(std::move(*maybeT), std::get<Indices>(as)...);
- }
- }
- };
-
- template <void (*drop)(T&&, As&...)>
- struct Dropper
- {
- void operator()(T&& t, As&... as) noexcept(noexcept(drop))
- {
- drop(std::move(t), as...);
- }
- };
-
- template <void (*drop)(T&&, As&...)>
- using Handle = HandleF<Dropper<drop>>;
-};
-
-} // namespace stdplus
diff --git a/src/stdplus/io_uring.hpp b/src/stdplus/io_uring.hpp
deleted file mode 100644
index 6572e04..0000000
--- a/src/stdplus/io_uring.hpp
+++ /dev/null
@@ -1,140 +0,0 @@
-#pragma once
-
-#include <liburing.h>
-
-#include <stdplus/fd/managed.hpp>
-#include <stdplus/handle/managed.hpp>
-
-#include <chrono>
-#include <optional>
-#include <vector>
-
-namespace stdplus
-{
-
-/** @brief Converts a chrono duration into a kernel duration */
-__kernel_timespec chronoToKTS(std::chrono::nanoseconds t) noexcept;
-
-class IoUring
-{
- public:
- struct CQEHandler
- {
- CQEHandler() = default;
- CQEHandler(CQEHandler&&) = delete;
- CQEHandler& operator=(CQEHandler&&) = delete;
- CQEHandler(const CQEHandler&) = delete;
- CQEHandler& operator=(const CQEHandler&) = delete;
- virtual ~CQEHandler() = default;
-
- virtual void handleCQE(io_uring_cqe&) noexcept = 0;
- };
-
- class FileHandle
- {
- public:
- inline operator int() const
- {
- return *slot;
- }
-
- private:
- explicit FileHandle(unsigned slot, IoUring& ring);
-
- static void drop(unsigned&& slot, IoUring*& ring);
-
- Managed<unsigned, IoUring*>::Handle<drop> slot;
-
- friend class IoUring;
- };
-
- explicit IoUring(size_t queue_size = 10, int flags = 0);
- explicit IoUring(size_t queue_size, io_uring_params& params);
-
- IoUring(IoUring&&) = delete;
- IoUring& operator=(IoUring&&) = delete;
- IoUring(const IoUring&) = delete;
- IoUring& operator=(const IoUring&) = delete;
- ~IoUring();
-
- /** @brief Reserves an additional number of file descriptor slots
- *
- * @param[in] num - The number of slots to register
- * @throws std::system_error if the allocation fails
- */
- void reserveFiles(size_t num);
-
- /** @brief Registers a file descriptor with a slot on the ring
- *
- * @param[in] fd - The file descriptor to register
- * @throws std::system_error if the allocation fails
- * @return A handle to the registered file on the ring
- */
- [[nodiscard]] FileHandle registerFile(int fd);
-
- /** @brief Get current list of files descriptors registered on the ring.
- * Note this view potentially expires when registrations change. */
- inline std::span<const int> getFiles() const noexcept
- {
- return files;
- }
-
- /** @brief Gets an unused SQE from the ring
- *
- * @throws std::system_error if the allocation fails
- * @return An SQE on the ring
- */
- io_uring_sqe& getSQE();
-
- /** @brief Associates the SQE with a user provided callback handler
- *
- * @param[in] sqe - The SQE that we want to register
- * @param[in] h - The handler which will be run when the CQE comes back
- */
- void setHandler(io_uring_sqe& sqe, CQEHandler* h) noexcept;
-
- /** @brief Cancels the outstanding request associated with a handler
- *
- * @param[in] h - The handler associated with the request
- */
- void cancelHandler(CQEHandler& h);
-
- /** @brief Submits all outstanding SQEs to the kernel
- *
- * @throws std::system_error if the submission fails
- */
- void submit();
-
- /** @brief Non-blocking process all outstanding CQEs */
- void process() noexcept;
-
- /** @brief Waits for new CQEs to become available */
- void wait();
- void wait(std::chrono::nanoseconds timeout);
-
- /** @brief Returns the EventFD associated with the ring
- * A new descriptor is created if it does not yet exist
- *
- * @throws std::system_error if constructing the event fd fails
- * @return A reference to the descriptor
- */
- stdplus::ManagedFd& getEventFd();
-
- /** @brief Non-blocking process all outstanding eventFd events
- * Should be used instead of process() to clear eventFd events.
- */
- void processEvents();
-
- private:
- io_uring ring;
- std::optional<stdplus::ManagedFd> event_fd;
- std::vector<CQEHandler*> handlers;
- std::vector<int> files;
- size_t filesAllocated = 0;
-
- void dropHandler(CQEHandler* h, io_uring_cqe& cqe) noexcept;
- void setFile(unsigned slot, int fd) noexcept;
- void updateFile(unsigned slot, int fd);
-};
-
-} // namespace stdplus
diff --git a/src/stdplus/raw.hpp b/src/stdplus/raw.hpp
deleted file mode 100644
index 7da4b92..0000000
--- a/src/stdplus/raw.hpp
+++ /dev/null
@@ -1,203 +0,0 @@
-#pragma once
-#include <fmt/format.h>
-#include <span>
-#include <stdexcept>
-#include <string_view>
-#include <type_traits>
-
-namespace stdplus
-{
-namespace raw
-{
-
-namespace detail
-{
-
-/** @brief Gets the datatype referenced in a container
- */
-template <typename Container>
-using dataType = std::remove_pointer_t<decltype(std::data(
- std::declval<std::add_lvalue_reference_t<Container>>()))>;
-
-/** @brief Gets the sizetype referenced in a container
- */
-template <typename Container>
-using sizeType =
- decltype(std::size(std::declval<std::add_lvalue_reference_t<Container>>()));
-
-/** @brief Determines if the container holds trivially copyable data
- */
-template <typename Container>
-inline constexpr bool trivialContainer =
- std::is_trivially_copyable_v<dataType<Container>>;
-
-/** @brief Adds const to A if B is const
- */
-template <typename A, typename B>
-using copyConst =
- std::conditional_t<std::is_const_v<B>, std::add_const_t<A>, A>;
-
-/** @brief Determines if a type is a container of data
- */
-template <typename, typename = void>
-inline constexpr bool hasData = false;
-template <typename T>
-inline constexpr bool hasData<T, std::void_t<dataType<T>, sizeType<T>>> = true;
-
-} // namespace detail
-
-/** @brief Compares two containers to see if their raw bytes are equal
- *
- * @param[in] a - The first container
- * @param[in] b - The second container
- * @return True if they are the same, false otherwise
- */
-template <typename A, typename B>
-bool equal(const A& a, const B& b) noexcept
-{
- static_assert(std::is_trivially_copyable_v<A>);
- static_assert(std::is_trivially_copyable_v<B>);
- static_assert(sizeof(A) == sizeof(B));
- return memcmp(&a, &b, sizeof(A)) == 0;
-}
-
-/** @brief Copies data from a buffer into a copyable type
- *
- * @param[in] data - The data buffer being copied from
- * @return The copyable type with data populated
- */
-template <typename T, typename Container>
-T copyFrom(const Container& c)
-{
- static_assert(std::is_trivially_copyable_v<T>);
- static_assert(detail::trivialContainer<Container>);
- T ret;
- const size_t bytes = std::size(c) * sizeof(*std::data(c));
- if (bytes < sizeof(ret))
- {
- throw std::runtime_error(
- fmt::format("CopyFrom: {} < {}", bytes, sizeof(ret)));
- }
- std::memcpy(&ret, std::data(c), sizeof(ret));
- return ret;
-}
-
-/** @brief References the data from a buffer if aligned
- *
- * @param[in] data - The data buffer being referenced
- * @return The reference to the data in the new type
- */
-template <typename T, typename Container,
- typename Tp = detail::copyConst<T, detail::dataType<Container>>>
-Tp& refFrom(Container&& c)
-{
- static_assert(std::is_trivially_copyable_v<Tp>);
- static_assert(detail::trivialContainer<Container>);
- static_assert(sizeof(*std::data(c)) % alignof(Tp) == 0);
- const size_t bytes = std::size(c) * sizeof(*std::data(c));
- if (bytes < sizeof(Tp))
- {
- throw std::runtime_error(
- fmt::format("RefFrom: {} < {}", bytes, sizeof(Tp)));
- }
- return *reinterpret_cast<Tp*>(std::data(c));
-}
-
-/** @brief Extracts data from a buffer into a copyable type
- * Updates the data buffer to show that data was removed
- *
- * @param[in,out] data - The data buffer being extracted from
- * @return The copyable type with data populated
- */
-template <typename T, typename CharT>
-T extract(std::basic_string_view<CharT>& data)
-{
- T ret = copyFrom<T>(data);
- static_assert(sizeof(T) % sizeof(CharT) == 0);
- data.remove_prefix(sizeof(T) / sizeof(CharT));
- return ret;
-}
-template <typename T, typename IntT,
- typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>>
-T extract(std::span<IntT>& data)
-{
- T ret = copyFrom<T>(data);
- static_assert(sizeof(T) % sizeof(IntT) == 0);
- data = data.subspan(sizeof(T) / sizeof(IntT));
- return ret;
-}
-
-/** @brief Extracts data from a buffer as a reference if aligned
- * Updates the data buffer to show that data was removed
- *
- * @param[in,out] data - The data buffer being extracted from
- * @return A reference to the data
- */
-template <typename T, typename CharT>
-const T& extractRef(std::basic_string_view<CharT>& data)
-{
- const T& ret = refFrom<T>(data);
- static_assert(sizeof(T) % sizeof(CharT) == 0);
- data.remove_prefix(sizeof(T) / sizeof(CharT));
- return ret;
-}
-template <typename T, typename IntT,
- typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
- typename Tp = detail::copyConst<T, IntT>>
-Tp& extractRef(std::span<IntT>& data)
-{
- Tp& ret = refFrom<Tp>(data);
- static_assert(sizeof(Tp) % sizeof(IntT) == 0);
- data = data.subspan(sizeof(Tp) / sizeof(IntT));
- return ret;
-}
-
-/** @brief Returns the std::span referencing the data of the raw trivial type
- * or of trivial types in a contiguous container.
- *
- * @param[in] t - The trivial raw data
- * @return A view over the input with the given output integral type
- */
-template <typename CharT, typename T>
-std::enable_if_t<!detail::hasData<T>, std::basic_string_view<CharT>>
- asView(const T& t) noexcept
-{
- static_assert(std::is_trivially_copyable_v<T>);
- static_assert(sizeof(T) % sizeof(CharT) == 0);
- return {reinterpret_cast<const CharT*>(&t), sizeof(T) / sizeof(CharT)};
-}
-
-template <typename CharT, typename Container>
-std::enable_if_t<detail::hasData<Container>, std::basic_string_view<CharT>>
- asView(const Container& c) noexcept
-{
- static_assert(detail::trivialContainer<Container>);
- static_assert(sizeof(*std::data(c)) % sizeof(CharT) == 0);
- return {reinterpret_cast<const CharT*>(std::data(c)),
- std::size(c) * sizeof(*std::data(c)) / sizeof(CharT)};
-}
-
-template <typename IntT, typename T,
- typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
- typename = std::enable_if_t<!detail::hasData<T>>,
- typename IntTp = detail::copyConst<IntT, T>>
-std::span<IntTp> asSpan(T& t) noexcept
-{
- static_assert(std::is_trivially_copyable_v<T>);
- static_assert(sizeof(T) % sizeof(IntTp) == 0);
- return {reinterpret_cast<IntTp*>(&t), sizeof(T) / sizeof(IntTp)};
-}
-template <typename IntT, typename Container,
- typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
- typename = std::enable_if_t<detail::hasData<Container>>,
- typename IntTp = detail::copyConst<IntT, detail::dataType<Container>>>
-std::span<IntTp> asSpan(Container&& c) noexcept
-{
- static_assert(detail::trivialContainer<Container>);
- static_assert(sizeof(*std::data(c)) % sizeof(IntTp) == 0);
- return {reinterpret_cast<IntTp*>(std::data(c)),
- std::size(c) * sizeof(*std::data(c)) / sizeof(IntTp)};
-}
-
-} // namespace raw
-} // namespace stdplus
diff --git a/src/stdplus/signal.hpp b/src/stdplus/signal.hpp
deleted file mode 100644
index 465181b..0000000
--- a/src/stdplus/signal.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-namespace stdplus
-{
-namespace signal
-{
-
-/** @brief Blocks the signal from being handled by the designated
- * sigaction. If the signal is already blocked this does nothing.
- *
- * @param[in] signum - The int representing the signal to block
- * @throws std::system_error if any underlying error occurs.
- */
-void block(int signum);
-
-} // namespace signal
-} // namespace stdplus
diff --git a/src/stdplus/util/cexec.hpp b/src/stdplus/util/cexec.hpp
deleted file mode 100644
index daf402c..0000000
--- a/src/stdplus/util/cexec.hpp
+++ /dev/null
@@ -1,227 +0,0 @@
-#pragma once
-#include <functional>
-#include <string>
-#include <system_error>
-#include <type_traits>
-#include <utility>
-
-/** @brief Wraps common c style error handling for exception throwing
- * This requires the callee to set errno on error.
- * @details We often have a pattern in our code for checking errors and
- * propagating up exceptions:
- *
- * int c_call(const char* path);
- *
- * int our_cpp_call(const char* path)
- * {
- * int r = c_call(path);
- * if (r < 0)
- * {
- * throw std::system_error(errno, std::generic_category(),
- * "our msg");
- * }
- * return r;
- * }
- *
- * To make that more succinct, we can use CHECK_ERRNO:
- *
- * int our_cpp_call(const char* path)
- * {
- * return CHECK_ERRNO(c_call(path), "our msg");
- * }
- *
- * @param[in] expr - The expression returning an errno value
- * @param[in] error_handler - Passed to the doError function
- * @throws std::system_error (depends on error_handler) for an error case
- * @return A successful return value based on the function type
- */
-#define CHECK_ERRNO(expr, error_handler) \
- [&](auto check_errno_ret) { \
- if constexpr (::std::is_pointer_v<decltype(check_errno_ret)>) \
- { \
- if (check_errno_ret == nullptr) \
- ::stdplus::util::doError(errno, (error_handler)); \
- } \
- else if constexpr (::std::is_signed_v<decltype(check_errno_ret)>) \
- { \
- if (check_errno_ret < 0) \
- ::stdplus::util::doError(errno, (error_handler)); \
- } \
- else \
- { \
- static_assert(::std::is_same_v<decltype(check_errno_ret), int>, \
- "Unimplemented check routine"); \
- } \
- return check_errno_ret; \
- }((expr))
-
-/** @brief Wraps common c style error handling for exception throwing
- * This requires the callee to provide error information in -r.
- * See CHECK_ERRNO() for details.
- *
- * @param[in] expr - The expression returning an negative error value
- * @param[in] error_handler - Passed to the doError function
- * @throws std::system_error (depends on error_handler) for an error case
- * @return A successful return value based on the function type
- */
-#define CHECK_RET(expr, error_handler) \
- [&](auto check_ret_ret) { \
- if constexpr (::std::is_signed_v<decltype(check_ret_ret)>) \
- { \
- if (check_ret_ret < 0) \
- ::stdplus::util::doError(-check_ret_ret, (error_handler)); \
- } \
- else \
- { \
- static_assert(::std::is_same_v<decltype(check_ret_ret), int>, \
- "Unimplemented check routine"); \
- } \
- return check_ret_ret; \
- }((expr))
-
-namespace stdplus
-{
-namespace util
-{
-
-/** @brief Common pattern used by default for constructing a system exception
- * @details Most libc or system calls will want to return a generic
- * system_error when detecting an error in a call. This function
- * creates that error from the errno and message.
- *
- * @param[in] error -
- * @param[in] msg -
- * @return The exception passed to a `throw` call.
- */
-inline auto makeSystemError(int error, const char* msg)
-{
- return std::system_error(error, std::generic_category(), msg);
-}
-
-/** @brief Turns errors into exceptions for the given error handler
- *
- * @param[in] error - The numeric system error code
- * @param[in] msg - The string used to describe the error
- * @throws A system exception with the given error and msg
- */
-inline void doError(int error, const char* msg)
-{
- throw makeSystemError(error, msg);
-}
-inline void doError(int error, const std::string& msg)
-{
- throw makeSystemError(error, msg.c_str());
-}
-
-/** @brief Turns errors into exceptions for the given error handler
- *
- * @param[in] error - The numeric system error code
- * @param[in] fun - the function used to throw the error
- */
-template <typename Fun>
-inline std::enable_if_t<std::is_invocable_v<Fun, int>, void> doError(int error,
- Fun&& fun)
-{
- fun(error);
-}
-
-/** @brief Wraps common c style error handling for exception throwing
- * This requires the callee to set errno on error.
- * @details We often have a pattern in our code for checking errors and
- * propagating up exceptions:
- *
- * int c_call(const char* path);
- *
- * int our_cpp_call(const char* path)
- * {
- * int r = c_call(path);
- * if (r < 0)
- * {
- * throw std::system_error(errno, std::generic_category(),
- * "our msg");
- * }
- * return r;
- * }
- *
- * To make that more succinct, we can use callCheckErrno:
- *
- * int our_cpp_call(const char* path)
- * {
- * return callCheckErrno("our msg", c_call, path);
- * }
- *
- * @param[in] msg - The error message displayed when errno is set.
- * @param[in] func - The wrapped function we invoke
- * @param[in] args... - The arguments passed to the function
- * @throws std::system_error for an error case.
- * @return A successful return value based on the function type
- */
-template <auto(*makeError)(int, const char*) = makeSystemError,
- typename... Args>
-inline auto callCheckErrno(const char* msg, Args&&... args)
-{
- using Ret = typename std::invoke_result<Args...>::type;
-
- if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
- {
- Ret r = std::invoke(std::forward<Args>(args)...);
- if (r < 0)
- throw makeError(errno, msg);
- return r;
- }
- else if constexpr (std::is_pointer_v<Ret>)
- {
- Ret r = std::invoke(std::forward<Args>(args)...);
- if (r == nullptr)
- throw makeError(errno, msg);
- return r;
- }
- else
- {
- static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
- }
-}
-template <auto(*makeError)(int, const char*) = makeSystemError,
- typename... Args>
-inline auto callCheckErrno(const std::string& msg, Args&&... args)
-{
- return callCheckErrno(msg.c_str(), std::forward<Args>(args)...);
-}
-
-/** @brief Wraps common c style error handling for exception throwing
- * This requires the callee to provide error information in -r.
- * See callCheckErrno() for details.
- *
- * @param[in] msg - The error message displayed when errno is set.
- * @param[in] func - The wrapped function we invoke
- * @param[in] args... - The arguments passed to the function
- * @throws std::system_error for an error case.
- * @return A successful return value based on the function type
- */
-template <auto(*makeError)(int, const char*) = makeSystemError,
- typename... Args>
-inline auto callCheckRet(const char* msg, Args&&... args)
-{
- using Ret = typename std::invoke_result<Args...>::type;
-
- if constexpr (std::is_integral_v<Ret> && std::is_signed_v<Ret>)
- {
- Ret r = std::invoke(std::forward<Args>(args)...);
- if (r < 0)
- throw makeError(-r, msg);
- return r;
- }
- else
- {
- static_assert(std::is_same_v<Ret, int>, "Unimplemented check routine");
- }
-}
-template <auto(*makeError)(int, const char*) = makeSystemError,
- typename... Args>
-inline auto callCheckRet(const std::string& msg, Args&&... args)
-{
- return callCheckRet(msg.c_str(), std::forward<Args>(args)...);
-}
-
-} // namespace util
-} // namespace stdplus
diff --git a/src/stdplus/util/string.hpp b/src/stdplus/util/string.hpp
deleted file mode 100644
index fad0d7a..0000000
--- a/src/stdplus/util/string.hpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#pragma once
-#include <cstring>
-#include <string>
-#include <string_view>
-#include <utility>
-
-namespace stdplus
-{
-namespace util
-{
-namespace detail
-{
-
-template <typename... Views>
-void strAppendViews(std::string& dst, Views... views)
-{
- dst.reserve((dst.size() + ... + views.size()));
- (dst.append(views), ...);
-}
-
-} // namespace detail
-
-/** @brief Converts the string into its underlying nul-terminated c-str
- *
- * @param[in] str - The string reference
- * @return The c-str
- */
-template <typename Str, typename = std::enable_if_t<
- std::is_same_v<std::remove_cv_t<Str>, std::string>>>
-auto cStr(Str& str)
-{
- return str.data();
-}
-template <
- typename Str,
- typename = std::enable_if_t<
- std::is_pointer_v<Str> &&
- std::is_same_v<std::remove_cv_t<std::remove_pointer_t<Str>>, char>>>
-auto cStr(Str str)
-{
- return str;
-}
-
-/** @brief Appends multiple strings to the end of the destination string
- * in the most optimal way for the given inputs.
- *
- * @param[in, out] dst - The string being appended to
- * @param[in] ...strs - An arbitrary number of strings to concatenate
- */
-template <typename... Strs>
-void strAppend(std::string& dst, const Strs&... strs)
-{
- detail::strAppendViews(dst, std::string_view(strs)...);
-}
-
-/** @brief Concatenates multiple strings together in the most optimal
- * way for the given inputs.
- *
- * @param[in] ...strs - An arbitrary number of strings to concatenate
- * @return The concatenated result string
- */
-template <typename... Strs>
-std::string strCat(const Strs&... strs)
-{
- std::string ret;
- strAppend(ret, strs...);
- return ret;
-}
-template <typename... Strs>
-std::string strCat(std::string&& in, const Strs&... strs)
-{
- std::string ret = std::move(in);
- strAppend(ret, strs...);
- return ret;
-}
-
-} // namespace util
-} // namespace stdplus