aboutsummaryrefslogtreecommitdiff
path: root/src/util/container_slist.c
diff options
context:
space:
mode:
authorNils Durner <durner@gnunet.org>2009-10-03 15:36:09 +0000
committerNils Durner <durner@gnunet.org>2009-10-03 15:36:09 +0000
commitd5f3c16326273625b37cd0f2d5b4716ac650f51d (patch)
tree558efc6c02137036c8984fdb24b966117e3470d2 /src/util/container_slist.c
parent382d50480d96cbd5b5b7a45997cfe6f33b914a3b (diff)
downloadgnunet-d5f3c16326273625b37cd0f2d5b4716ac650f51d.tar.gz
gnunet-d5f3c16326273625b37cd0f2d5b4716ac650f51d.zip
use singly linked lists instead of vectors
Diffstat (limited to 'src/util/container_slist.c')
-rw-r--r--src/util/container_slist.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/util/container_slist.c b/src/util/container_slist.c
new file mode 100644
index 000000000..c279bb2ea
--- /dev/null
+++ b/src/util/container_slist.c
@@ -0,0 +1,270 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/container_slist.c
23 * @brief Implementation of a singly-linked list
24 * @author Nils Durner
25 */
26
27#include "platform.h"
28#include "gnunet_container_lib.h"
29
30struct GNUNET_CONTAINER_SList_Elem
31{
32 void *elem;
33 size_t len;
34 int disp;
35 struct GNUNET_CONTAINER_SList_Elem *next;
36};
37
38struct GNUNET_CONTAINER_SList
39{
40 struct GNUNET_CONTAINER_SList_Elem head;
41};
42
43struct GNUNET_CONTAINER_SList_Iterator
44{
45 struct GNUNET_CONTAINER_SList_Elem *last;
46 struct GNUNET_CONTAINER_SList_Elem *elem;
47};
48
49/**
50 * Create a new element that is to be inserted into the list
51 * @internal
52 * @param disp memory disposition
53 * @param buf payload buffer
54 * @param len length of the buffer
55 * @return a new element
56 */
57static struct GNUNET_CONTAINER_SList_Elem *
58create_elem (int disp, const void *buf, size_t len)
59{
60 struct GNUNET_CONTAINER_SList_Elem *e;
61
62 e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem));
63 e->disp = disp;
64 if (disp == GNUNET_MEM_DISP_TRANSIENT)
65 {
66 e->elem = GNUNET_malloc (len);
67 memcpy (e->elem, buf, len);
68 }
69 else
70 e->elem = (void *) buf;
71 e->len = len;
72
73 return e;
74}
75
76/**
77 * Add a new element to the list
78 * @param l list
79 * @param disp memory disposition
80 * @param buf payload buffer
81 * @param len length of the buffer
82 */
83void
84GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, int disp,
85 const void *buf, size_t len)
86{
87 struct GNUNET_CONTAINER_SList_Elem *e;
88
89 e = create_elem (disp, buf, len);
90 e->next = l->head.next;
91 l->head.next = e;
92}
93
94/**
95 * Create a new singly linked list
96 * @return the new list
97 */
98struct GNUNET_CONTAINER_SList *
99GNUNET_CONTAINER_slist_create ()
100{
101 struct GNUNET_CONTAINER_SList *ret;
102
103 ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList));
104 if (NULL == ret)
105 return NULL;
106
107 memset (&ret->head, 0, sizeof (struct GNUNET_CONTAINER_SList));
108
109 return ret;
110}
111
112/**
113 * Destroy a singly linked list
114 * @param l the list to be destroyed
115 */
116void
117GNUNET_CONTAINER_slist_destroy (struct GNUNET_CONTAINER_SList *l)
118{
119 GNUNET_CONTAINER_slist_clear (l);
120 GNUNET_free (l);
121}
122
123/**
124 * Return the beginning of a list
125 * @param l list
126 * @return iterator pointing to the beginning
127 */
128const struct GNUNET_CONTAINER_SList_Iterator *
129GNUNET_CONTAINER_slist_begin (const struct GNUNET_CONTAINER_SList *l)
130{
131 struct GNUNET_CONTAINER_SList_Iterator *ret;
132
133 ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Iterator));
134 ret->elem = l->head.next;
135 ret->last = (struct GNUNET_CONTAINER_SList_Elem *) &l->head;
136 return ret;
137}
138
139/**
140 * Clear a list
141 * @param l list
142 */
143void
144GNUNET_CONTAINER_slist_clear (struct GNUNET_CONTAINER_SList *l)
145{
146 struct GNUNET_CONTAINER_SList_Elem *e, *n;
147
148 e = l->head.next;
149 while (e != NULL)
150 {
151 if (e->disp != GNUNET_MEM_DISP_STATIC)
152 GNUNET_free (e->elem);
153 n = e->next;
154 GNUNET_free (e);
155 e = n;
156 }
157 l->head.next = NULL;
158}
159
160/**
161 * Check if a list contains a certain element
162 * @param l list
163 * @param buf payload buffer to find
164 * @param lenght of the payload
165 */
166int
167GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l,
168 const void *buf, size_t len)
169{
170 struct GNUNET_CONTAINER_SList_Elem *e;
171
172 for (e = l->head.next; e != NULL; e = e->next)
173 if (e->len == len && memcmp (buf, e->elem, len) == 0)
174 return GNUNET_YES;
175
176 return GNUNET_NO;
177}
178
179/**
180 * Count the elements of a list
181 * @param l list
182 * @return number of elements in the list
183 */
184int
185GNUNET_CONTAINER_slist_count (const struct GNUNET_CONTAINER_SList *l)
186{
187 int n;
188 struct GNUNET_CONTAINER_SList_Elem *e;
189
190 for (n = 0, e = l->head.next; e != NULL; e = e->next)
191 n++;
192
193 return n;
194}
195
196/**
197 * Remove an element from the list
198 * @param i iterator that points to the element to be removed
199 */
200void
201GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i)
202{
203 struct GNUNET_CONTAINER_SList_Elem *next;
204
205 next = i->elem->next;
206 i->last->next = next;
207 if (i->elem->disp != GNUNET_MEM_DISP_STATIC)
208 GNUNET_free (i->elem->elem);
209 GNUNET_free (i->elem);
210 i->elem = next;
211}
212
213/**
214 * Insert an element into a list at a specific position
215 * @param before where to insert the new element
216 * @param disp memory disposition
217 * @param buf payload buffer
218 * @param len length of the payload
219 */
220void
221GNUNET_CONTAINER_slist_insert (struct GNUNET_CONTAINER_SList_Iterator *before,
222 int disp, const void *buf, size_t len)
223{
224 struct GNUNET_CONTAINER_SList_Elem *e;
225
226 e = create_elem (disp, buf, len);
227 e->next = before->elem;
228 before->last->next = e;
229}
230
231/**
232 * Advance an iterator to the next element
233 * @param i iterator
234 * @return GNUNET_YES on success, GNUNET_NO if the end has been reached
235 */
236int
237GNUNET_CONTAINER_slist_next (struct GNUNET_CONTAINER_SList_Iterator *i)
238{
239 i->last = i->elem;
240 i->elem = i->elem->next;
241
242 return i->elem != NULL;
243}
244
245/**
246 * Check if an iterator points beyond the end of a list
247 * @param i iterator
248 * @return GNUNET_YES if the end has been reached, GNUNET_NO if the iterator
249 * points to a valid element
250 */
251int
252GNUNET_CONTAINER_slist_end (struct GNUNET_CONTAINER_SList_Iterator *i)
253{
254 return i->elem == NULL;
255}
256
257/**
258 * Retrieve the element at a specific position in a list
259 * @param i iterator
260 * @param len payload length
261 * @return payload
262 */
263void *
264GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i,
265 size_t * len)
266{
267 if (len)
268 *len = i->elem->len;
269 return i->elem->elem;
270}