#include #include #include #include "utils.h" #include "zarray.h" int zarray_init(zarray_t* array, int delta, zarray_item_killer_t killer) { if ((array == NULL) || (delta <= 0)) { return -EINVAL; } mylock_init(&(array->lock)); array->delta = delta; array->data = NULL; array->killer = killer; array->count = 0; array->caps = 0; array->pos = 0; return 0; } static int zarray_ensure_items(zarray_t* array, int mincap) { int nc, i; void* p; if (mincap < array->caps) { return 1; } nc = mincap; if (nc < array->caps + array->delta) { nc = array->caps + array->delta; } p = (void*)realloc(array->data, nc * sizeof(void*)); if (p == NULL) { return -ENOMEM; } array->data = p; for (i = array->caps; i < nc; i++) { array->data[i] = NULL; } /* this will make we can get next free * location quickly */ array->pos = array->caps; array->caps = nc; return 1; } int zarray_store(zarray_t* array, void* data) { int rc, i; if (array == NULL) { return -EINVAL; } mylock_lock(&(array->lock)); rc = zarray_ensure_items(array, array->count + 1); if (rc >= 0) { int idx; rc = -ENOMEM; idx = array->pos; for (i = 0; i < array->caps; i++) { if (array->data[idx] == NULL) { array->data[idx] = data; array->count++; rc = idx; break; } idx++; if (idx >= array->caps) { idx = 0; } } if (rc >= 0) { array->pos = (rc + 1) % array->caps; } } mylock_unlock(&(array->lock)); return rc; } int zarray_clear(zarray_t* array, int idx) { if (array == NULL) { return -EINVAL; } if ((idx < 0) || (idx >= array->caps)) { return -EINVAL; } mylock_lock(&(array->lock)); array->data[idx] = NULL; mylock_unlock(&(array->lock)); return 0; } void zarray_fini(zarray_t* array) { if (array == NULL) { return; } if (array->data != NULL) { int i; if (array->killer != NULL) { for (i = 0; i < array->caps; i++) { if (array->data[i] != NULL) { void* ptr = array->data[i]; array->data[i] = NULL; (array->killer)(ptr); } } } free(array->data); array->data = NULL; } } int zarray_iter_ex(zarray_t* array, xlist_t* l, void* arg) { int i, j; if ((array == NULL) || (l == NULL)) { return -EINVAL; } mylock_lock(&(array->lock)); for (j = 0; j < l->count; j++) { zarray_iter_fn_t f = (zarray_iter_fn_t)l->data[j]; if (f == NULL) { continue; } for (i = 0; i < array->caps; i++) { (*f)(arg, array->data[i]); } } mylock_unlock(&(array->lock)); return 0; } int zarray_iter(zarray_t* array, zarray_iter_fn_t f, void* arg) { int rc; xlist_t l; if ((array == NULL) || (f == NULL)) { return -EINVAL; } xlist_init(&l, 2); xlist_store(&l, f); rc = zarray_iter_ex(array, &l, arg); xlist_fini(&l); return rc; } int zarray_del(zarray_t* array, int idx) { void* ptr = NULL; if (array == NULL) { return -EINVAL; } if ((idx < 0) && (idx >= array->caps)) { return -EINVAL; } mylock_lock(&(array->lock)); ptr = array->data[idx]; array->data[idx] = NULL; if (ptr != NULL) { array->count--; } /* idx will be a usable position */ array->pos = idx; mylock_unlock(&(array->lock)); if (array->killer != NULL) { if (ptr != NULL) { (array->killer)(ptr); } } return 0; } int zarray_put(zarray_t* array, int idx, void* data) { int rc = 0; /* clang-format off */ if ((array == NULL) || (idx < 0) || (data == NULL)) { return -EINVAL; } /* clang-format on */ mylock_lock(&(array->lock)); rc = zarray_ensure_items(array, idx + 1); if (rc >= 0) { void* ptr = array->data[idx]; array->data[idx] = data; rc = 0; if (ptr != NULL) { if (array->killer != NULL) { array->killer(ptr); } } else { array->count++; } } mylock_unlock(&(array->lock)); return rc; } void* zarray_get(zarray_t* array, int idx) { void* ptr = NULL; /* clang-format off */ if ((array == NULL) || (idx < 0) || (idx >= array->caps)) { SET_ERROR(EINVAL); return NULL; } /* clang-format on */ mylock_lock(&(array->lock)); ptr = array->data[idx]; mylock_unlock(&(array->lock)); return ptr; }