From: Yu Watanabe Date: Mon, 23 Mar 2026 14:04:05 +0000 (+0900) Subject: iovec-util: introduce IOVEC_SHIFT() macro and friends X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=043358d852499f61756d6eb76bff0ea286ab0b95;p=thirdparty%2Fsystemd.git iovec-util: introduce IOVEC_SHIFT() macro and friends --- diff --git a/src/fundamental/iovec-util-fundamental.h b/src/fundamental/iovec-util-fundamental.h index 707274f86e5..5b693742f3a 100644 --- a/src/fundamental/iovec-util-fundamental.h +++ b/src/fundamental/iovec-util-fundamental.h @@ -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); diff --git a/src/test/test-iovec-util.c b/src/test/test-iovec-util.c index e091463a934..68255071e86 100644 --- a/src/test/test-iovec-util.c +++ b/src/test/test-iovec-util.c @@ -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 = {};