diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-03-06 16:56:59 +0100 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-03-06 22:08:36 +0100 |
commit | b8f5b8d89dfc3a86e4f371fac7331372c2d0c901 (patch) | |
tree | 49e7c6584db67646c49674a89d21e0b5bb03fc7b /lib/util/array.c | |
parent | 8e2b5d633d1e33ec7bc478bf97b2f1e94776b925 (diff) |
Add a generic implementation of a dynamic array to libutil
The intention is to get rid of all the ad-hoc array implementations
in the other components and cut down code size.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/util/array.c')
-rw-r--r-- | lib/util/array.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/util/array.c b/lib/util/array.c new file mode 100644 index 0000000..3697a07 --- /dev/null +++ b/lib/util/array.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * array.c + * + * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "array.h" + +#include "sqfs/error.h" + +#include <stdlib.h> + +int array_init(array_t *array, size_t size, size_t capacity) +{ + size_t total; + + memset(array, 0, sizeof(*array)); + + if (capacity > 0) { + if (SZ_MUL_OV(size, capacity, &total)) + return SQFS_ERROR_OVERFLOW; + + array->data = malloc(total); + if (array->data == NULL) + return SQFS_ERROR_ALLOC; + } + + array->size = size; + array->count = capacity; + return 0; +} + +int array_init_copy(array_t *array, const array_t *src) +{ + int ret; + + ret = array_init(array, src->size, src->used); + if (ret != 0) + return ret; + + memcpy(array->data, src->data, src->used * src->size); + array->used = src->used; + return 0; +} + +void array_cleanup(array_t *array) +{ + free(array->data); + memset(array, 0, sizeof(*array)); +} + +int array_append(array_t *array, const void *data) +{ + size_t new_sz, new_count; + void *new; + + if (array->used == array->count) { + if (array->count == 0) { + new_count = 128; + } else { + if (SZ_MUL_OV(array->count, 2, &new_count)) + return SQFS_ERROR_ALLOC; + } + + if (SZ_MUL_OV(new_count, array->size, &new_sz)) + return SQFS_ERROR_ALLOC; + + new = realloc(array->data, new_sz); + if (new == NULL) + return SQFS_ERROR_ALLOC; + + array->data = new; + array->count = new_count; + } + + memcpy((char *)array->data + array->size * array->used, + data, array->size); + + array->used += 1; + return 0; +} + +int array_set_capacity(array_t *array, size_t capacity) +{ + size_t new_sz, new_count; + void *new; + + if (capacity <= array->count) + return 0; + + if (array->count == 0) { + new_count = 128; + } else { + if (SZ_MUL_OV(array->count, 2, &new_count)) + return SQFS_ERROR_ALLOC; + } + + while (new_count < capacity) { + if (SZ_MUL_OV(new_count, 2, &new_count)) + return SQFS_ERROR_ALLOC; + } + + if (SZ_MUL_OV(new_count, array->size, &new_sz)) + return SQFS_ERROR_ALLOC; + + new = realloc(array->data, new_sz); + if (new == NULL) + return SQFS_ERROR_ALLOC; + + array->data = new; + array->count = new_count; + return 0; +} |