Home | History | Annotate | Download | only in shared
      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