From 55994e9cb3a2a9df764e78ce856a9feceb2e818c Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Fri, 31 Jul 2026 16:31:20 +0300 Subject: [PATCH] Dual-linked list: tests and sort and delete function. --- src/utils/dlist.c | 128 +++++++++++++++++++++++++++------------------ src/utils/dlist.h | 20 +++---- test/utils/dlist.c | 46 +++++++++------- 3 files changed, 114 insertions(+), 80 deletions(-) diff --git a/src/utils/dlist.c b/src/utils/dlist.c index da8ebec..3625484 100644 --- a/src/utils/dlist.c +++ b/src/utils/dlist.c @@ -6,6 +6,8 @@ #include "dlist.h" +/* TODO: Test for dlist_remove_by_ptr */ + dlist_t *_dlist_init(void *el_ptr, int el_siz) { dlist_t *dlist = malloc(sizeof(dlist_t)); dlist->len = 0; @@ -19,102 +21,124 @@ dlist_t *_dlist_init(void *el_ptr, int el_siz) { return dlist; } -void _dlist_insert(dlist_t *dlist, dlist_el_t *new_el, dlist_el_t *prev_el) { - if (prev_el != NULL) { - new_el->next = prev_el->next; - prev_el->next->previous = new_el; - new_el->previous = prev_el; - prev_el->next = new_el; +void _dlist_insert(dlist_t *dlist, dlist_node_t *new_el, dlist_node_t *prev_node) { + if (prev_node != NULL) { + new_el->next = prev_node->next; + prev_node->next->previous = new_el; + new_el->previous = prev_node; + prev_node->next = new_el; if (new_el->next == NULL) { dlist->current = new_el; dlist->pointer = new_el; } } else { - new_el->next = dlist->current; + new_el->next = dlist->start; new_el->previous = NULL; + dlist->start->previous = new_el; dlist->start = new_el; - dlist->current->previous = new_el; } dlist->len++; } -void _dlist_insert_end(dlist_t *dlist, dlist_el_t *new_el) { - dlist->current->next = new_el; - new_el->previous = dlist->current; - new_el->next = NULL; - dlist->current = new_el; - dlist->pointer = new_el; +void _dlist_insert_end(dlist_t *dlist, dlist_node_t *new_node) { + dlist->current->next = new_node; + new_node->previous = dlist->current; + new_node->next = NULL; + dlist->current = new_node; + dlist->pointer = new_node; dlist->len++; } void _dlist_insert_sort(dlist_t *dlist, void *el_ptr, int el_siz, - dblist_cb_t *cb) { - dlist_el_t *d_el = malloc(sizeof(dlist_el_t)); - d_el->el_ptr = malloc(el_siz); - memcpy(d_el->el_ptr, el_ptr, el_siz); + dblist_sort_cb_t *cb) { + dlist_node_t *node = malloc(sizeof(dlist_node_t)); + node->el_ptr = malloc(el_siz); + memcpy(node->el_ptr, el_ptr, el_siz); - dlist_el_t *dlist_item = dlist->start; + dlist_node_t *dlist_item = dlist->start; bool res = true; if (dlist->start == NULL) { - dlist->start = d_el; - dlist->current = d_el; - d_el->next = NULL; - d_el->previous = NULL; - dlist->pointer = d_el; + dlist->start = node; + dlist->current = node; + node->next = NULL; + node->previous = NULL; + dlist->pointer = node; dlist->len++; return; } + for (int i = 0; i < dlist->len; i++) { res = cb(el_ptr, dlist_item->el_ptr); - if (!res) { - dlist_item = dlist_item->previous; - _dlist_insert(dlist, d_el, dlist_item); + if (!res) break; - } + dlist_item = dlist_item->next; + } + + if (!res) { + dlist_item = dlist_item->previous; + _dlist_insert(dlist, node, dlist_item); + } else { + _dlist_insert_end(dlist, node); } - if (res) _dlist_insert_end(dlist, d_el); } void _dlist_add(dlist_t *dlist, void *el_ptr, int el_siz, bool prepend) { - dlist_el_t *d_el = malloc(sizeof(dlist_el_t)); - d_el->el_ptr = malloc(el_siz); - memcpy(d_el->el_ptr, el_ptr, el_siz); + dlist_node_t *node = malloc(sizeof(dlist_node_t)); + node->el_ptr = malloc(el_siz); + memcpy(node->el_ptr, el_ptr, el_siz); if (dlist->start == NULL) { - d_el->previous = NULL; - d_el->next = NULL; - dlist->start = d_el; - dlist->current = d_el; - dlist->pointer = d_el; + node->previous = NULL; + node->next = NULL; + dlist->start = node; + dlist->current = node; + dlist->pointer = node; } else if (prepend) { - d_el->previous = NULL; - d_el->next = dlist->start; - dlist->start->previous = d_el; - dlist->start = d_el; + node->previous = NULL; + node->next = dlist->start; + dlist->start->previous = node; + dlist->start = node; } else { - d_el->previous = dlist->current; - d_el->next = NULL; - dlist->current->next = d_el; - dlist->current = d_el; - dlist->pointer = d_el; + node->previous = dlist->current; + node->next = NULL; + dlist->current->next = node; + dlist->current = node; + dlist->pointer = node; } dlist->len++; } +dlist_node_t *find_node_by_ptr(dlist_t *dlist, void *el_ptr) { + dlist_node_t *el = dlist->start; + do { + if (el->el_ptr == el_ptr) break; + } while ((el = el->next) != NULL); + if (el->el_ptr == el_ptr) return el_ptr; + return NULL; +} + +int dlist_remove_by_ptr(dlist_t *dlist, void *el_ptr, dblist_rm_cb_t cb) { + dlist_node_t *node = find_node_by_ptr(dlist, el_ptr); + if (node == NULL) return -1; + cb(node->el_ptr); + node->next->previous = node->previous; + node->previous->next = node->next; + free(node); + return 1; +} + void *dlist_it_prev(dlist_t *dlist) { + dlist_node_t *cur_ptr = dlist->pointer; if (dlist->pointer->previous != NULL) { dlist->pointer = dlist->pointer->previous; - return dlist->pointer->el_ptr; - } else { - return NULL; } + return cur_ptr->el_ptr; } void *dlist_it_next(dlist_t *dlist) { + dlist_node_t *cur_ptr = dlist->pointer; if (dlist->pointer->next != NULL) { dlist->pointer = dlist->pointer->next; - return dlist->pointer->el_ptr; - } else { - return NULL; } + return cur_ptr->el_ptr; } \ No newline at end of file diff --git a/src/utils/dlist.h b/src/utils/dlist.h index 8ddc984..13f5d3f 100644 --- a/src/utils/dlist.h +++ b/src/utils/dlist.h @@ -4,23 +4,25 @@ #include #include -typedef struct dlist_el_t { - struct dlist_el_t *next; - struct dlist_el_t *previous; +typedef struct dlist_node_t { + struct dlist_node_t *next; + struct dlist_node_t *previous; void *el_ptr; -} dlist_el_t; +} dlist_node_t; typedef struct dlist_t { - dlist_el_t *start; - dlist_el_t *current; - dlist_el_t *pointer; + dlist_node_t *start; + dlist_node_t *current; + dlist_node_t *pointer; size_t len; } dlist_t; dlist_t *_dlist_init(void *el_ptr, int el_siz); /* Returns if a > b */ -typedef bool dblist_cb_t(void *a, void *b); +typedef bool dblist_sort_cb_t(void *a, void *b); + +typedef bool dblist_rm_cb_t(void *el_ptr); void *dlist_get_current(dlist_t *dlist); void *dlist_it_prev(dlist_t *dlist); @@ -28,7 +30,7 @@ void _dlist_add(dlist_t *dlist, void *el_ptr, int el_siz, bool prepend); void *dlist_it_prev(dlist_t *dlist); void *dlist_it_next(dlist_t *dlist); void _dlist_insert_sort(dlist_t *dlist, void *el_ptr, int el_siz, - dblist_cb_t *cb); + dblist_sort_cb_t *cb); #define dlist_init(el_ptr, el_def) _dlist_init(el_ptr, sizeof(el_def)) #define dlist_add(dlist, el_ptr, el_def, prepend) \ diff --git a/test/utils/dlist.c b/test/utils/dlist.c index 2cf2b99..afa6f2b 100644 --- a/test/utils/dlist.c +++ b/test/utils/dlist.c @@ -1,6 +1,8 @@ #include +#include +#include #include -#include +#include #include typedef struct { @@ -84,7 +86,7 @@ void test__init__add_and_iterate(void **state) { dlist_add(dlist, &t2, test_t, false); dlist_add(dlist, &t3, test_t, false); - test_t *dl_t3 = dlist_get_current(dlist); + test_t *dl_t3 = dlist_it_prev(dlist); test_t *dl_t2 = dlist_it_prev(dlist); test_t *dl_t1 = dlist_it_prev(dlist); @@ -100,28 +102,34 @@ bool _sort(void *_a, void *_b) { return a->num > b->num; } -void test__init__insert_sort(void **state) { - test_t t1 = {.buf = "TEST BUF", .num = 123, .text = LOREM_IPSUM}; - test_t t2 = {.buf = "TEST 1 BUF", .num = 11, .text = "RAND 1 TEXT"}; - test_t t3 = {.buf = "TEST 2 BUF", .num = 22, .text = "RAND 2 TEXT"}; - test_t t4 = {.buf = "TEST 3 BUF", .num = 23, .text = "RAND 3 TEXT"}; +#define T_BUF "TEST BUF " +#define T_TEXT "RAND TEXT " +#define T_IT_NUM 120 +void test__init__insert_sort(void **state) { + srand(time(NULL)); + + test_t t = {.text = T_TEXT}; dlist_t *dlist = dlist_init(NULL, test_t); - dlist_insert_sort(dlist, &t1, test_t, _sort); - dlist_insert_sort(dlist, &t2, test_t, _sort); - dlist_insert_sort(dlist, &t3, test_t, _sort); - dlist_insert_sort(dlist, &t4, test_t, _sort); + for (int i = 0; i < T_IT_NUM; i++) { + sprintf(t.buf, "%s %d", T_BUF, i); + t.num = rand(); + dlist_insert_sort(dlist, &t, test_t, _sort); + } - test_t *dl_t1 = dlist_get_current(dlist); - test_t *dl_t4 = dlist_it_prev(dlist); - test_t *dl_t3 = dlist_it_prev(dlist); - test_t *dl_t2 = dlist_it_prev(dlist); + test_t *t1, *t2; - assert_memory_equal(dl_t1, &t1, sizeof(test_t)); - assert_memory_equal(dl_t2, &t2, sizeof(test_t)); - assert_memory_equal(dl_t3, &t3, sizeof(test_t)); - assert_memory_equal(dl_t4, &t4, sizeof(test_t)); + t2 = dlist_it_prev(dlist); + t1 = dlist_it_prev(dlist); + + assert_int_in_range(t2->num, t1->num, INT_MAX);\ + + for (int i = T_IT_NUM - 2; i > 0; i--) { + t2 = t1; + t1 = dlist_it_prev(dlist); + assert_int_in_range(t2->num, t1->num, INT_MAX); + } } int setup(void **state) { return 0; }