Hi Jacob, thanks for the review. Your reply went only to me, so I'm re-adding the list for this reply.
On Wed, Oct 14, 2026 at 5:22 PM Jacob Tanenbaum <[email protected]> wrote: > > > > On Tue, Oct 6, 2026 at 2:52 PM Mark Michelson via dev > <[email protected]> wrote: >> >> 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); >> +} > > > could you add a few more test cases? calling vector_steal() on an empty > vector? and could you push to the empty vector after it was stolen from? > That should exercise all the claims about vector_steal() I've updated the test to perform more operations on vec after being stolen, and ensuring that those operations do not affect the 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 >> > > Jacob Tanenbaum _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
