1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
/* libhw_generic/io.c - Utilities for device-independent I/O definitions
*
* Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libmisc/assert.h>
#include <libhw/generic/io.h>
#define IOV_ITER(ACTION) \
assert(src_cnt >= 0); \
assert(src_cnt == 0 || src); \
\
const size_t byte_end = byte_beg + byte_max_cnt; \
int j = 0; \
size_t byte_pos = 0; \
for (int i = 0; \
i < src_cnt && (byte_max_cnt == 0 || byte_pos < byte_end); \
i++) { \
size_t off = 0, len; \
if (byte_pos < byte_beg) { \
if (byte_beg - byte_pos >= src[i].iov_len) { \
byte_pos += src[i].iov_len; \
continue; \
} \
off = byte_beg-byte_pos; \
len = src[i].iov_len-off; \
byte_pos = byte_beg; \
} else { \
len = src[i].iov_len; \
} \
if (byte_max_cnt && byte_end - byte_pos < len) \
len = byte_end - byte_pos; \
do { ACTION } while (0); \
byte_pos += len; \
j++; \
}
int io_slice_cnt(const struct iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
IOV_ITER();
return j;
}
int io_duplex_slice_cnt(const struct duplex_iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
IOV_ITER();
return j;
}
void io_slice(struct iovec *dst, const struct iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
assert(src_cnt == 0 || dst);
IOV_ITER(
dst[j] = ((struct iovec){
.iov_base = src[i].iov_base+off,
.iov_len = len,
});
);
}
void io_slice_duplex(struct duplex_iovec *dst, const struct duplex_iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
assert(src_cnt == 0 || dst);
IOV_ITER(
dst[j] = ((struct duplex_iovec){
.iov_read_to = src[i].iov_read_to+off,
.iov_write_from = src[i].iov_write_from+off,
.iov_len = len,
});
);
}
void io_slice_rd_to_duplex(struct duplex_iovec *dst, const struct iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
assert(src_cnt == 0 || dst);
IOV_ITER(
dst[j] = ((struct duplex_iovec){
.iov_read_to = src[i].iov_base+off,
.iov_write_from = IOVEC_DISCARD,
.iov_len = len,
});
);
}
void io_slice_wr_to_duplex(struct duplex_iovec *dst, const struct iovec *src, int src_cnt, size_t byte_beg, size_t byte_max_cnt) {
assert(src_cnt == 0 || dst);
IOV_ITER(
dst[j] = ((struct duplex_iovec){
.iov_read_to = IOVEC_DISCARD,
.iov_write_from = src[i].iov_base+off,
.iov_len = len,
});
);
}
void io_rd_to_duplex(struct duplex_iovec *dst, const struct iovec *src, int iovcnt) {
io_slice_rd_to_duplex(dst, src, iovcnt, 0, 0);
}
void io_wr_to_duplex(struct duplex_iovec *dst, const struct iovec *src, int iovcnt) {
io_slice_wr_to_duplex(dst, src, iovcnt, 0, 0);
}
|