Added SILC Server library.
[silc.git] / lib / silcutil / silcdlist.h
1 /*
2
3   silcdlist.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2000 - 2005 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 #ifndef SILDCLIST_H
21 #define SILDCLIST_H
22
23 #include "silclist.h"
24
25 /****h* silcutil/SILC Dynamic List Interface
26  *
27  * DESCRIPTION
28  *
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.
34  *
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.
40  *
41  ***/
42
43 /****s* silcutil/SilcDListAPI/SilcDList
44  *
45  * NAME
46  *
47  *    typedef struct { ... } *SilcDList;
48  *
49  * DESCRIPTION
50  *
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.
54  *
55  * SOURCE
56  */
57 typedef struct SilcDListStruct {
58   SilcList list;
59   void *current;
60   void *prev;
61 } *SilcDList;
62 /***/
63
64 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
65    directly by the application. */
66 typedef struct SilcDListEntryStruct {
67   void *context;
68   struct SilcDListEntryStruct *next;
69   struct SilcDListEntryStruct *prev;
70 } *SilcDListEntry;
71
72 /****f* silcutil/SilcDListAPI/silc_dlist_init
73  *
74  * SYNOPSIS
75  *
76  *    static inline
77  *    SilcDList silc_dlist_init(void);
78  *
79  * DESCRIPTION
80  *
81  *    Initializes SilcDList.
82  *
83  ***/
84
85 static inline
86 SilcDList silc_dlist_init(void)
87 {
88   SilcDList list;
89
90   list = (SilcDList)silc_malloc(sizeof(*list));
91   if (!list)
92     return NULL;
93   list->current = list->prev = NULL;
94   silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
95
96   return list;
97 }
98
99 /****f* silcutil/SilcDListAPI/silc_dlist_uninit
100  *
101  * SYNOPSIS
102  *
103  *    static inline
104  *    void silc_dlist_uninit(SilcDList list);
105  *
106  * DESCRIPTION
107  *
108  *    Uninits and frees all memory. Must be called to free memory. Does NOT
109  *    free the contexts saved by caller.
110  *
111  ***/
112
113 static inline
114 void silc_dlist_uninit(SilcDList list)
115 {
116   if (list) {
117     SilcDListEntry e;
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);
121       silc_free(e);
122     }
123     silc_free(list);
124   }
125 }
126
127 /****f* silcutil/SilcDListAPI/silc_dlist_count
128  *
129  * SYNOPSIS
130  *
131  *    static inline
132  *    int silc_dlist_count(SilcDList list);
133  *
134  * DESCRIPTION
135  *
136  * Return the number of entries in the list.
137  *
138  ***/
139
140 static inline
141 int silc_dlist_count(SilcDList list)
142 {
143   return silc_list_count(list->list);
144 }
145
146 /****f* silcutil/SilcDListAPI/silc_dlist_start
147  *
148  * SYNOPSIS
149  *
150  *    static inline
151  *    void silc_dlist_start(SilcDList list);
152  *
153  * DESCRIPTION
154  *
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.
157  *
158  ***/
159
160 static inline
161 void silc_dlist_start(SilcDList list)
162 {
163   silc_list_start(list->list);
164   list->current = list->prev = NULL;
165 }
166
167 /****f* silcutil/SilcDListAPI/silc_dlist_end
168  *
169  * SYNOPSIS
170  *
171  *    static inline
172  *    void silc_dlist_end(SilcDList list);
173  *
174  * DESCRIPTION
175  *
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.
178  *
179  ***/
180
181 static inline
182 void silc_dlist_end(SilcDList list)
183 {
184   silc_list_end(list->list);
185   list->current = list->prev = NULL;
186 }
187
188 /****f* silcutil/SilcDListAPI/silc_dlist_add
189  *
190  * SYNOPSIS
191  *
192  *    static inline
193  *    SilcBool silc_dlist_add(SilcDList list, void *context);
194  *
195  * DESCRIPTION
196  *
197  *    Adds new entry to the list. This is the default function to add new
198  *    entries to the list.
199  *
200  ***/
201
202 static inline
203 SilcBool silc_dlist_add(SilcDList list, void *context)
204 {
205   SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
206   if (!e)
207     return FALSE;
208   e->context = context;
209   silc_list_add(list->list, e);
210   return TRUE;
211 }
212
213 /****f* silcutil/SilcDList/silc_dlist_insert
214  *
215  * SYNOPSIS
216  *
217  *    static inline
218  *    SilcBool silc_dlist_insert(SilcDList list, void *context);
219  *
220  * DESCRIPTION
221  *
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.
225  *
226  ***/
227
228 static inline
229 SilcBool silc_dlist_insert(SilcDList list, void *context)
230 {
231   SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
232   if (!e)
233     return FALSE;
234   e->context = context;
235   silc_list_insert(list->list, list->prev, e);
236   return TRUE;
237 }
238
239 /****f* silcutil/SilcDListAPI/silc_dlist_del
240  *
241  * SYNOPSIS
242  *
243  *    static inline
244  *    void silc_dlist_del(SilcDList list, void *context);
245  *
246  * DESCRIPTION
247  *
248  *    Remove entry from the list. Returns < 0 on error, 0 otherwise.
249  *
250  ***/
251
252 static inline
253 void silc_dlist_del(SilcDList list, void *context)
254 {
255   SilcDListEntry e;
256
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));
263 #endif
264       if (list->current == e)
265         list->current = NULL;
266       if (list->prev == e)
267         list->prev = NULL;
268       silc_free(e);
269       break;
270     }
271   }
272 }
273
274 /****f* silcutil/SilcDListAPI/silc_dlist_get
275  *
276  * SYNOPSIS
277  *
278  *    static inline
279  *    void *silc_dlist_get(SilcDList list);
280  *
281  * DESCRIPTION
282  *
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.
288  *
289  * EXAMPLE
290  *
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) {
294  *      ...
295  *    }
296  *
297  ***/
298
299 static inline
300 void *silc_dlist_get(SilcDList list)
301 {
302   SilcDListEntry e;
303   list->prev = list->current;
304   list->current = e = (SilcDListEntry)silc_list_get(list->list);
305   if (e != SILC_LIST_END)
306     return e->context;
307   return SILC_LIST_END;
308 }
309
310 #endif