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

Reply via email to