This is similar to vector_clone(), except that it performs a shallow
copy of the vector instead of using memcpy(). The vector that is stolen
from is for all intents and purposes unusable after calling this
function.

This is useful for cases where a vector is built up and then needs to be
copied as part of a struct initializer.

Signed-off-by: Mark Michelson <[email protected]>
---
 lib/vec.c           | 18 ++++++++++++++++++
 lib/vec.h           |  1 +
 tests/ovn.at        |  2 ++
 tests/test-vector.c | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 55 insertions(+)

diff --git a/lib/vec.c b/lib/vec.c
index 97e6b6549..e4bb72c2c 100644
--- a/lib/vec.c
+++ b/lib/vec.c
@@ -168,6 +168,24 @@ vector_clone(struct vector *vec)
     return clone;
 }
 
+/* Performs a shallow copy of vec into another structure. vec is
+ * re-initialized after this operation and is safe to re-use or
+ * destroy. However, its buffer will be empty.
+ */
+struct vector
+vector_steal(struct vector *vec)
+{
+    struct vector thief = (struct vector) {
+        .buffer = vec->buffer,
+        .esize = vec->esize,
+        .len = vec->len,
+        .capacity = vec->capacity,
+    };
+
+    vector_init(vec);
+    return thief;
+}
+
 /* Reserves additional space to fit extra n items. */
 void
 vector_reserve(struct vector *vec, size_t n)
diff --git a/lib/vec.h b/lib/vec.h
index ff8f69a5e..50dd09bc4 100644
--- a/lib/vec.h
+++ b/lib/vec.h
@@ -76,6 +76,7 @@ bool vector_remove_block(struct vector *vec, size_t start, 
size_t end);
 void *vector_get_ptr(const struct vector *vec, size_t index);
 void vector_shrink_to_fit(struct vector *vec);
 struct vector vector_clone(struct vector *vec);
+struct vector vector_steal(struct vector *vec);
 void vector_reserve(struct vector *vec, size_t n);
 
 /* Pushes element into the end of the vector. */
diff --git a/tests/ovn.at b/tests/ovn.at
index 817d335f7..849290591 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -2453,6 +2453,8 @@ check ovstest test-vector shrink
 check ovstest test-vector clone
 
 check ovstest test-vector pointers
+
+check ovstest test-vector steal
 AT_CLEANUP
 
 AT_SETUP([Sparse array operations])
diff --git a/tests/test-vector.c b/tests/test-vector.c
index f2bad0c33..5d93f5835 100644
--- a/tests/test-vector.c
+++ b/tests/test-vector.c
@@ -254,6 +254,39 @@ test_clone(struct ovs_cmdl_context *ctx OVS_UNUSED)
     vector_destroy(&clone);
 }
 
+static void
+test_steal(struct ovs_cmdl_context *ctx OVS_UNUSED)
+{
+    uint32_t elements[3] = {0, 1, 2};
+    struct vector vec = VECTOR_CAPACITY_INITIALIZER(uint32_t, 10);
+    vector_push_array(&vec, elements, ARRAY_SIZE(elements));
+
+    struct vector thief = vector_steal(&vec);
+    ovs_assert(vector_capacity(&thief) == 10);
+    ovs_assert(vector_len(&thief) == 3);
+
+    ovs_assert(vector_capacity(&vec) == 0);
+    ovs_assert(vector_len(&vec) == 0);
+    /* While it's unnecessary to destroy vec, we should
+     * ensure that destroying it is safe and does not
+     * affect the thief negatively.
+     */
+    vector_destroy(&vec);
+
+    size_t i = 0;
+    uint32_t num;
+    VECTOR_FOR_EACH (&thief, num) {
+        ovs_assert(elements[i++] == num);
+    }
+    ovs_assert(i == ARRAY_SIZE(elements));
+
+    vector_shrink_to_fit(&thief);
+    ovs_assert(vector_capacity(&thief) == 3);
+    ovs_assert(vector_len(&thief) == 3);
+
+    vector_destroy(&thief);
+}
+
 static void
 test_pointers(struct ovs_cmdl_context *ctx OVS_UNUSED)
 {
@@ -305,6 +338,7 @@ test_vector_main(int argc OVS_UNUSED, char *argv[] 
OVS_UNUSED)
         {"shrink", NULL, 0, 0, test_shrink, OVS_RO},
         {"clone", NULL, 0, 0, test_clone, OVS_RO},
         {"pointers", NULL, 0, 0, test_pointers, OVS_RO},
+        {"steal", NULL, 0, 0, test_steal, OVS_RO},
         {NULL, NULL, 0, 0, NULL, OVS_RO},
     };
     struct ovs_cmdl_context ctx;
-- 
2.55.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to