182 lines
3.5 KiB
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;
|
|
}
|