On Mon, Oct 19, 2026 at 10:53 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]> > --- > v1 -> v2: > * Expanded the test case in test-vector.c. > --- > lib/vec.c | 18 +++++++++++++++ > lib/vec.h | 1 + > tests/ovn.at | 2 ++ > tests/test-vector.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 75 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 94ed06c63..8081fb04c 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..f91741856 100644 > --- a/tests/test-vector.c > +++ b/tests/test-vector.c > @@ -254,6 +254,59 @@ 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); > + > + 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); > + > + /* Let's make sure the original vec has been unaffected by > + * the changes to thief. > + */ > + ovs_assert(vector_capacity(&vec) == 0); > + ovs_assert(vector_len(&vec) == 0); > + > + /* The vast majority of the time, the reason you would want to steal a > + * vector is because it is going to go out of scope and this prevents > + * having to destroy it. However, it is also possible to steal a > vector as > + * a way of saving its contents elsewhere and resetting it. Let's > make sure > + * we can still operate on vec after it has been stolen. > + */ > + uint32_t more_elements[5] = {3, 4, 5, 6, 7}; > + vector_push_array(&vec, more_elements, ARRAY_SIZE(more_elements)); > + ovs_assert(vector_capacity(&vec) == 5); > + ovs_assert(vector_len(&vec) == 5); > + > + /* And now let's make sure the thief is unaffected by changes to vec. > */ > + ovs_assert(vector_capacity(&thief) == 3); > + ovs_assert(vector_len(&thief) == 3); > + > + /* Since we have re-added elements to vec, we now need to destroy it. > + * If we had stolen from it and left it alone, this would be > unnecessary. > + */ > + vector_destroy(&vec); > + vector_destroy(&thief); > +} > + > static void > test_pointers(struct ovs_cmdl_context *ctx OVS_UNUSED) > { > @@ -305,6 +358,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 > > Looks good to me, thanks. Acked-by: Ales Musil <[email protected]> I have also stopped the review at this patch, it seems that the rest of the series has some issue with CI, could you please check it out? _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
