From 22001e480edd555a434097eaa7f490b70e3ad7a7 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Sat, 4 Jun 2022 21:59:01 +0300 Subject: [PATCH] Add list base --- src/list/base.c | 77 ++++++++++++++++++++++++++++++++ src/list/copy.c | 109 +++++++++++++++++++++++++++++++++++++++++++++ src/list/include.h | 28 ++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 src/list/base.c create mode 100644 src/list/copy.c create mode 100644 src/list/include.h diff --git a/src/list/base.c b/src/list/base.c new file mode 100644 index 0000000..90adb5e --- /dev/null +++ b/src/list/base.c @@ -0,0 +1,77 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +/*#####################################################################################################################*/ + +void list_init(list_t* x) { + memset(x, 0, sizeof(*x)); +} + +void list_free(list_t* x) { + lnode_t* c; + lnode_t* next; + + c = x->first; + + while (!is_null(c)) { + next = c->next; + vnode_free(c->node, c->type); + free(c); + c = next; + } + + memset(x, 0, sizeof(*x)); +} + +/*#####################################################################################################################*/ + +size_t list_size(const list_t* x) { + lnode_t* c; + size_t n; + + c = x->first; + n = 0; + + while (!is_null(c)) { + c = c->next; + ++n; + } + + return n; +} + +/*#####################################################################################################################*/ + +int list_compare(const list_t* s0, const list_t* s1) { + lnode_t *c0, *c1; + int c; + + if (s0 == s1) return 0; + + c0 = s0->first; + c1 = s1->first; + + for (;;) { + if (is_null(c0) || is_null(c1)) { + return (c0 == c1) ? 0 : (ssize_t)c0 - (ssize_t)c1; + } + + c = lnode_compare(c0, c1); + + if (c != 0) break; + + c0 = c0->next; + c1 = c1->next; + } + + for (;;) { + c0 = c0->next; + c1 = c1->next; + + if (is_null(c0) || is_null(c1)) { + return (c0 == c1) ? 0 : (ssize_t)c0 - (ssize_t)c1; + } + } +} diff --git a/src/list/copy.c b/src/list/copy.c new file mode 100644 index 0000000..a68334f --- /dev/null +++ b/src/list/copy.c @@ -0,0 +1,109 @@ +/* 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 = node; + x->last->next = 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)); +} diff --git a/src/list/include.h b/src/list/include.h new file mode 100644 index 0000000..e88d623 --- /dev/null +++ b/src/list/include.h @@ -0,0 +1,28 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "../../include/extra/list.h" +#include "../__internal/vnode.h" + +#ifndef LIBCDSB_SRC_LIST_INCLUDE_H +#define LIBCDSB_SRC_LIST_INCLUDE_H + +typedef enum libcdsb_list_direction { + LD_PREV = 1, + LD_NEXT = 2 +} ldir_t; + +typedef struct libcdsb_list_node { + struct libcdsb_list_node* prev; + struct libcdsb_list_node* next; + + vnode_t node; + vtype type; +} lnode_t; + +#define ldir_dir(cur, d) (&((cur)->prev))[(d)>>1] +#define ldir_inv(cur, d) (&((cur)->prev))[(d)&1] + +#define lnode_compare(s0, s1) vnode_compare((s0)->node, (s0)->type, (s1)->node, (s1)->type) + +#endif /* LIBCDSB_SRC_LIST_INCLUDE_H */