diff options
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 145 |
1 files changed, 145 insertions, 0 deletions
@@ -0,0 +1,145 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Miroslav Lichvar 2014 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ********************************************************************** + + ======================================================================= + + Functions implementing an array with automatic memory allocation. + + */ + +#include "config.h" + +#include "sysincl.h" + +#include "array.h" +#include "memory.h" + +struct ARR_Instance_Record { + void *data; + unsigned int elem_size; + unsigned int used; + unsigned int allocated; +}; + +ARR_Instance +ARR_CreateInstance(unsigned int elem_size) +{ + ARR_Instance array; + + assert(elem_size > 0); + + array = MallocNew(struct ARR_Instance_Record); + + array->data = NULL; + array->elem_size = elem_size; + array->used = 0; + array->allocated = 0; + + return array; +} + +void +ARR_DestroyInstance(ARR_Instance array) +{ + Free(array->data); + Free(array); +} + +static void +realloc_array(ARR_Instance array, unsigned int min_size) +{ + assert(min_size <= 2 * min_size); + if (array->allocated >= min_size && array->allocated <= 2 * min_size) + return; + + if (array->allocated < min_size) { + while (array->allocated < min_size) + array->allocated = array->allocated ? 2 * array->allocated : 1; + } else { + array->allocated = min_size; + } + + array->data = Realloc2(array->data, array->allocated, array->elem_size); +} + +void * +ARR_GetNewElement(ARR_Instance array) +{ + array->used++; + realloc_array(array, array->used); + return ARR_GetElement(array, array->used - 1); +} + +void * +ARR_GetElement(ARR_Instance array, unsigned int index) +{ + assert(index < array->used); + return (void *)((char *)array->data + (size_t)index * array->elem_size); +} + +void * +ARR_GetElements(ARR_Instance array) +{ + /* Return a non-NULL pointer when the array has zero size */ + if (!array->data) { + assert(!array->used); + return array; + } + + return array->data; +} + +void +ARR_AppendElement(ARR_Instance array, void *element) +{ + void *e; + + e = ARR_GetNewElement(array); + memcpy(e, element, array->elem_size); +} + +void +ARR_RemoveElement(ARR_Instance array, unsigned int index) +{ + void *e, *l; + + e = ARR_GetElement(array, index); + l = ARR_GetElement(array, array->used - 1); + + if (e < l) + memmove(e, (char *)e + array->elem_size, (char *)l - (char *)e); + array->used--; + + realloc_array(array, array->used); +} + +void +ARR_SetSize(ARR_Instance array, unsigned int size) +{ + realloc_array(array, size); + array->used = size; +} + +unsigned int +ARR_GetSize(ARR_Instance array) +{ + return array->used; +} |