libcdsb/src/list/copy.c

182 lines
3.5 KiB
C

/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "include.h"
static void init_first(list_t* x, vnode_t v, vtype t) {
lnode_t* node = malloc(sizeof(*node));
node->next = nullptr;
node->prev = nullptr;
node->node = v;
node->type = t;
x->first = node;
x->last = node;
}
static void push_next(list_t* x, vnode_t v, vtype t) {
lnode_t* node = malloc(sizeof(*node));
node->next = nullptr;
node->prev = x->last;
node->node = v;
node->type = t;
x->last->next = node;
x->last = node;
}
/*#####################################################################################################################*/
list_t list_copy(const list_t* s) {
list_t x;
lnode_t* c;
c = s->first;
memset(&x, 0, sizeof(x));
if (is_null(c))
return x;
init_first(&x, vnode_duplicate(&c->node, c->type), c->type);
while (!is_null(c = c->next)) {
push_next(&x, vnode_duplicate(&c->node, c->type), c->type);
}
return x;
}
list_t* list_duplicate(const list_t* s) {
list_t* x;
lnode_t* c;
c = s->first;
x = calloc(sizeof(*x), 1);
if (is_null(c))
return x;
init_first(x, vnode_duplicate(&c->node, c->type), c->type);
while (!is_null(c = c->next)) {
push_next(x, vnode_duplicate(&c->node, c->type), c->type);
}
return x;
}
void list_copy_init(list_t* x, const list_t* s) {
lnode_t* c;
c = s->first;
memset(x, 0, sizeof(*x));
if (is_null(c))
return;
init_first(x, vnode_duplicate(&c->node, c->type), c->type);
while (!is_null(c = c->next)) {
push_next(x, vnode_duplicate(&c->node, c->type), c->type);
}
}
void list_extend(list_t* x, const list_t* s) {
lnode_t* c;
c = s->first;
if (is_null(c))
return;
if (is_null(x->first)) {
init_first(x, vnode_duplicate(&c->node, c->type), c->type);
c = c->next;
if (is_null(c))
return;
}
do {
push_next(x, vnode_duplicate(&c->node, c->type), c->type);
} while (!is_null(c = c->next));
}
size_t list_slice(list_t* x, list_t* s, ssize_t i, size_t n, _Bool cut) {
lnode_t* c;
lnode_t* e;
size_t r;
r = n;
if (!n || is_null(s->first)) {
memset(x, 0, sizeof(*x));
return 0;
}
if (i < 0) {
c = s->last;
e = s->last;
i = ~i;
while (i && !is_null(c)) {
c = c->prev;
--i;
if (!n) { e = e->prev; }
else --n;
}
if (is_null(c)) c = x->first;
} else {
c = s->first;
while (i && !is_null(c)) {
c = c->next;
--i;
}
e = c;
while (n && !is_null(e)) {
e = e->next;
--n;
}
if (is_null(e)) e = x->last;
}
if (is_null(c)) return 0;
else r -= n;
if (!cut) {
init_first(x, vnode_duplicate(&c->node, c->type), c->type);
while ((c = c->next) != e) {
push_next(x, vnode_duplicate(&c->node, c->type), c->type);
}
push_next(x, vnode_duplicate(&e->node, e->type), e->type);
} else {
if (c->prev) {
c->prev->next = e->next;
} else s->first = e->next;
if (e->next) {
e->next->prev = c->prev;
} else s->last = c->prev;
(x->first = c)->prev = nullptr;
(x->last = e)->next = nullptr;
}
return r;
}