summaryrefslogtreecommitdiff
path: root/libhw_generic/include/libhw/generic/io.h
diff options
context:
space:
mode:
Diffstat (limited to 'libhw_generic/include/libhw/generic/io.h')
-rw-r--r--libhw_generic/include/libhw/generic/io.h94
1 files changed, 94 insertions, 0 deletions
diff --git a/libhw_generic/include/libhw/generic/io.h b/libhw_generic/include/libhw/generic/io.h
new file mode 100644
index 0000000..a7f7378
--- /dev/null
+++ b/libhw_generic/include/libhw/generic/io.h
@@ -0,0 +1,94 @@
+/* libhw/generic/io.h - Device-independent I/O definitions
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBHW_GENERIC_IO_H_
+#define _LIBHW_GENERIC_IO_H_
+
+#include <stddef.h> /* for size_t */
+#include <sys/types.h> /* for ssize_t */
+
+#include <libobj/obj.h>
+
+/* structs ********************************************************************/
+
+#if __unix__
+#include <sys/uio.h>
+#else
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+#endif
+
+struct duplex_iovec {
+ void *iov_read_dst;
+ void *iov_write_src;
+ size_t iov_len;
+};
+
+/* basic interfaces ***********************************************************/
+
+/**
+ * Return bytes-read on success, 0 on EOF, -errno on error; a short
+ * read is *not* an error.
+ */
+#define io_reader_LO_IFACE \
+ LO_FUNC(ssize_t, readv, const struct iovec *iov, int iovcnt)
+LO_INTERFACE(io_reader)
+#define io_readv(r, iov, iovcnt) LO_CALL(r, readv, iov, iovcnt)
+#define io_read(r, buf, count) LO_CALL(r, readv, &((struct iovec){.iov_base = buf, .iov_len = count}), 1)
+
+/**
+ * Return `count` on success, -errno on error; a short write *is* an
+ * error.
+ *
+ * Writes are *not* guaranteed to be atomic, so if you have concurrent
+ * writers then you should arrange for a mutex to protect the writer.
+ */
+#define io_writer_LO_IFACE \
+ LO_FUNC(ssize_t, writev, const struct iovec *iov, int iovcnt)
+LO_INTERFACE(io_writer)
+#define io_writev(w, iov, iovcnt) LO_CALL(w, writev, iov, iovcnt)
+#define io_write(w, buf, count) LO_CALL(w, writev, &((struct iovec){.iov_base = buf, .iov_len = count}), 1)
+
+/**
+ * Return 0 on success, -errno on error.
+ */
+#define io_closer_LO_IFACE \
+ LO_FUNC(int, close)
+LO_INTERFACE(io_closer)
+#define io_close(c) LO_CALL(c, close)
+
+/**
+ * All methods return 0 on success, -errno on error.
+ */
+#define io_bidi_closer_LO_IFACE \
+ LO_NEST(io_closer) \
+ LO_FUNC(int, close_read) \
+ LO_FUNC(int, close_write)
+LO_INTERFACE(io_bidi_closer)
+#define io_close_read(c) LO_CALL(c, close_read)
+#define io_close_write(c) LO_CALL(c, close_write)
+
+/**
+ * Return bytes-read and bytes-written on success, -errno on error; a
+ * short read/write *is* an error.
+ */
+#define io_duplex_readwriter_LO_IFACE \
+ LO_FUNC(void, readwritev, const struct duplex_iovec *iov, int iovcnt)
+LO_INTERFACE(io_duplex_readwriter)
+
+#define io_readwritev(rw, iov, iovcnt) \
+ LO_CALL(rw, readwritev, iov, iovcnt)
+
+/* aggregate interfaces *******************************************************/
+
+#define io_readwriter_LO_IFACE \
+ LO_NEST(io_reader) \
+ LO_NEST(io_writer)
+LO_INTERFACE(io_readwriter)
+
+#endif /* _LIBHW_GENERIC_IO_H_ */