1 /*
2 * uhub - A tiny ADC p2p connection hub
3 * Copyright (C) 2007-2014, Jan Vidar Krey
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "uhub.h"
21
list_create()22 struct linked_list* list_create()
23 {
24 struct linked_list* list = NULL;
25 list = (struct linked_list*) hub_malloc_zero(sizeof(struct linked_list));
26 if (list == NULL)
27 return NULL;
28 return list;
29 }
30
31
list_destroy(struct linked_list * list)32 void list_destroy(struct linked_list* list)
33 {
34 if (list)
35 {
36 uhub_assert(list->size == 0);
37 uhub_assert(list->first == NULL);
38 uhub_assert(list->last == NULL);
39 hub_free(list);
40 }
41 }
42
dummy_free(void * ptr)43 static void dummy_free(void* ptr)
44 {
45 }
46
list_clear(struct linked_list * list,void (* free_handle)(void * ptr))47 void list_clear(struct linked_list* list, void (*free_handle)(void* ptr))
48 {
49 struct node* node = list->first;
50 struct node* tmp = NULL;
51 if (free_handle == NULL)
52 free_handle = &dummy_free;
53 while (node)
54 {
55 tmp = node->next;
56 free_handle(node->ptr);
57 hub_free(node);
58 node = tmp;
59 }
60 memset(list, 0, sizeof(struct linked_list));
61 }
62
63
list_append(struct linked_list * list,void * data_ptr)64 void list_append(struct linked_list* list, void* data_ptr)
65 {
66 struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
67 if (!new_node)
68 {
69 LOG_FATAL("Unable to allocate memory");
70 return;
71 }
72 new_node->ptr = data_ptr;
73
74 if (list->last)
75 {
76 list->last->next = new_node;
77 new_node->prev = list->last;
78 }
79 else
80 {
81 list->first = new_node;
82 }
83
84 list->last = new_node;
85 list->size++;
86 }
87
list_append_list(struct linked_list * list,struct linked_list * other)88 void list_append_list(struct linked_list* list, struct linked_list* other)
89 {
90 /* Anything to move? */
91 if (!other->size)
92 return;
93
94 if (!list->size)
95 {
96 /* If the list is empty, just move the pointers */
97 list->size = other->size;
98 list->first = other->first;
99 list->last = other->last;
100 list->iterator = other->iterator;
101 }
102 else
103 {
104 other->first->prev = list->last;
105 list->last->next = other->first;
106 list->last = other->last;
107 list->size += other->size;
108 }
109
110 /* Make sure the original list appears empty */
111 other->size = 0;
112 other->first = NULL;
113 other->last = NULL;
114 other->iterator = NULL;
115 }
116
117
list_remove(struct linked_list * list,void * data_ptr)118 void list_remove(struct linked_list* list, void* data_ptr)
119 {
120 struct node* node = list->first;
121 uhub_assert(data_ptr);
122
123 list->iterator = NULL;
124
125 while (node)
126 {
127 if (node->ptr == data_ptr)
128 {
129 if (node->next)
130 node->next->prev = node->prev;
131
132 if (node->prev)
133 node->prev->next = node->next;
134
135 if (node == list->last)
136 list->last = node->prev;
137
138 if (node == list->first)
139 list->first = node->next;
140
141 hub_free(node);
142
143 list->size--;
144 return;
145 }
146 node = node->next;
147 }
148 }
149
list_remove_first(struct linked_list * list,void (* free_handle)(void * ptr))150 void list_remove_first(struct linked_list* list, void (*free_handle)(void* ptr))
151 {
152 struct node* node = list->first;
153
154 list->iterator = NULL;
155
156 if (!node)
157 return;
158
159 list->first = node->next;
160
161 if (list->first)
162 list->first->prev = NULL;
163
164 if (list->last == node)
165 list->last = NULL;
166
167 list->size--;
168
169 if (free_handle)
170 free_handle(node->ptr);
171 hub_free(node);
172 }
173
174
list_size(struct linked_list * list)175 size_t list_size(struct linked_list* list)
176 {
177 return list->size;
178 }
179
180
list_get_index(struct linked_list * list,size_t offset)181 void* list_get_index(struct linked_list* list, size_t offset)
182 {
183 struct node* node = list->first;
184 size_t n = 0;
185 for (n = 0; n < list->size; n++)
186 {
187 if (n == offset)
188 {
189 return node->ptr;
190 }
191 node = node->next;
192 }
193 return NULL;
194 }
195
196
list_get_first(struct linked_list * list)197 void* list_get_first(struct linked_list* list)
198 {
199 list->iterator = list->first;
200 if (list->iterator == NULL)
201 return NULL;
202
203 return list->iterator->ptr;
204 }
205
list_get_first_node(struct linked_list * list)206 struct node* list_get_first_node(struct linked_list* list)
207 {
208 list->iterator = list->first;
209 if (list->iterator == NULL)
210 return NULL;
211
212 return list->iterator;
213 }
214
list_get_last(struct linked_list * list)215 void* list_get_last(struct linked_list* list)
216 {
217 list->iterator = list->last;
218 if (list->iterator == NULL)
219 return NULL;
220
221 return list->iterator->ptr;
222 }
223
list_get_last_node(struct linked_list * list)224 struct node* list_get_last_node(struct linked_list* list)
225 {
226 list->iterator = list->last;
227 if (list->iterator == NULL)
228 return NULL;
229
230 return list->iterator;
231
232 }
233
list_get_next(struct linked_list * list)234 void* list_get_next(struct linked_list* list)
235 {
236 if (list->iterator == NULL)
237 list->iterator = list->first;
238 else
239 list->iterator = list->iterator->next;
240
241 if (list->iterator == NULL)
242 return NULL;
243
244 return list->iterator->ptr;
245 }
246
247
list_get_prev(struct linked_list * list)248 void* list_get_prev(struct linked_list* list)
249 {
250 if (list->iterator == NULL)
251 return NULL;
252
253 list->iterator = list->iterator->prev;
254
255 if (list->iterator == NULL)
256 return NULL;
257
258 return list->iterator->ptr;
259 }
260
261