d9f6d55267bfd19cbe45526237c4d5381b28a1c6
[silc.git] / lib / silcutil / silcdlist.h
1 /*
2
3   silcdlist.h
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 2000 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20
21 #ifndef SILDCLIST_H
22 #define SILDCLIST_H
23
24 #include "silclist.h"
25  
26 /****h* silcutil/SILC Dynamic List Interface
27  *
28  * DESCRIPTION
29  *
30  *    SILC Dynamic List API can be used to add opaque contexts to list that
31  *    will automatically allocate list entries.  Normal SILC List API cannot
32  *    be used for this purpose because in that case the context passed to the
33  *    list must be defined as list structure already.  This is not the case in
34  *    SilcDList.
35  *
36  *    This is slower than SilcList because this requires one extra memory
37  *    allocation when adding new entries to the list.  The context is probably
38  *    allocated already and the new list entry requires one additional memory
39  *    allocation.  The memory allocation and freeing is done automatically in
40  *    the API and does not show to the caller.
41  *
42  ***/
43
44 /****s* silcutil/SilcDListAPI/SilcDList
45  *
46  * NAME
47  *
48  *    typedef struct { ... } *SilcDList;
49  *
50  * DESCRIPTION
51  *
52  *    This is the actual SilcDList object that is used by application.
53  *    Application defines this object and adds contexts to this list with
54  *    Dynamic List Interface functions.
55  *
56  * SOURCE
57  */
58 typedef struct {
59   SilcList list;
60 } *SilcDList;
61 /***/
62
63 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
64    directly by the application. */
65 typedef struct SilcDListEntryStruct {
66   void *context;
67   struct SilcDListEntryStruct *next;
68 } *SilcDListEntry;
69
70 /****f* silcutil/SilcDListAPI/silc_dlist_init
71  *
72  * SYNOPSIS
73  * 
74  *    static inline
75  *    SilcDList silc_dlist_init();
76  *
77  * DESCRIPTION
78  *
79  *    Initializes SilcDList.
80  *
81  ***/
82
83 static inline
84 SilcDList silc_dlist_init()
85 {
86   SilcDList list;
87
88   list = (SilcDList)silc_calloc(1, sizeof(*list));
89   silc_list_init(list->list, struct SilcDListEntryStruct, next);
90
91   return list;
92 }
93
94 /****f* silcutil/SilcDListAPI/silc_dlist_uninit
95  *
96  * SYNOPSIS
97  *
98  *    static inline
99  *    void silc_dlist_uninit(SilcDList list);
100  *
101  * DESCRIPTION
102  *
103  *    Uninits and frees all memory. Must be called to free memory. Does NOT
104  *    free the contexts saved by caller.
105  *
106  ***/
107
108 static inline
109 void silc_dlist_uninit(SilcDList list)
110 {
111   if (list) {
112     SilcDListEntry e;
113     silc_list_start(list->list);
114     while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
115       silc_list_del(list->list, e);
116       silc_free(e);
117     }
118     silc_free(list);
119   }
120 }
121
122 /****f* silcutil/SilcDListAPI/silc_dlist_count
123  *
124  * SYNOPSIS
125  *
126  *    static inline
127  *    int silc_dlist_count(SilcDList list);
128  *
129  * DESCRIPTION
130  *
131  * Return the number of entries in the list.
132  *
133  ***/
134
135 static inline
136 int silc_dlist_count(SilcDList list)
137 {
138   return silc_list_count(list->list);
139 }
140
141 /****f* silcutil/SilcDListAPI/silc_dlist_start
142  *
143  * SYNOPSIS
144  *
145  *    static inline
146  *    void silc_dlist_start(SilcDList list);
147  *
148  * DESCRIPTION
149  *
150  *    Set the start of the list. This prepares the list for traversing entries
151  *    from the start of the list.
152  *
153  ***/
154
155 static inline
156 void silc_dlist_start(SilcDList list)
157 {
158   silc_list_start(list->list);
159 }
160
161 /****f* silcutil/SilcDListAPI/silc_dlist_add
162  *
163  * SYNOPSIS
164  *
165  *    static inline
166  *    void silc_dlist_add(SilcDList list, void *context);
167  *
168  * DESCRIPTION
169  *
170  *    Adds new entry to the list. This is the default function to add new
171  *    entries to the list.
172  *
173  ***/
174
175 static inline
176 void silc_dlist_add(SilcDList list, void *context)
177 {
178   SilcDListEntry e = (SilcDListEntry)silc_calloc(1, sizeof(*e));
179   e->context = context;
180   silc_list_add(list->list, e);
181 }
182
183 /****f* silcutil/SilcDListAPI/silc_dlist_del
184  *
185  * SYNOPSIS
186  *
187  *    static inline
188  *    void silc_dlist_del(SilcDList list, void *context);
189  *
190  * DESCRIPTION
191  *
192  *    Remove entry from the list. Returns < 0 on error, 0 otherwise.
193  *
194  ***/
195
196 static inline
197 void silc_dlist_del(SilcDList list, void *context)
198 {
199   SilcDListEntry e;
200
201   silc_list_start(list->list);
202   while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
203     if (e->context == context) {
204       silc_list_del(list->list, e);
205 #if defined(SILC_DEBUG)
206       memset(e, 'F', sizeof(*e));
207 #endif
208       silc_free(e);
209       break;
210     }
211   }
212 }
213
214 /****f* silcutil/SilcDListAPI/silc_dlist_get
215  *
216  * SYNOPSIS
217  *
218  *    static inline
219  *    void *silc_dlist_get(SilcDList list);
220  *
221  * DESCRIPTION
222  *
223  *    Returns current entry from the list and moves the list pointer forward
224  *    so that calling this next time returns the next entry from the list.
225  *    This can be used to traverse the list. Return SILC_LIST_END when the
226  *    entire list has been traversed. Later, silc_list_start must be called
227  *    again when re-starting list traversing.
228  *
229  * EXAMPLE
230  *
231  *    // Traverse the list from the beginning to the end 
232  *    silc_dlist_start(list)
233  *    while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
234  *      ...
235  *    }
236  *
237  ***/
238
239 static inline
240 void *silc_dlist_get(SilcDList list)
241 {
242   SilcDListEntry e = (SilcDListEntry)silc_list_get(list->list);
243   if (e != SILC_LIST_END)
244     return e->context;
245   return SILC_LIST_END;
246 }
247
248 #endif