solidc
Robust collection of general-purpose cross-platform C libraries and data structures designed for rapid and safe development in C
Loading...
Searching...
No Matches
list.c
1#include "../include/list.h"
2
3#include <stdalign.h>
4#include <stdlib.h>
5#include <string.h>
6
7#define ALIGNMENT 8U
8#define ALIGNMENT_MASK (ALIGNMENT - 1)
9
10// Round up to proper alignment
11static inline size_t aligned_size(size_t n) { return (n + ALIGNMENT_MASK) & ~(ALIGNMENT_MASK); }
12
13// Node allocation: single malloc (node + element)
14static list_node_t* list_node_new(size_t elem_size, void* data) {
15 size_t total_size = sizeof(list_node_t) + aligned_size(elem_size);
16 list_node_t* node = (list_node_t*)malloc(total_size);
17 if (!node) return NULL;
18
19 node->next = NULL;
20 node->prev = NULL;
21 node->data = (void*)(node + 1); // element lives inline
22 memcpy(node->data, data, elem_size);
23 return node;
24}
25
26static void list_node_free(list_node_t* node) {
27 free(node); // single allocation
28}
29
30// ---- list implementation ----
31
32list_t* list_new(size_t elem_size) {
33 list_t* list = (list_t*)malloc(sizeof(list_t));
34 if (!list) return NULL;
35 list->head = list->tail = NULL;
36 list->size = 0;
37 list->elem_size = elem_size;
38 return list;
39}
40
41void list_free(list_t* list) {
42 if (!list) return;
43 list_clear(list);
44 free(list);
45}
46
47void list_clear(list_t* list) {
48 if (!list) return;
49 list_node_t* cur = list->head;
50 while (cur) {
51 list_node_t* next = cur->next;
52 list_node_free(cur);
53 cur = next;
54 }
55 list->head = list->tail = NULL;
56 list->size = 0;
57}
58
59size_t list_size(const list_t* list) { return list ? list->size : 0; }
60
61void list_push_back(list_t* list, void* elem) {
62 if (!list) return;
63 list_node_t* node = list_node_new(list->elem_size, elem);
64 if (!node) return;
65
66 if (!list->tail) {
67 list->head = list->tail = node;
68 } else {
69 node->prev = list->tail;
70 list->tail->next = node;
71 list->tail = node;
72 }
73 list->size++;
74}
75
76void list_pop_back(list_t* list) {
77 if (!list || !list->tail) return;
78 list_node_t* n = list->tail;
79 list->tail = n->prev;
80 if (list->tail)
81 list->tail->next = NULL;
82 else
83 list->head = NULL;
84 list_node_free(n);
85 list->size--;
86}
87
88void list_push_front(list_t* list, void* elem) {
89 if (!list) return;
90 list_node_t* node = list_node_new(list->elem_size, elem);
91 if (!node) return;
92
93 if (!list->head) {
94 list->head = list->tail = node;
95 } else {
96 node->next = list->head;
97 list->head->prev = node;
98 list->head = node;
99 }
100 list->size++;
101}
102
104 if (!list || !list->head) return;
105 list_node_t* n = list->head;
106 list->head = n->next;
107 if (list->head)
108 list->head->prev = NULL;
109 else
110 list->tail = NULL;
111 list_node_free(n);
112 list->size--;
113}
114
115void* list_get(const list_t* list, size_t index) {
116 if (!list || index >= list->size) return NULL;
117 list_node_t* cur = list->head;
118 for (size_t i = 0; i < index; i++) cur = cur->next;
119 return cur ? cur->data : NULL;
120}
121
122int list_index_of(const list_t* list, void* elem) {
123 if (!list) return -1;
124 list_node_t* cur = list->head;
125 int idx = 0;
126 while (cur) {
127 if (memcmp(cur->data, elem, list->elem_size) == 0) return idx;
128 cur = cur->next;
129 idx++;
130 }
131 return -1;
132}
133
134void list_insert(list_t* list, size_t index, void* elem) {
135 if (!list || index > list->size) return;
136 if (index == 0) {
137 list_push_front(list, elem);
138 return;
139 }
140 if (index == list->size) {
141 list_push_back(list, elem);
142 return;
143 }
144
145 list_node_t* cur = list->head;
146 for (size_t i = 0; i < index; i++) cur = cur->next;
147
148 list_node_t* node = list_node_new(list->elem_size, elem);
149 if (!node) return;
150
151 node->next = cur;
152 node->prev = cur->prev;
153 if (cur->prev) cur->prev->next = node;
154 cur->prev = node;
155 if (cur == list->head) list->head = node;
156 list->size++;
157}
158
159void list_remove(list_t* list, void* elem) {
160 if (!list) return;
161 int idx = list_index_of(list, elem);
162 if (idx == -1) return;
163
164 list_node_t* cur = list->head;
165 for (int i = 0; i < idx; i++) cur = cur->next;
166
167 if (cur->prev)
168 cur->prev->next = cur->next;
169 else
170 list->head = cur->next;
171
172 if (cur->next)
173 cur->next->prev = cur->prev;
174 else
175 list->tail = cur->prev;
176
177 list_node_free(cur);
178 list->size--;
179}
180
181void list_insert_after(list_t* list, void* elem, void* after) {
182 int idx = list_index_of(list, after);
183 if (idx == -1) return;
184 list_insert(list, (size_t)idx + 1, elem);
185}
186
187void list_insert_before(list_t* list, void* elem, void* before) {
188 int idx = list_index_of(list, before);
189 if (idx == -1) return;
190 list_insert(list, (size_t)idx, elem);
191}
void list_pop_back(list_t *list)
Definition list.c:76
void list_insert(list_t *list, size_t index, void *elem)
Definition list.c:134
void list_insert_before(list_t *list, void *elem, void *before)
Definition list.c:187
void list_insert_after(list_t *list, void *elem, void *after)
Definition list.c:181
int list_index_of(const list_t *list, void *elem)
Definition list.c:122
void list_free(list_t *list)
Definition list.c:41
void * list_get(const list_t *list, size_t index)
Definition list.c:115
struct list_node list_node_t
void list_push_front(list_t *list, void *elem)
Definition list.c:88
list_t * list_new(size_t elem_size)
Definition list.c:32
void list_pop_front(list_t *list)
Definition list.c:103
void list_clear(list_t *list)
Definition list.c:47
void list_push_back(list_t *list, void *elem)
Definition list.c:61
void list_remove(list_t *list, void *elem)
Definition list.c:159
size_t list_size(const list_t *list)
Definition list.c:59
struct list_node * next
Definition list.h:24
struct list_node * prev
Definition list.h:26
void * data
Definition list.h:22
Definition list.h:34
size_t elem_size
Definition list.h:42
list_node_t * tail
Definition list.h:38
size_t size
Definition list.h:40
list_node_t * head
Definition list.h:36