tommylist.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
97#ifndef __TOMMYLIST_H
98#define __TOMMYLIST_H
99
100#include "tommytypes.h"
101
102/******************************************************************************/
103/* list */
104
109
114tommy_inline void tommy_list_init(tommy_list* list)
115{
116 *list = 0;
117}
118
124{
125 return *list;
126}
127
133{
134 tommy_node* head = tommy_list_head(list);
135
136 if (!head)
137 return 0;
138
139 return head->prev;
140}
141
147tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node)
148{
149 /* one element "circular" prev list */
150 node->prev = node;
151
152 /* one element "0 terminated" next list */
153 node->next = 0;
154
155 *list = node;
156}
157
164tommy_inline void tommy_list_insert_head_not_empty(tommy_list* list, tommy_node* node)
165{
166 tommy_node* head = tommy_list_head(list);
167
168 /* insert in the "circular" prev list */
169 node->prev = head->prev;
170 head->prev = node;
171
172 /* insert in the "0 terminated" next list */
173 node->next = head;
174
175 *list = node;
176}
177
184tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node)
185{
186 /* insert in the "circular" prev list */
187 node->prev = head->prev;
188 head->prev = node;
189
190 /* insert in the "0 terminated" next list */
191 node->next = 0;
192 node->prev->next = node;
193}
194
201tommy_inline void tommy_list_insert_head(tommy_list* list, tommy_node* node, void* data)
202{
203 tommy_node* head = tommy_list_head(list);
204
205 if (head)
206 tommy_list_insert_head_not_empty(list, node);
207 else
208 tommy_list_insert_first(list, node);
209
210 node->data = data;
211}
212
219tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data)
220{
221 tommy_node* head = tommy_list_head(list);
222
223 if (head)
224 tommy_list_insert_tail_not_empty(head, node);
225 else
226 tommy_list_insert_first(list, node);
227
228 node->data = data;
229}
230
240tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node)
241{
242 tommy_node* head = tommy_list_head(list);
243
244 /* remove from the "circular" prev list */
245 if (node->next)
246 node->next->prev = node->prev;
247 else
248 head->prev = node->prev; /* the last */
249
250 /* remove from the "0 terminated" next list */
251 if (head == node)
252 *list = node->next; /* the new head, in case 0 */
253 else
254 node->prev->next = node->next;
255
256 return node->data;
257}
258
266tommy_inline void tommy_list_concat(tommy_list* first, tommy_list* second)
267{
268 tommy_node* first_head;
269 tommy_node* first_tail;
270 tommy_node* second_head;
271
272 /* if the second is empty, nothing to do */
273 second_head = tommy_list_head(second);
274 if (second_head == 0)
275 return;
276
277 /* if the first is empty, copy the second */
278 first_head = tommy_list_head(first);
279 if (first_head == 0) {
280 *first = *second;
281 return;
282 }
283
284 /* tail of the first list */
285 first_tail = first_head->prev;
286
287 /* set the "circular" prev list */
288 first_head->prev = second_head->prev;
289 second_head->prev = first_tail;
290
291 /* set the "0 terminated" next list */
292 first_tail->next = second_head;
293}
294
303
309{
310 return tommy_list_head(list) == 0;
311}
312
318{
319 tommy_size_t count = 0;
320 tommy_node* i = tommy_list_head(list);
321
322 while (i) {
323 ++count;
324 i = i->next;
325 }
326
327 return count;
328}
329
358tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func)
359{
360 tommy_node* node = tommy_list_head(list);
361
362 while (node) {
363 void* data = node->data;
364 node = node->next;
365 func(data);
366 }
367}
368
372tommy_inline void tommy_list_foreach_arg(tommy_list* list, tommy_foreach_arg_func* func, void* arg)
373{
374 tommy_node* node = tommy_list_head(list);
375
376 while (node) {
377 void* data = node->data;
378 node = node->next;
379 func(arg, data);
380 }
381}
382
383#endif
Data structure node.
Definition: tommytypes.h:211
struct tommy_node_struct * next
Next node.
Definition: tommytypes.h:216
struct tommy_node_struct * prev
Previous node.
Definition: tommytypes.h:222
void * data
Pointer to the object containing the node.
Definition: tommytypes.h:228
void tommy_list_foreach_arg(tommy_list *list, tommy_foreach_arg_func *func, void *arg)
Calls the specified function with an argument for each element in the list.
Definition: tommylist.h:372
void tommy_list_init(tommy_list *list)
Initializes the list.
Definition: tommylist.h:114
void tommy_list_insert_head(tommy_list *list, tommy_node *node, void *data)
Inserts an element at the head of a list.
Definition: tommylist.h:201
tommy_node * tommy_list
Doubly linked list type.
Definition: tommylist.h:108
void * tommy_list_remove_existing(tommy_list *list, tommy_node *node)
Removes an element from the list.
Definition: tommylist.h:240
tommy_node * tommy_list_tail(tommy_list *list)
Gets the tail of the list.
Definition: tommylist.h:132
void tommy_list_insert_tail(tommy_list *list, tommy_node *node, void *data)
Inserts an element at the tail of a list.
Definition: tommylist.h:219
void tommy_list_concat(tommy_list *first, tommy_list *second)
Concats two lists.
Definition: tommylist.h:266
tommy_bool_t tommy_list_empty(tommy_list *list)
Checks if empty.
Definition: tommylist.h:308
TOMMY_API void tommy_list_sort(tommy_list *list, tommy_compare_func *cmp)
Sorts a list.
tommy_size_t tommy_list_count(tommy_list *list)
Gets the number of elements.
Definition: tommylist.h:317
tommy_node * tommy_list_head(tommy_list *list)
Gets the head of the list.
Definition: tommylist.h:123
void tommy_list_foreach(tommy_list *list, tommy_foreach_func *func)
Calls the specified function for each element in the list.
Definition: tommylist.h:358
Generic types.
int tommy_compare_func(const void *obj_a, const void *obj_b)
Compare function for elements.
Definition: tommytypes.h:269
uint64_t tommy_size_t
Generic size_t type.
Definition: tommytypes.h:60
void tommy_foreach_func(void *obj)
Foreach function.
Definition: tommytypes.h:318
void tommy_foreach_arg_func(void *arg, void *obj)
Foreach function with an argument.
Definition: tommytypes.h:325
int tommy_bool_t
Generic boolean type.
Definition: tommytypes.h:72