libcdsb/src/list/extra.c

192 lines
3.7 KiB
C
Raw Normal View History

2022-06-04 21:59:26 +03:00
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "include.h"
2022-06-08 20:59:07 +03:00
static void lnode_cut(list_t* s, lnode_t* cur) {
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
vnode_free(&cur->node, cur->type);
2022-06-04 21:59:26 +03:00
if (!is_null(cur->prev)) {
cur->prev->next = cur->next;
} else s->first = cur->next;
if (!is_null(cur->next)) {
cur->next->prev = cur->prev;
} else s->last = cur->prev;
free(cur);
}
2022-06-08 20:59:07 +03:00
2022-06-04 21:59:26 +03:00
/*#####################################################################################################################*/
2022-06-08 20:59:07 +03:00
_Bool libcdsb_list_update(list_t* x, ssize_t i, const void* v, vtype t, int ins) {
2022-06-04 21:59:26 +03:00
ldir_t dir;
lnode_t* c;
if (i < 0) {
2022-06-08 20:59:07 +03:00
i = ~i;
2022-06-04 21:59:26 +03:00
dir = LD_PREV;
2022-06-08 20:59:07 +03:00
} else dir = LD_NEXT;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
c = ldir_dir((lnode_t*)x, dir);
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
while (i && !is_null(c)) {
2022-06-04 21:59:26 +03:00
c = ldir_dir(c, dir);
2022-06-08 20:59:07 +03:00
--i;
2022-06-04 21:59:26 +03:00
}
2022-06-08 20:59:07 +03:00
if (i && dir == LD_PREV) {
c = x->first;
} else if (i) return false;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
if (is_null(c)) {
x->first = x->last = c = calloc(sizeof(*c), 1);
} else if (ins) {
lnode_t *v = malloc(sizeof(*v));
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
dir = (ins < 0) ? LD_PREV : LD_NEXT;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
ldir_dir(v, dir) = ldir_dir(c, dir);
ldir_inv(v, dir) = c;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
c = v;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
if (!is_null(ldir_dir(c, dir))) {
ldir_inv(ldir_dir(c, dir), dir) = c;
} else ldir_inv((lnode_t*)x, dir) = c;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
ldir_dir(ldir_inv(c, dir), dir) = c;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
} else vnode_free(&c->node, c->type);
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
c->node = vnode_create(v, t);
c->type = t;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
return true;
2022-06-04 21:59:26 +03:00
}
size_t libcdsb_list_count(const list_t* s, const void* v, vtype t) {
lnode_t* c;
size_t n;
int cmp;
c = s->first;
n = 0;
while (!is_null(c)) {
2022-06-05 19:29:30 +03:00
cmp = vtype_compare(vnode_peek(&c->node, c->type), c->type, v, t);
2022-06-04 21:59:26 +03:00
if (cmp == 0) ++n;
c = c->next;
}
return n;
}
2022-06-08 20:59:07 +03:00
int libcdsb_list_get(vtype_list* x, ssize_t i, void* _, list_access_callback callback, _Bool cut) {
2022-06-04 21:59:26 +03:00
ldir_t dir;
lnode_t* c;
2022-06-08 20:59:07 +03:00
size_t n;
2022-06-04 21:59:26 +03:00
if (i < 0) {
2022-06-08 20:59:07 +03:00
n = ~i;
2022-06-04 21:59:26 +03:00
dir = LD_PREV;
2022-06-08 20:59:07 +03:00
} else {
n = i;
dir = LD_NEXT;
}
2022-06-04 21:59:26 +03:00
c = ldir_dir((lnode_t*)x, dir);
2022-06-08 20:59:07 +03:00
while (n && !is_null(c)) {
2022-06-04 21:59:26 +03:00
c = ldir_dir(c, dir);
2022-06-08 20:59:07 +03:00
--n;
2022-06-04 21:59:26 +03:00
}
2022-06-08 20:59:07 +03:00
if (n || is_null(c)) return -1;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
i = (callback) ? callback(vnode_peek(&c->node, c->type), i, c->type, _) : 0;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
if (cut) lnode_cut(x, c);
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
return i;
}
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
int libcdsb_list_find(vtype_list* x, const void* v, vtype t, void* _, list_access_callback callback, _Bool r, _Bool cut) {
ldir_t dir;
lnode_t* c;
ssize_t i;
int cmp;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
dir = r ? LD_PREV : LD_NEXT;
c = ldir_dir((lnode_t*)x, dir);
i = 0;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
while (!is_null(c)) {
cmp = vtype_compare(vnode_peek(&c->node, c->type), c->type, v, t);
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
if (cmp == 0) {
i = (callback) ? callback(vnode_peek(&c->node, c->type), (r)?~i:i, c->type, _) : 0;
2022-06-04 21:59:26 +03:00
2022-06-08 20:59:07 +03:00
if (cut) lnode_cut(x, c);
2022-06-05 18:36:48 +03:00
2022-06-08 20:59:07 +03:00
return i;
}
2022-06-05 18:36:48 +03:00
2022-06-08 20:59:07 +03:00
c = ldir_dir(c, dir);
++i;
}
return -1;
}
2022-06-05 18:36:48 +03:00
2022-06-08 20:59:07 +03:00
int libcdsb_list_foreach(vtype_list* x, void* data, list_access_callback callback, _Bool flush) {
2022-06-05 18:36:48 +03:00
lnode_t* n;
2022-06-05 18:36:48 +03:00
lnode_t* c;
size_t i;
2022-06-05 18:36:48 +03:00
int r;
c = x->first;
i = 0;
2022-06-05 18:36:48 +03:00
while (!is_null(c)) {
if ((r = callback(vnode_peek(&c->node, c->type), i, c->type, data)) != 0)
break;
n = c->next;
2022-06-08 20:59:07 +03:00
if (flush) {
vnode_free(&c->node, c->type);
free(c);
}
c = n;
++i;
}
if (flush) {
while(!is_null(c)) {
n = c->next;
vnode_free(&c->node, c->type);
free(c);
c = n;
}
memset(x, 0, sizeof(*x));
2022-06-05 18:36:48 +03:00
}
return 0;
}