]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
iovec-wrapper: introduce iovw_compare() and iovw_equal()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 17 Apr 2026 13:53:56 +0000 (22:53 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 18 Apr 2026 20:51:01 +0000 (05:51 +0900)
src/basic/iovec-wrapper.c
src/basic/iovec-wrapper.h
src/test/test-iovec-wrapper.c

index 2b302b96ab0b29847c1bab644be16229d26260d0..a76087b859e83deb6865a8ece9efd58d3a298eca 100644 (file)
@@ -23,6 +23,28 @@ void iovw_done_free(struct iovec_wrapper *iovw) {
         iovw_done(iovw);
 }
 
+int iovw_compare(const struct iovec_wrapper *a, const struct iovec_wrapper *b) {
+        int r;
+
+        if (a == b)
+                return 0;
+
+        if (!a || !b)
+                return CMP(!!a, !!b);
+
+        /* Note, this performs structural (element-by-element) comparison, not content-based comparison.
+         * Two wrappers with identical concatenated content but different element boundaries
+         * (e.g., ["fo","o"] vs ["f","oo"]) will not compare as equal. */
+
+        for (size_t i = 0, n = MIN(a->count, b->count); i < n; i++) {
+                r = iovec_memcmp(a->iovec + i, b->iovec + i);
+                if (r != 0)
+                        return r;
+        }
+
+        return CMP(a->count, b->count);
+}
+
 int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
         assert(iovw);
 
index eaa859af06d4a33044f427af300fe0e5c4cd8547..d2437b60f1925f8ed71860e0c221e3e37c31b952 100644 (file)
@@ -11,6 +11,11 @@ struct iovec_wrapper {
 void iovw_done_free(struct iovec_wrapper *iovw);
 void iovw_done(struct iovec_wrapper *iovw);
 
+int iovw_compare(const struct iovec_wrapper *a, const struct iovec_wrapper *b) _pure_;
+static inline bool iovw_equal(const struct iovec_wrapper *a, const struct iovec_wrapper *b) {
+        return iovw_compare(a, b) == 0;
+}
+
 int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len);
 int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len);
 int iovw_append(struct iovec_wrapper *iovw, const void *data, size_t len);
index 1f4585a129f40ff433b7f73ea9d22ad25dbaaac7..168217f16c2377096ed72078443385e210f7bd8d 100644 (file)
@@ -3,9 +3,66 @@
 #include <sys/uio.h>
 
 #include "alloc-util.h"
+#include "iovec-util.h"
 #include "iovec-wrapper.h"
 #include "tests.h"
 
+TEST(iovw_compare) {
+        _cleanup_(iovw_done) struct iovec_wrapper a1 = {}, a2 = {}, b = {}, c = {}, d = {}, e = {};
+
+        ASSERT_OK(iovw_put(&a1, (char*) "foo", 3));
+        ASSERT_OK(iovw_put(&a1, (char*) "aaaaa", 5));
+
+        ASSERT_OK(iovw_put(&a2, (char*) "foo", 3));
+        ASSERT_OK(iovw_put(&a2, (char*) "aaaaa", 5));
+
+        ASSERT_OK(iovw_put(&b, (char*) "foo", 3));
+        ASSERT_OK(iovw_put(&b, (char*) "bbbbb", 5));
+
+        ASSERT_OK(iovw_put(&c, (char*) "foo", 3));
+
+        ASSERT_OK(iovw_put(&d, (char*) "fooaa", 5));
+        ASSERT_OK(iovw_put(&d, (char*) "aaa", 3));
+
+        ASSERT_EQ(iovw_compare(&a1, &a1), 0);
+        ASSERT_EQ(iovw_compare(&a1, &a2), 0);
+        ASSERT_EQ(iovw_compare(&a2, &a1), 0);
+        ASSERT_LT(iovw_compare(&a1, &b), 0);
+        ASSERT_GT(iovw_compare(&b, &a1), 0);
+        ASSERT_EQ(iovw_compare(&b, &b), 0);
+        ASSERT_GT(iovw_compare(&a1, &c), 0);
+        ASSERT_LT(iovw_compare(&c, &a1), 0);
+        ASSERT_EQ(iovw_compare(&c, &c), 0);
+        ASSERT_LT(iovw_compare(&a1, &d), 0);
+        ASSERT_GT(iovw_compare(&d, &a1), 0);
+        ASSERT_EQ(iovw_compare(&d, &d), 0);
+        ASSERT_GT(iovw_compare(&a1, &e), 0);
+        ASSERT_LT(iovw_compare(&e, &a1), 0);
+        ASSERT_EQ(iovw_compare(&e, &e), 0);
+        ASSERT_GT(iovw_compare(&a1, NULL), 0);
+        ASSERT_LT(iovw_compare(NULL, &a1), 0);
+        ASSERT_EQ(iovw_compare(NULL, NULL), 0);
+
+        ASSERT_TRUE(iovw_equal(&a1, &a1));
+        ASSERT_TRUE(iovw_equal(&a1, &a2));
+        ASSERT_TRUE(iovw_equal(&a2, &a1));
+        ASSERT_FALSE(iovw_equal(&a1, &b));
+        ASSERT_FALSE(iovw_equal(&b, &a1));
+        ASSERT_TRUE(iovw_equal(&b, &b));
+        ASSERT_FALSE(iovw_equal(&a1, &c));
+        ASSERT_FALSE(iovw_equal(&c, &a1));
+        ASSERT_TRUE(iovw_equal(&c, &c));
+        ASSERT_FALSE(iovw_equal(&a1, &d));
+        ASSERT_FALSE(iovw_equal(&d, &a1));
+        ASSERT_TRUE(iovw_equal(&d, &d));
+        ASSERT_FALSE(iovw_equal(&a1, &e));
+        ASSERT_FALSE(iovw_equal(&e, &a1));
+        ASSERT_TRUE(iovw_equal(&e, &e));
+        ASSERT_FALSE(iovw_equal(&a1, NULL));
+        ASSERT_FALSE(iovw_equal(NULL, &a1));
+        ASSERT_TRUE(iovw_equal(NULL, NULL));
+}
+
 TEST(iovw_put) {
         _cleanup_(iovw_done) struct iovec_wrapper iovw = {};