Dual-linked list: tests and sort and delete function.
This commit is contained in:
+76
-52
@@ -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;
|
||||
}
|
||||
+11
-9
@@ -4,23 +4,25 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
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) \
|
||||
|
||||
+27
-19
@@ -1,6 +1,8 @@
|
||||
#include <cmocka.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <utils/dlist.h>
|
||||
|
||||
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; }
|
||||
|
||||
Reference in New Issue
Block a user