00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <apol/vector.h>
00026 #include "vector-internal.h"
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <errno.h>
00030
00031
00032 #define APOL_VECTOR_DFLT_INIT_CAP 10
00033
00034
00035
00036
00037 struct apol_vector
00038 {
00039
00040 void **array;
00041
00042 size_t size;
00043
00044
00045 size_t capacity;
00046 apol_vector_free_func *fr;
00047 };
00048
00049 apol_vector_t *apol_vector_create(apol_vector_free_func * fr)
00050 {
00051 return apol_vector_create_with_capacity(APOL_VECTOR_DFLT_INIT_CAP, fr);
00052 }
00053
00054 apol_vector_t *apol_vector_create_with_capacity(size_t cap, apol_vector_free_func * fr)
00055 {
00056 apol_vector_t *v = NULL;
00057 int error;
00058
00059 if (cap < 1) {
00060 cap = 1;
00061 }
00062 v = calloc(1, sizeof(apol_vector_t));
00063 if (!v)
00064 return NULL;
00065 v->array = calloc((v->capacity = cap), sizeof(void *));
00066 if (!(v->array)) {
00067 error = errno;
00068 free(v);
00069 errno = error;
00070 return NULL;
00071 }
00072 v->fr = fr;
00073 return v;
00074 }
00075
00076 apol_vector_t *apol_vector_create_from_iter(qpol_iterator_t * iter, apol_vector_free_func * fr)
00077 {
00078 size_t iter_size;
00079 apol_vector_t *v;
00080 void *item;
00081 int error;
00082 if (qpol_iterator_get_size(iter, &iter_size) < 0 || (v = apol_vector_create_with_capacity(iter_size, fr)) == NULL) {
00083 return NULL;
00084 }
00085 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00086 if (qpol_iterator_get_item(iter, &item)) {
00087 error = errno;
00088 free(v);
00089 errno = error;
00090 return NULL;
00091 }
00092 apol_vector_append(v, item);
00093 }
00094 return v;
00095 }
00096
00097 apol_vector_t *apol_vector_create_from_vector(const apol_vector_t * v, apol_vector_dup_func * dup, void *data,
00098 apol_vector_free_func * fr)
00099 {
00100 apol_vector_t *new_v;
00101 size_t i;
00102 if (v == NULL) {
00103 errno = EINVAL;
00104 return NULL;
00105 }
00106 if ((new_v = apol_vector_create_with_capacity(v->capacity, fr)) == NULL) {
00107 return NULL;
00108 }
00109 if (dup == NULL) {
00110 memcpy(new_v->array, v->array, v->size * sizeof(void *));
00111 } else {
00112 for (i = 0; i < v->size; i++) {
00113 new_v->array[i] = dup(v->array[i], data);
00114 }
00115 }
00116 new_v->size = v->size;
00117 return new_v;
00118 }
00119
00120 apol_vector_t *apol_vector_create_from_intersection(const apol_vector_t * v1,
00121 const apol_vector_t * v2, apol_vector_comp_func * cmp, void *data)
00122 {
00123 apol_vector_t *new_v;
00124 size_t i, j;
00125 if (v1 == NULL || v2 == NULL) {
00126 errno = EINVAL;
00127 return NULL;
00128 }
00129 if ((new_v = apol_vector_create(NULL)) == NULL) {
00130 return NULL;
00131 }
00132 for (i = 0; i < v1->size; i++) {
00133 for (j = 0; j < v2->size; j++) {
00134 if ((cmp != NULL && cmp(v1->array[i], v2->array[j], data) == 0) ||
00135 (cmp == NULL && v1->array[i] == v2->array[j])) {
00136 if (apol_vector_append(new_v, v1->array[i]) < 0) {
00137 apol_vector_destroy(&new_v);
00138 return NULL;
00139 }
00140 break;
00141 }
00142 }
00143 }
00144 return new_v;
00145 }
00146
00147 void apol_vector_destroy(apol_vector_t ** v)
00148 {
00149 size_t i = 0;
00150
00151 if (!v || !(*v))
00152 return;
00153
00154 if ((*v)->fr) {
00155 for (i = 0; i < (*v)->size; i++) {
00156 (*v)->fr((*v)->array[i]);
00157 }
00158 }
00159 free((*v)->array);
00160 (*v)->array = NULL;
00161 free(*v);
00162 *v = NULL;
00163 }
00164
00165 size_t apol_vector_get_size(const apol_vector_t * v)
00166 {
00167 if (!v) {
00168 errno = EINVAL;
00169 return 0;
00170 } else {
00171 return v->size;
00172 }
00173 }
00174
00175 size_t apol_vector_get_capacity(const apol_vector_t * v)
00176 {
00177 if (!v) {
00178 errno = EINVAL;
00179 return 0;
00180 } else {
00181 return v->capacity;
00182 }
00183 }
00184
00185 void *apol_vector_get_element(const apol_vector_t * v, size_t idx)
00186 {
00187 if (!v || !(v->array)) {
00188 errno = EINVAL;
00189 return NULL;
00190 }
00191
00192 if (idx >= v->size) {
00193 errno = ERANGE;
00194 return NULL;
00195 }
00196
00197 return v->array[idx];
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207 static int apol_vector_grow(apol_vector_t * v)
00208 {
00209 void **tmp;
00210 size_t new_capacity = v->capacity;
00211 if (new_capacity >= 128) {
00212 new_capacity += 128;
00213 } else {
00214 new_capacity *= 2;
00215 }
00216 tmp = realloc(v->array, new_capacity * sizeof(void *));
00217 if (!tmp) {
00218 return -1;
00219 }
00220 v->capacity = new_capacity;
00221 v->array = tmp;
00222 return 0;
00223 }
00224
00225 int apol_vector_get_index(const apol_vector_t * v, const void *elem, apol_vector_comp_func * cmp, void *data, size_t * i)
00226 {
00227 if (!v || !i) {
00228 errno = EINVAL;
00229 return -1;
00230 }
00231
00232 for (*i = 0; *i < v->size; (*i)++) {
00233 if ((cmp != NULL && cmp(v->array[*i], elem, data) == 0) || (cmp == NULL && elem == v->array[*i])) {
00234 return 0;
00235 }
00236 }
00237 return -1;
00238 }
00239
00240 int apol_vector_append(apol_vector_t * v, void *elem)
00241 {
00242 if (!v) {
00243 errno = EINVAL;
00244 return -1;
00245 }
00246
00247 if (v->size >= v->capacity && apol_vector_grow(v)) {
00248 return -1;
00249 }
00250
00251 v->array[v->size] = elem;
00252 v->size++;
00253
00254 return 0;
00255 }
00256
00257 int apol_vector_append_unique(apol_vector_t * v, void *elem, apol_vector_comp_func * cmp, void *data)
00258 {
00259 size_t i;
00260 if (apol_vector_get_index(v, elem, cmp, data, &i) < 0) {
00261 return apol_vector_append(v, elem);
00262 }
00263 errno = EEXIST;
00264 return 1;
00265 }
00266
00267 int apol_vector_compare(const apol_vector_t * a, const apol_vector_t * b, apol_vector_comp_func * cmp, void *data, size_t * i)
00268 {
00269 int compval;
00270 if (a == NULL || b == NULL || i == NULL) {
00271 errno = EINVAL;
00272 return 0;
00273 }
00274 size_t a_len = apol_vector_get_size(a);
00275 size_t b_len = apol_vector_get_size(b);
00276 for (*i = 0; *i < a_len && *i < b_len; (*i)++) {
00277 if (cmp != NULL) {
00278 compval = cmp(a->array[*i], b->array[*i], data);
00279 } else {
00280 compval = (int)((char *)a->array[*i] - (char *)b->array[*i]);
00281 }
00282 if (compval != 0) {
00283 return compval;
00284 }
00285 }
00286 if (a_len == b_len) {
00287 return 0;
00288 } else if (a_len < b_len) {
00289 return -1;
00290 } else {
00291 return 1;
00292 }
00293 }
00294
00295 static size_t vector_qsort_partition(void **data, size_t first, size_t last, apol_vector_comp_func * cmp, void *arg)
00296 {
00297 void *pivot = data[last];
00298 size_t i = first, j = last;
00299 while (i < j) {
00300 if (cmp(data[i], pivot, arg) <= 0) {
00301 i++;
00302 } else {
00303 data[j] = data[i];
00304 data[i] = data[j - 1];
00305 j--;
00306 }
00307 }
00308 data[j] = pivot;
00309 return j;
00310 }
00311
00312 static void vector_qsort(void **data, size_t first, size_t last, apol_vector_comp_func * cmp, void *arg)
00313 {
00314 if (first < last) {
00315 size_t i = vector_qsort_partition(data, first, last, cmp, arg);
00316
00317
00318
00319 if (i > 0) {
00320 vector_qsort(data, first, i - 1, cmp, arg);
00321 }
00322 vector_qsort(data, i + 1, last, cmp, arg);
00323 }
00324 }
00325
00326
00327
00328
00329
00330 static int vector_int_comp(const void *a, const void *b, void *data __attribute__ ((unused)))
00331 {
00332 char *i = (char *)a;
00333 char *j = (char *)b;
00334 if (i < j) {
00335 return -1;
00336 } else if (i > j) {
00337 return 1;
00338 }
00339 return 0;
00340 }
00341
00342
00343 void apol_vector_sort(apol_vector_t * v, apol_vector_comp_func * cmp, void *data)
00344 {
00345 if (!v) {
00346 errno = EINVAL;
00347 return;
00348 }
00349 if (cmp == NULL) {
00350 cmp = vector_int_comp;
00351 }
00352 if (v->size > 1) {
00353 vector_qsort(v->array, 0, v->size - 1, cmp, data);
00354 }
00355 }
00356
00357 void apol_vector_sort_uniquify(apol_vector_t * v, apol_vector_comp_func * cmp, void *data)
00358 {
00359 if (!v) {
00360 errno = EINVAL;
00361 return;
00362 }
00363 if (cmp == NULL) {
00364 cmp = vector_int_comp;
00365 }
00366 if (v->size > 1) {
00367 size_t i, j = 0;
00368 void **new_array;
00369
00370
00371 for (i = 1; i < v->size; i++) {
00372 if (cmp(v->array[i], v->array[j], data) != 0) {
00373
00374 j++;
00375 v->array[j] = v->array[i];
00376 } else {
00377
00378 if (v->fr != NULL) {
00379 v->fr(v->array[i]);
00380 }
00381 }
00382 }
00383 v->size = j + 1;
00384
00385 apol_vector_sort(v, cmp, data);
00386 j = 0;
00387 for (i = 1; i < v->size; i++) {
00388 if (cmp(v->array[i], v->array[j], data) != 0) {
00389
00390 j++;
00391 v->array[j] = v->array[i];
00392 } else {
00393
00394 if (v->fr != NULL) {
00395 v->fr(v->array[i]);
00396 }
00397 }
00398 }
00399
00400 v->size = j + 1;
00401 if ((new_array = realloc(v->array, v->size * sizeof(void *))) != NULL) {
00402 v->array = new_array;
00403 v->capacity = v->size;
00404 }
00405 }
00406 }
00407
00408 int apol_vector_cat(apol_vector_t * dest, const apol_vector_t * src)
00409 {
00410 size_t i, orig_size, cap;
00411 void **a;
00412 if (!src || !apol_vector_get_size(src)) {
00413 return 0;
00414 }
00415
00416 if (!dest) {
00417 errno = EINVAL;
00418 return -1;
00419 }
00420 orig_size = apol_vector_get_size(dest);
00421 for (i = 0; i < apol_vector_get_size(src); i++)
00422 if (apol_vector_append(dest, apol_vector_get_element(src, i))) {
00423
00424 if (orig_size == 0) {
00425 cap = 1;
00426 } else {
00427 cap = orig_size;
00428 }
00429 a = realloc(dest->array, cap * sizeof(*a));
00430 if (a != NULL) {
00431 dest->array = a;
00432 }
00433 dest->size = orig_size;
00434 dest->capacity = cap;
00435 return -1;
00436 }
00437
00438 return 0;
00439 }
00440
00441 int apol_vector_remove(apol_vector_t * v, const size_t idx)
00442 {
00443 if (v == NULL || idx >= v->size) {
00444 errno = EINVAL;
00445 return -1;
00446 }
00447 memmove(v->array + idx, v->array + idx + 1, sizeof(v->array[0]) * (v->size - idx - 1));
00448 v->size--;
00449 return 0;
00450 }
00451
00452
00453
00454 void vector_set_free_func(apol_vector_t * v, apol_vector_free_func * fr)
00455 {
00456 v->fr = fr;
00457 }