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

Reply via email to