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