5 Author: Timo Sirainen <tss@iki.fi>
7 Copyright (C) 2002 Timo Sirainen
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.
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.
21 /****h* silcutil/SILC List Interface
25 * Implementation of the SilcList interface. This interface provides
33 /****s* silcutil/SilcList/SilcList
37 * typedef struct { ... } SilcList;
41 * This is the SilcList context, and is initialized by calling the
42 * function silc_list_init.
47 * silc_list_init(list, struct SilcInternalEntryStruct, next);
56 /****d* silcutil/SilcList/SILC_LIST_END
60 * #define SILC_LIST_END ...
64 * Functions return this when the list is invalid or when traversing
65 * the list there is no more entires in the list.
69 #define SILC_LIST_END NULL
72 /* Initializes SilcList object. Example:
76 silc_list_init(list, struct SilcInternalEntryStruct, next);
78 Where `list' is the defined list, and second argument is the structure
79 of the entries in the list and last argument is the pointer in the entry
80 structure that is used as list member. SilcInternalEntry might be as
83 struct SilcInternalEntryStruct {
85 struct SilcInternalEntryStruct *next; // The list member pointer
88 The `next' pointer in the structure (or some other pointer for that matter)
89 is given for the silc_list_init as the last argument. This pointer is used
90 by the list routines to link the entries together in the list. Your code
91 should not touch the member pointer manually.
94 /****f* silcutil/SilcList/silc_list_init
98 * #define silc_list_init(list, type, field) ...
102 * This macro initializes the SilcList list. The `list' is the defined
103 * list, second argument is the structure of the entries in the list,
104 * and last argument is the pointer in the entry structure that is used
105 * as list member. When using SilcList, you should not touch the
106 * structure member pointer (the `next' for example) manually.
110 * struct SilcInternalEntryStruct {
112 * struct SilcInternalEntryStruct *next; // The list member pointer
116 * silc_list_init(list, struct SilcInternalEntryStruct, next);
119 #define silc_list_init(list, type, field) \
120 __silc_list_init(&(list), silc_offsetof(type, field))
122 static inline void __silc_list_init(SilcList *list, int offset)
124 list->head = list->tail = list->current = SILC_LIST_END;
125 list->offset = offset;
128 #define list_next(list, pos) ((void **) ((char *) (pos) + (list)->offset))
130 /****f* silcutil/SilcList/silc_list_count
134 * #define silc_list_count(list) ...
138 * Returns the number of entries in the list indicated by `list'.
141 #define silc_list_count(list) __silc_list_count(&(list))
142 static inline int __silc_list_count(SilcList *list)
147 for (pos = list->head; pos != NULL; pos = *list_next(list, pos))
153 /****f* silcutil/SilcList/silc_list_start
157 * #define silc_list_start(list) ...
161 * Sets the start of the list. This prepares the list for traversing
162 * the entries from the start of the list.
165 #define silc_list_start(list) (list).current = (list).head;
167 /****f* silcutil/SilcList/silc_list_add
171 * #define silc_list_add(list, entry) ...
175 * Adds new entry indicated by `entry' to the end of the list indicated
179 #define silc_list_add(list, entry) __silc_list_add(&(list), entry)
180 static inline void __silc_list_add(SilcList *list, void *data)
182 if (list->head == NULL)
185 *list_next(list, list->tail) = data;
188 *list_next(list, data) = NULL;
191 /****f* silcutil/SilcList/silc_list_del
195 * #define silc_list_del(list, entry) ...
199 * Remove entry indicated by `entry' from the list indicated by `list'.
202 #define silc_list_del(list, data) __silc_list_del(&(list), data)
203 static inline void __silc_list_del(SilcList *list, void *data)
208 for (pos = &list->head; *pos != NULL; pos = list_next(list, *pos)) {
210 *pos = *list_next(list, data);
211 if (list->current == data)
212 list->current = *pos;
219 if (data == list->tail)
223 /****f* silcutil/SilcList/silc_list_get
227 * #define silc_list_get(list, entry) ...
231 * Returns the current entry from the list indicated by `list' and
232 * moves the list pointer forward so that calling this next time will
233 * return the next entry from the list. This can be used to traverse
234 * the list. Returns SILC_LIST_END when the entire list has been
235 * tarversed and no additional entries exist in the list. Later,
236 * silc_list_start must be called again when re-starting the list
241 * // Traverse the list from the beginning to the end
242 * silc_list_start(list)
243 * while ((entry = silc_list_get(list)) != SILC_LIST_END) {
248 #define silc_list_get(x) __silc_list_get(&(x))
251 void *__silc_list_get(SilcList *list)
257 list->current = *list_next(list, pos);