diff --git a/include/util/array.h b/include/util/array.h index a51bdb640..862921680 100644 --- a/include/util/array.h +++ b/include/util/array.h @@ -15,4 +15,15 @@ void array_remove_at(struct wl_array *arr, size_t offset, size_t size); */ bool array_realloc(struct wl_array *arr, size_t size); +/** + * Returns a pointer to the first valid element in a reversed array. + */ +void *array_reversed_start(struct wl_array *arr); + +/** + * Adds a new element to the array inserting them starting from a higher + * memory address effectively inserting them in reverse order. + */ +void *array_reversed_add(struct wl_array *arr, size_t size); + #endif diff --git a/util/array.c b/util/array.c index ec16a7b13..427cf725a 100644 --- a/util/array.c +++ b/util/array.c @@ -38,3 +38,26 @@ bool array_realloc(struct wl_array *arr, size_t size) { arr->alloc = alloc; return true; } + +void *array_reversed_start(struct wl_array *arr) { + char *data = arr->data; + return data + arr->alloc - arr->size; +} + +void *array_reversed_add(struct wl_array *arr, size_t size) { + if (arr->size + size > arr->alloc) { + size_t new_alloc = arr->alloc * 2; + char *new = malloc(new_alloc); + if (!new) { + return NULL; + } + + memcpy(new + (new_alloc - arr->size), array_reversed_start(arr), arr->size); + free(arr->data); + arr->data = new; + arr->alloc = new_alloc; + } + + arr->size += size; + return array_reversed_start(arr); +}