diff options
Diffstat (limited to 'src/lib/array.c')
-rw-r--r-- | src/lib/array.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/lib/array.c b/src/lib/array.c new file mode 100644 index 0000000..44b91a5 --- /dev/null +++ b/src/lib/array.c @@ -0,0 +1,166 @@ +/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" + + +void * +array_idx_modifiable_i(const struct array *array, unsigned int idx) +{ + i_assert(idx < array->buffer->used / array->element_size); + return PTR_OFFSET(array->buffer->data, idx * array->element_size); +} + +void *array_idx_get_space_i(struct array *array, unsigned int idx) +{ + return buffer_get_space_unsafe(array->buffer, idx * array->element_size, + array->element_size); +} + +void array_idx_set_i(struct array *array, unsigned int idx, const void *data) +{ + buffer_write(array->buffer, idx * array->element_size, + data, array->element_size); +} + +void array_idx_clear_i(struct array *array, unsigned int idx) +{ + buffer_write_zero(array->buffer, idx * array->element_size, + array->element_size); +} + +void *array_insert_space_i(struct array *array, unsigned int idx) +{ + void *data; + size_t pos; + + pos = idx * array->element_size; + buffer_copy(array->buffer, pos + array->element_size, + array->buffer, pos, SIZE_MAX); + + data = buffer_get_space_unsafe(array->buffer, pos, array->element_size); + memset(data, 0, array->element_size); + return data; +} + +bool array_cmp_i(const struct array *array1, const struct array *array2) +{ + if (!array_is_created_i(array1) || array1->buffer->used == 0) + return !array_is_created_i(array2) || array2->buffer->used == 0; + + if (!array_is_created_i(array2)) + return FALSE; + + return buffer_cmp(array1->buffer, array2->buffer); +} + +bool array_equal_fn_i(const struct array *array1, const struct array *array2, + int (*cmp)(const void *, const void*)) +{ + unsigned int count1, count2, i; + size_t size; + + if (!array_is_created_i(array1) || array1->buffer->used == 0) + return !array_is_created_i(array2) || array2->buffer->used == 0; + + if (!array_is_created_i(array2)) + return FALSE; + + count1 = array_count_i(array1); count2 = array_count_i(array2); + if (count1 != count2) + return FALSE; + + size = array1->element_size; + i_assert(size == array2->element_size); + + for (i = 0; i < count1; i++) { + if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size), + CONST_PTR_OFFSET(array2->buffer->data, i * size)) != 0) + return FALSE; + } + return TRUE; +} + +bool array_equal_fn_ctx_i(const struct array *array1, const struct array *array2, + int (*cmp)(const void *, const void *, const void *), + const void *context) +{ + unsigned int count1, count2, i; + size_t size; + + if (!array_is_created_i(array1) || array1->buffer->used == 0) + return !array_is_created_i(array2) || array2->buffer->used == 0; + + if (!array_is_created_i(array2)) + return FALSE; + + count1 = array_count_i(array1); count2 = array_count_i(array2); + if (count1 != count2) + return FALSE; + + size = array1->element_size; + i_assert(size == array2->element_size); + + for (i = 0; i < count1; i++) { + if (cmp(CONST_PTR_OFFSET(array1->buffer->data, i * size), + CONST_PTR_OFFSET(array2->buffer->data, i * size), context) != 0) + return FALSE; + } + return TRUE; +} + +void array_reverse_i(struct array *array) +{ + const size_t element_size = array->element_size; + unsigned int i, count = array_count_i(array); + size_t size; + void *data, *tmp; + + data = buffer_get_modifiable_data(array->buffer, &size); + tmp = t_buffer_get(array->element_size); + for (i = 0; i+1 < count; i++, count--) { + memcpy(tmp, PTR_OFFSET(data, i * element_size), element_size); + memcpy(PTR_OFFSET(data, i * element_size), + PTR_OFFSET(data, (count-1) * element_size), + element_size); + memcpy(PTR_OFFSET(data, (count-1) * element_size), tmp, + element_size); + } +} + +void array_sort_i(struct array *array, int (*cmp)(const void *, const void *)) +{ + unsigned int count; + + count = array_count_i(array); + if (count == 0) + return; + qsort(buffer_get_modifiable_data(array->buffer, NULL), + count, array->element_size, cmp); +} + +void *array_bsearch_i(struct array *array, const void *key, + int (*cmp)(const void *, const void *)) +{ + unsigned int count; + + count = array_count_i(array); + return bsearch(key, array->buffer->data, + count, array->element_size, cmp); +} + +const void *array_lsearch_i(const struct array *array, const void *key, + int (*cmp)(const void *, const void *)) +{ + const void * const data = array->buffer->data; + const size_t s = array->element_size; + unsigned int idx; + + for (idx = 0; idx < array_count_i(array); idx++) { + if (cmp(key, CONST_PTR_OFFSET(data, idx * s)) == 0) { + return PTR_OFFSET(data, idx * s); + } + } + + return NULL; +} |