static int list_copy_all()

in source/list_utils.c [43:106]


static int list_copy_all(
    struct aws_allocator *alloc,
    struct aws_array_list *dest,
    const struct aws_array_list *src,
    clone_item_fn cloner,
    clean_up_item_fn cleaner) {
    AWS_ERROR_PRECONDITION(aws_allocator_is_valid(alloc));
    AWS_ERROR_PRECONDITION(src != dest);
    AWS_ERROR_PRECONDITION(aws_array_list_is_valid(dest));
    AWS_ERROR_PRECONDITION(aws_array_list_is_valid(src));
    AWS_ERROR_PRECONDITION(dest->item_size == src->item_size);

    size_t initial_length = aws_array_list_length(dest);
    size_t src_length     = aws_array_list_length(src);
    int lasterr;

    /* You can do this with a variable length uint8_t array everywhere except Windows,
     * but Microsoft forces us to do an allocation here.
     */
    void *dest_item = aws_mem_acquire(alloc, dest->item_size);
    if (!dest_item) {
        return AWS_OP_ERR;
    }

    for (size_t i = 0; i < src_length; i++) {
        void *src_item;

        if (aws_array_list_get_at_ptr(src, &src_item, i)) {
            goto err;
        }

        if (cloner(alloc, dest_item, src_item)) {
            goto err;
        }

        if (aws_array_list_push_back(dest, dest_item)) {
            cleaner(dest_item);
            goto err;
        }
    }

    aws_mem_release(alloc, dest_item);
    return AWS_OP_SUCCESS;
err:
    aws_mem_release(alloc, dest_item);
    lasterr = aws_last_error();

    while (aws_array_list_length(dest) > initial_length) {
        void *dest_item_ptr;

        if (aws_array_list_get_at_ptr(dest, &dest_item_ptr, aws_array_list_length(dest) - 1)) {
            /*
             * We had elements at aws_array_list, but not anymore, it seems.
             * Someone must be mucking with the destination list from another thread;
             * abort before we do any more damage.
             */
            abort();
        }
        cleaner(dest_item_ptr);
        aws_array_list_pop_back(dest);
    }

    return aws_raise_error(lasterr);
}