5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
25 /****h* silcutil/SILC Dynamic List Interface
29 * SILC Dynamic List API can be used to add opaque contexts to list that
30 * will automatically allocate list entries. Normal SILC List API cannot
31 * be used for this purpose because in that case the context passed to the
32 * list must be defined as list structure already. This is not the case in
33 * SilcDList. But SilcDList is a bit slower than SilcList because it
34 * requires memory allocation when adding new entries to the list.
36 * SILC Dynamic List is not thread-safe. If the same list context must be
37 * used in multithreaded environment concurrency control must be employed.
41 /****s* silcutil/SilcDListAPI/SilcDList
45 * typedef struct { ... } *SilcDList;
49 * This is the actual SilcDList object that is used by application.
50 * Application defines this object and adds contexts to this list with
51 * Dynamic List Interface functions.
54 typedef struct SilcDListStruct {
60 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
61 directly by the application. */
62 typedef struct SilcDListEntryStruct {
64 struct SilcDListEntryStruct *next;
65 struct SilcDListEntryStruct *prev;
68 /****f* silcutil/SilcDListAPI/silc_dlist_init
73 * SilcDList silc_dlist_init(void);
77 * Initializes SilcDList.
82 SilcDList silc_dlist_init(void)
86 list = (SilcDList)silc_malloc(sizeof(*list));
89 list->current = list->prev = NULL;
90 silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
95 /****f* silcutil/SilcDListAPI/silc_dlist_uninit
100 * void silc_dlist_uninit(SilcDList list);
104 * Uninits and frees all memory. Must be called to free memory. Does NOT
105 * free the contexts saved by caller.
110 void silc_dlist_uninit(SilcDList list)
114 silc_list_start(list->list);
115 while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
116 silc_list_del(list->list, e);
123 /****f* silcutil/SilcDListAPI/silc_dlist_count
128 * int silc_dlist_count(SilcDList list);
132 * Return the number of entries in the list.
137 int silc_dlist_count(SilcDList list)
139 return silc_list_count(list->list);
142 /****f* silcutil/SilcDListAPI/silc_dlist_start
147 * void silc_dlist_start(SilcDList list);
151 * Set the start of the list. This prepares the list for traversing entries
152 * from the start of the list towards end of the list.
157 void silc_dlist_start(SilcDList list)
159 silc_list_start(list->list);
160 list->current = list->prev = NULL;
163 /****f* silcutil/SilcDListAPI/silc_dlist_end
168 * void silc_dlist_end(SilcDList list);
172 * Set the end of the list. This prepares the list for traversing entries
173 * from the end of the list towards start of the list.
178 void silc_dlist_end(SilcDList list)
180 silc_list_end(list->list);
181 list->current = list->prev = NULL;
184 /****f* silcutil/SilcDListAPI/silc_dlist_add
189 * SilcBool silc_dlist_add(SilcDList list, void *context);
193 * Adds new entry to the list. This is the default function to add new
194 * entries to the list.
199 SilcBool silc_dlist_add(SilcDList list, void *context)
201 SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
202 if (silc_unlikely(!e))
204 e->context = context;
205 silc_list_add(list->list, e);
209 /****f* silcutil/SilcDList/silc_dlist_insert
214 * SilcBool silc_dlist_insert(SilcDList list, void *context);
218 * Insert new entry to the list between current and previous entry.
219 * If list is at the start this adds the entry at head of the list.
220 * Use silc_dlist_add to add at the end of the list.
225 SilcBool silc_dlist_insert(SilcDList list, void *context)
227 SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
228 if (silc_unlikely(!e))
230 e->context = context;
231 silc_list_insert(list->list, list->prev, e);
235 /****f* silcutil/SilcDListAPI/silc_dlist_del
240 * void silc_dlist_del(SilcDList list, void *entry);
244 * Remove entry from the list.
249 void silc_dlist_del(SilcDList list, void *entry)
253 silc_list_start(list->list);
254 while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
255 if (e->context == entry) {
256 silc_list_del(list->list, e);
257 #if defined(SILC_DEBUG)
258 memset(e, 'F', sizeof(*e));
260 if (list->current == e)
261 list->current = NULL;
270 /****f* silcutil/SilcDListAPI/silc_dlist_get
275 * void *silc_dlist_get(SilcDList list);
279 * Returns current entry from the list and moves the list pointer forward
280 * so that calling this next time returns the next entry from the list.
281 * This can be used to traverse the list. Return SILC_LIST_END when the
282 * entire list has been traversed. Later, silc_list_start (or
283 * silc_dlist_end) must be called again when re-starting list traversing.
287 * // Traverse the list from the beginning to the end
288 * silc_dlist_start(list)
289 * while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
296 void *silc_dlist_get(SilcDList list)
299 list->prev = list->current;
300 list->current = e = (SilcDListEntry)silc_list_get(list->list);
301 if (e != SILC_LIST_END)
303 return SILC_LIST_END;