myxce/src/lib/zarray.c

264 lines
4.9 KiB
C

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#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;
}