Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / silcdlist.h
1 /*
2
3   silcdlist.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2000 - 2003 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 } *SilcDList;
60 /***/
61
62 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
63    directly by the application. */
64 typedef struct SilcDListEntryStruct {
65   void *context;
66   struct SilcDListEntryStruct *next;
67   struct SilcDListEntryStruct *prev;
68 } *SilcDListEntry;
69
70 /****f* silcutil/SilcDListAPI/silc_dlist_init
71  *
72  * SYNOPSIS
73  *
74  *    static inline
75  *    SilcDList silc_dlist_init(void);
76  *
77  * DESCRIPTION
78  *
79  *    Initializes SilcDList.
80  *
81  ***/
82
83 static inline
84 SilcDList silc_dlist_init(void)
85 {
86   SilcDList list;
87
88   list = (SilcDList)silc_malloc(sizeof(*list));
89   if (!list)
90     return NULL;
91   silc_list_init_prev(list->list, struct SilcDListEntryStruct, next, prev);
92
93   return list;
94 }
95
96 /****f* silcutil/SilcDListAPI/silc_dlist_uninit
97  *
98  * SYNOPSIS
99  *
100  *    static inline
101  *    void silc_dlist_uninit(SilcDList list);
102  *
103  * DESCRIPTION
104  *
105  *    Uninits and frees all memory. Must be called to free memory. Does NOT
106  *    free the contexts saved by caller.
107  *
108  ***/
109
110 static inline
111 void silc_dlist_uninit(SilcDList list)
112 {
113   if (list) {
114     SilcDListEntry e;
115     silc_list_start(list->list);
116     while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
117       silc_list_del(list->list, e);
118       silc_free(e);
119     }
120     silc_free(list);
121   }
122 }
123
124 /****f* silcutil/SilcDListAPI/silc_dlist_count
125  *
126  * SYNOPSIS
127  *
128  *    static inline
129  *    int silc_dlist_count(SilcDList list);
130  *
131  * DESCRIPTION
132  *
133  * Return the number of entries in the list.
134  *
135  ***/
136
137 static inline
138 int silc_dlist_count(SilcDList list)
139 {
140   return silc_list_count(list->list);
141 }
142
143 /****f* silcutil/SilcDListAPI/silc_dlist_start
144  *
145  * SYNOPSIS
146  *
147  *    static inline
148  *    void silc_dlist_start(SilcDList list);
149  *
150  * DESCRIPTION
151  *
152  *    Set the start of the list. This prepares the list for traversing entries
153  *    from the start of the list towards end of the list.
154  *
155  ***/
156
157 static inline
158 void silc_dlist_start(SilcDList list)
159 {
160   silc_list_start(list->list);
161 }
162
163 /****f* silcutil/SilcDListAPI/silc_dlist_end
164  *
165  * SYNOPSIS
166  *
167  *    static inline
168  *    void silc_dlist_end(SilcDList list);
169  *
170  * DESCRIPTION
171  *
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.
174  *
175  ***/
176
177 static inline
178 void silc_dlist_end(SilcDList list)
179 {
180   silc_list_end(list->list);
181 }
182
183 /****f* silcutil/SilcDListAPI/silc_dlist_add
184  *
185  * SYNOPSIS
186  *
187  *    static inline
188  *    void silc_dlist_add(SilcDList list, void *context);
189  *
190  * DESCRIPTION
191  *
192  *    Adds new entry to the list. This is the default function to add new
193  *    entries to the list.
194  *
195  ***/
196
197 static inline
198 void silc_dlist_add(SilcDList list, void *context)
199 {
200   SilcDListEntry e = (SilcDListEntry)silc_malloc(sizeof(*e));
201   if (!e)
202     return;
203   e->context = context;
204   silc_list_add(list->list, e);
205 }
206
207 /****f* silcutil/SilcDListAPI/silc_dlist_del
208  *
209  * SYNOPSIS
210  *
211  *    static inline
212  *    void silc_dlist_del(SilcDList list, void *context);
213  *
214  * DESCRIPTION
215  *
216  *    Remove entry from the list. Returns < 0 on error, 0 otherwise.
217  *
218  ***/
219
220 static inline
221 void silc_dlist_del(SilcDList list, void *context)
222 {
223   SilcDListEntry e;
224
225   silc_list_start(list->list);
226   while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
227     if (e->context == context) {
228       silc_list_del(list->list, e);
229 #if defined(SILC_DEBUG)
230       memset(e, 'F', sizeof(*e));
231 #endif
232       silc_free(e);
233       break;
234     }
235   }
236 }
237
238 /****f* silcutil/SilcDListAPI/silc_dlist_get
239  *
240  * SYNOPSIS
241  *
242  *    static inline
243  *    void *silc_dlist_get(SilcDList list);
244  *
245  * DESCRIPTION
246  *
247  *    Returns current entry from the list and moves the list pointer forward
248  *    so that calling this next time returns the next entry from the list.
249  *    This can be used to traverse the list. Return SILC_LIST_END when the
250  *    entire list has been traversed. Later, silc_list_start (or
251  *    silc_dlist_end) must be called again when re-starting list traversing.
252  *
253  * EXAMPLE
254  *
255  *    // Traverse the list from the beginning to the end
256  *    silc_dlist_start(list)
257  *    while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
258  *      ...
259  *    }
260  *
261  ***/
262
263 static inline
264 void *silc_dlist_get(SilcDList list)
265 {
266   SilcDListEntry e = (SilcDListEntry)silc_list_get(list->list);
267   if (e != SILC_LIST_END)
268     return e->context;
269   return SILC_LIST_END;
270 }
271
272 #endif