5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2000 - 2005 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
35 * This is slower than SilcList because this requires one extra memory
36 * allocation when adding new entries to the list. The context is probably
37 * allocated already and the new list entry requires one additional memory
38 * allocation. The memory allocation and freeing is done automatically in
39 * the API and does not show to the caller.
43 /****s* silcutil/SilcDListAPI/SilcDList
47 * typedef struct { ... } *SilcDList;
51 * This is the actual SilcDList object that is used by application.
52 * Application defines this object and adds contexts to this list with
53 * Dynamic List Interface functions.
57 typedef struct SilcDListStruct {
64 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
65 directly by the application. */
66 typedef struct SilcDListEntryStruct {
68 struct SilcDListEntryStruct *next;
69 struct SilcDListEntryStruct *prev;
72 /****f* silcutil/SilcDListAPI/silc_dlist_init
77 * SilcDList silc_dlist_init(void);
81 * Initializes SilcDList.
86 SilcDList silc_dlist_init(void)
90 list = (SilcDList)silc_malloc(sizeof(*list));
93 list->current = list->prev = NULL;
94 silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
99 /****f* silcutil/SilcDListAPI/silc_dlist_uninit
104 * void silc_dlist_uninit(SilcDList list);
108 * Uninits and frees all memory. Must be called to free memory. Does NOT
109 * free the contexts saved by caller.
114 void silc_dlist_uninit(SilcDList list)
118 silc_list_start(list->list);
119 while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
120 silc_list_del(list->list, e);
127 /****f* silcutil/SilcDListAPI/silc_dlist_count
132 * int silc_dlist_count(SilcDList list);
136 * Return the number of entries in the list.
141 int silc_dlist_count(SilcDList list)
143 return silc_list_count(list->list);
146 /****f* silcutil/SilcDListAPI/silc_dlist_start
151 * void silc_dlist_start(SilcDList list);
155 * Set the start of the list. This prepares the list for traversing entries
156 * from the start of the list towards end of the list.
161 void silc_dlist_start(SilcDList list)
163 silc_list_start(list->list);
164 list->current = list->prev = NULL;
167 /****f* silcutil/SilcDListAPI/silc_dlist_end
172 * void silc_dlist_end(SilcDList list);
176 * Set the end of the list. This prepares the list for traversing entries
177 * from the end of the list towards start of the list.
182 void silc_dlist_end(SilcDList list)
184 silc_list_end(list->list);
185 list->current = list->prev = NULL;
188 /****f* silcutil/SilcDListAPI/silc_dlist_add
193 * SilcBool silc_dlist_add(SilcDList list, void *context);
197 * Adds new entry to the list. This is the default function to add new
198 * entries to the list.
203 SilcBool silc_dlist_add(SilcDList list, void *context)
205 SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
208 e->context = context;
209 silc_list_add(list->list, e);
213 /****f* silcutil/SilcDList/silc_dlist_insert
218 * SilcBool silc_dlist_insert(SilcDList list, void *context);
222 * Insert new entry to the list between current and previous entry.
223 * If list is at the start this adds the entry at head of the list.
224 * Use silc_dlist_add to add at the end of the list.
229 SilcBool silc_dlist_insert(SilcDList list, void *context)
231 SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
234 e->context = context;
235 silc_list_insert(list->list, list->prev, e);
239 /****f* silcutil/SilcDListAPI/silc_dlist_del
244 * void silc_dlist_del(SilcDList list, void *context);
248 * Remove entry from the list. Returns < 0 on error, 0 otherwise.
253 void silc_dlist_del(SilcDList list, void *context)
257 silc_list_start(list->list);
258 while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
259 if (e->context == context) {
260 silc_list_del(list->list, e);
261 #if defined(SILC_DEBUG)
262 memset(e, 'F', sizeof(*e));
264 if (list->current == e)
265 list->current = NULL;
274 /****f* silcutil/SilcDListAPI/silc_dlist_get
279 * void *silc_dlist_get(SilcDList list);
283 * Returns current entry from the list and moves the list pointer forward
284 * so that calling this next time returns the next entry from the list.
285 * This can be used to traverse the list. Return SILC_LIST_END when the
286 * entire list has been traversed. Later, silc_list_start (or
287 * silc_dlist_end) must be called again when re-starting list traversing.
291 * // Traverse the list from the beginning to the end
292 * silc_dlist_start(list)
293 * while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
300 void *silc_dlist_get(SilcDList list)
303 list->prev = list->current;
304 list->current = e = (SilcDListEntry)silc_list_get(list->list);
305 if (e != SILC_LIST_END)
307 return SILC_LIST_END;