]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
iovec-util: introduce IOVEC_SHIFT() macro and friends
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 23 Mar 2026 14:04:05 +0000 (23:04 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 18 Apr 2026 18:27:35 +0000 (03:27 +0900)
src/fundamental/iovec-util-fundamental.h
src/test/test-iovec-util.c

index 707274f86e53fc6c40115a5d302d9924bc97bf1a..5b693742f3a7cf067c424b81fd627c06663bfdee 100644 (file)
@@ -23,6 +23,25 @@ struct iovec {
                 .iov_len = (len),                                       \
         }
 
+static inline struct iovec* iovec_shift(const struct iovec *iovec, size_t shift, struct iovec *ret) {
+        assert(iovec);
+        assert(ret);
+
+        /* This returns an empty iovec when 'shift' is larger or equals to the input iovec length.
+         * The 'iovec' and 'ret' can point to the same object. */
+
+        *ret = IOVEC_MAKE(iovec->iov_len > shift ? (uint8_t*) iovec->iov_base + shift : NULL,
+                          LESS_BY(iovec->iov_len, shift));
+        return ret;
+}
+
+#define IOVEC_SHIFT(iov, shift)                         \
+        *iovec_shift(iov, shift, &(struct iovec){})
+
+static inline struct iovec* iovec_inc(struct iovec *iovec, size_t shift) {
+        return iovec_shift(iovec, shift, iovec);
+}
+
 static inline void iovec_done(struct iovec *iovec) {
         /* A _cleanup_() helper that frees the iov_base in the iovec */
         assert(iovec);
index e091463a93423190bab560211991e8df192de231..68255071e861d983846482a60c8d47f43113f221 100644 (file)
@@ -4,6 +4,40 @@
 #include "memory-util.h"
 #include "tests.h"
 
+TEST(iovec_shift) {
+        const struct iovec iov = CONST_IOVEC_MAKE_STRING("54321");
+
+        ASSERT_EQ(iovec_memcmp(&IOVEC_SHIFT(&iov, 0), &CONST_IOVEC_MAKE_STRING("54321")), 0);
+        ASSERT_EQ(iovec_memcmp(&IOVEC_SHIFT(&iov, 1), &CONST_IOVEC_MAKE_STRING("4321")), 0);
+        ASSERT_EQ(iovec_memcmp(&IOVEC_SHIFT(&iov, 2), &CONST_IOVEC_MAKE_STRING("321")), 0);
+        ASSERT_EQ(iovec_memcmp(&IOVEC_SHIFT(&iov, 3), &CONST_IOVEC_MAKE_STRING("21")), 0);
+        ASSERT_EQ(iovec_memcmp(&IOVEC_SHIFT(&iov, 4), &CONST_IOVEC_MAKE_STRING("1")), 0);
+        ASSERT_FALSE(iovec_is_set(&IOVEC_SHIFT(&iov, 5)));
+        ASSERT_FALSE(iovec_is_set(&IOVEC_SHIFT(&iov, 6)));
+        ASSERT_FALSE(iovec_is_set(&IOVEC_SHIFT(&iov, 7)));
+
+        const struct iovec empty = {};
+        ASSERT_FALSE(iovec_is_set(&IOVEC_SHIFT(&empty, 0)));
+        ASSERT_FALSE(iovec_is_set(&IOVEC_SHIFT(&empty, 1)));
+}
+
+TEST(iovec_inc) {
+        struct iovec iov = IOVEC_MAKE_STRING("54321");
+
+        ASSERT_EQ(iovec_memcmp(iovec_inc(&iov, 0), &CONST_IOVEC_MAKE_STRING("54321")), 0);
+        ASSERT_EQ(iovec_memcmp(iovec_inc(&iov, 1), &CONST_IOVEC_MAKE_STRING("4321")), 0);
+        ASSERT_EQ(iovec_memcmp(iovec_inc(&iov, 1), &CONST_IOVEC_MAKE_STRING("321")), 0);
+        ASSERT_EQ(iovec_memcmp(iovec_inc(&iov, 1), &CONST_IOVEC_MAKE_STRING("21")), 0);
+        ASSERT_EQ(iovec_memcmp(iovec_inc(&iov, 1), &CONST_IOVEC_MAKE_STRING("1")), 0);
+        ASSERT_FALSE(iovec_is_set(iovec_inc(&iov, 1)));
+        ASSERT_FALSE(iovec_is_set(iovec_inc(&iov, 1)));
+        ASSERT_FALSE(iovec_is_set(iovec_inc(&iov, 1)));
+
+        struct iovec empty = {};
+        ASSERT_FALSE(iovec_is_set(iovec_inc(&empty, 0)));
+        ASSERT_FALSE(iovec_is_set(iovec_inc(&empty, 1)));
+}
+
 TEST(iovec_memcmp) {
         struct iovec iov1 = CONST_IOVEC_MAKE_STRING("abcdef"), iov2 = IOVEC_MAKE_STRING("bcdefg"), empty = {};