aboutsummaryrefslogtreecommitdiff
path: root/src/llist.c
blob: f28aaaee282b36f803d9c15f761831fb396e2901 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "llist.h"
#include "util_rt.h"


void prne_init_llist (prne_llist_t *llist) {
	llist->head = NULL;
	llist->tail = NULL;
	llist->size = 0;
}

void prne_free_llist (prne_llist_t *llist) {
	prne_llist_clear(llist);
}

void prne_llist_clear (prne_llist_t *llist) {
	struct prne_llist_entry *cur = llist->head, *next;

	while (cur != NULL) {
		next = cur->next;
		prne_free(cur);
		cur = next;
	}

	llist->head = llist->tail = NULL;
	llist->size = 0;
}

prne_llist_entry_t *prne_llist_insert (
	prne_llist_t *llist,
	prne_llist_entry_t *entry,
	const prne_llist_element_t element)
{
	prne_llist_entry_t *ny;

	if (entry == NULL) {
		return prne_llist_append(llist, element);
	}

	ny = (prne_llist_entry_t*)prne_malloc(sizeof(prne_llist_entry_t), 1);
	if (ny == NULL) {
		return NULL;
	}
	ny->prev = entry;
	ny->next = entry->next;
	ny->element = element;
	if (entry->next != NULL) {
		entry->next->prev = ny;
	}
	else {
		llist->tail = ny;
	}
	entry->next = ny;

	llist->size += 1;
	return ny;
}

prne_llist_entry_t *prne_llist_append (
	prne_llist_t *llist,
	const prne_llist_element_t element)
{
	prne_llist_entry_t *ny = (prne_llist_entry_t*)prne_malloc(
		sizeof(prne_llist_entry_t),
		1);

	if (ny == NULL) {
		return NULL;
	}
	ny->next = NULL;
	ny->element = element;

	if (llist->tail == NULL) {
		llist->head = llist->tail = ny;
		ny->prev = NULL;
	}
	else {
		llist->tail->next = ny;
		ny->prev = llist->tail;
		llist->tail = ny;
	}

	llist->size += 1;
	return ny;
}

prne_llist_entry_t *prne_llist_erase (
	prne_llist_t *llist,
	prne_llist_entry_t *entry)
{
	prne_llist_entry_t *ret;

	if (entry == NULL) {
		return NULL;
	}

	if (entry == llist->head && entry == llist->tail) {
		llist->head = llist->tail = NULL;
		ret = NULL;
	}
	else if (entry == llist->head) {
		ret = llist->head = llist->head->next;
		llist->head->prev = NULL;
	}
	else if (entry == llist->tail) {
		ret = llist->tail = llist->tail->prev;
		llist->tail->next = NULL;
	}
	else {
		ret = entry->prev->next = entry->next;
		entry->next->prev = entry->prev;
	}

	prne_free(entry);
	llist->size -= 1;
	return ret;
}