1 /* 2 * libkmod - interface to kernel module operations 3 * 4 * Copyright (C) 2011-2013 ProFUSION embedded systems 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <assert.h> 21 #include <errno.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include <shared/array.h> 26 27 /* basic pointer array growing in steps */ 28 29 30 static int array_realloc(struct array *array, size_t new_total) 31 { 32 void *tmp = realloc(array->array, sizeof(void *) * new_total); 33 if (tmp == NULL) 34 return -ENOMEM; 35 array->array = tmp; 36 array->total = new_total; 37 return 0; 38 } 39 40 void array_init(struct array *array, size_t step) 41 { 42 assert(step > 0); 43 array->array = NULL; 44 array->count = 0; 45 array->total = 0; 46 array->step = step; 47 } 48 49 int array_append(struct array *array, const void *element) 50 { 51 size_t idx; 52 53 if (array->count + 1 >= array->total) { 54 int r = array_realloc(array, array->total + array->step); 55 if (r < 0) 56 return r; 57 } 58 idx = array->count; 59 array->array[idx] = (void *)element; 60 array->count++; 61 return idx; 62 } 63 64 int array_append_unique(struct array *array, const void *element) 65 { 66 void **itr = array->array; 67 void **itr_end = itr + array->count; 68 for (; itr < itr_end; itr++) 69 if (*itr == element) 70 return -EEXIST; 71 return array_append(array, element); 72 } 73 74 void array_pop(struct array *array) { 75 array->count--; 76 if (array->count + array->step < array->total) { 77 int r = array_realloc(array, array->total - array->step); 78 if (r < 0) 79 return; 80 } 81 } 82 83 void array_free_array(struct array *array) { 84 free(array->array); 85 array->count = 0; 86 array->total = 0; 87 } 88 89 90 void array_sort(struct array *array, int (*cmp)(const void *a, const void *b)) 91 { 92 qsort(array->array, array->count, sizeof(void *), cmp); 93 } 94 95 int array_remove_at(struct array *array, unsigned int pos) 96 { 97 if (array->count <= pos) 98 return -ENOENT; 99 100 array->count--; 101 if (pos < array->count) 102 memmove(array->array + pos, array->array + pos + 1, 103 sizeof(void *) * (array->count - pos)); 104 105 if (array->count + array->step < array->total) { 106 int r = array_realloc(array, array->total - array->step); 107 /* ignore error */ 108 if (r < 0) 109 return 0; 110 } 111 112 return 0; 113 } 114