102 lines
2.3 KiB
C
102 lines
2.3 KiB
C
/* This software is licensed by the MIT License, see LICENSE file */
|
|
/* Copyright © 2022 Gregory Lirent */
|
|
|
|
#include "include.h"
|
|
|
|
bool libcdsb_list_insert(list_t* x, ssize_t i, var_t value, int ins, void* dt, list_access_callback callback) {
|
|
ldir_t dir;
|
|
lnode_t* c;
|
|
|
|
if (i < 0) {
|
|
i = ~i;
|
|
dir = LD_PREV;
|
|
} else dir = LD_NEXT;
|
|
|
|
c = ldir_dir((lnode_t*)x, dir);
|
|
|
|
while (i && !is_null(c)) {
|
|
c = ldir_dir(c, dir);
|
|
--i;
|
|
}
|
|
|
|
if (i && dir == LD_PREV) {
|
|
c = x->first;
|
|
} else if (i) return false;
|
|
|
|
if (is_null(c)) {
|
|
x->first = x->last = c = calloc(sizeof(*c), 1);
|
|
} else if (ins) {
|
|
lnode_t *v = malloc(sizeof(*v));
|
|
|
|
dir = (ins < 0) ? LD_PREV : LD_NEXT;
|
|
|
|
ldir_dir(v, dir) = ldir_dir(c, dir);
|
|
ldir_inv(v, dir) = c;
|
|
|
|
c = v;
|
|
|
|
if (!is_null(ldir_dir(c, dir))) {
|
|
ldir_inv(ldir_dir(c, dir), dir) = c;
|
|
} else ldir_inv((lnode_t*)x, dir) = c;
|
|
|
|
ldir_dir(ldir_inv(c, dir), dir) = c;
|
|
} else {
|
|
if (callback) callback(vnode_peek(&c->node, c->type), -1, dt);
|
|
vnode_free(&c->node, c->type);
|
|
}
|
|
|
|
c->node = vnode_create(value);
|
|
c->type = value.type;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool libcdsb_list_attach(list_t* x, ssize_t i, var_t value, int ins, void* dt, list_access_callback callback) {
|
|
ldir_t dir;
|
|
lnode_t* c;
|
|
|
|
if (i < 0) {
|
|
i = ~i;
|
|
dir = LD_PREV;
|
|
} else dir = LD_NEXT;
|
|
|
|
c = ldir_dir((lnode_t*)x, dir);
|
|
|
|
while (i && !is_null(c)) {
|
|
c = ldir_dir(c, dir);
|
|
--i;
|
|
}
|
|
|
|
if (i && dir == LD_PREV) {
|
|
c = x->first;
|
|
} else if (i) return false;
|
|
|
|
if (is_null(c)) {
|
|
x->first = x->last = c = calloc(sizeof(*c), 1);
|
|
} else if (ins) {
|
|
lnode_t *v = malloc(sizeof(*v));
|
|
|
|
dir = (ins < 0) ? LD_PREV : LD_NEXT;
|
|
|
|
ldir_dir(v, dir) = ldir_dir(c, dir);
|
|
ldir_inv(v, dir) = c;
|
|
|
|
c = v;
|
|
|
|
if (!is_null(ldir_dir(c, dir))) {
|
|
ldir_inv(ldir_dir(c, dir), dir) = c;
|
|
} else ldir_inv((lnode_t*)x, dir) = c;
|
|
|
|
ldir_dir(ldir_inv(c, dir), dir) = c;
|
|
} else {
|
|
if (callback) callback(vnode_peek(&c->node, c->type), -1, dt);
|
|
vnode_free(&c->node, c->type);
|
|
}
|
|
|
|
vnode_attach(&c->node, value);
|
|
c->type = value.type;
|
|
|
|
return true;
|
|
}
|