updates
[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 /*
27    SILC Dynamic List API
28
29    SILC Dynamic List API can be used to add opaque contexts to list that will
30    automatically allocate list entries.  Normal SILC List API cannot be used
31    for this purpose because in that case the context passed to the list must
32    be defined as list structure already.  This is not the case in SilcDList.
33
34    This is slower than SilcList because this requires one extra memory 
35    allocation when adding new entries to the list.  The context is probably
36    allocated already and the new list entry requires one additional memory 
37    allocation.  The memory allocation and free'ing is done automatically in
38    the API and does not show to the caller.
39
40    I left sorting functions out because I don't know whether we need them.
41    If needed, just copy them from silclist.h
42
43 */
44
45 /* SilcDList object. This is the actual SilcDList object that is used by
46    application. Application defines this object and adds context's to this
47    list with functions defined below. */
48 typedef struct {
49   SilcList list;
50 } *SilcDList;
51
52 /* SilcDListEntry structure, one entry in the list. This MUST NOT be used
53    directly by the application. */
54 typedef struct SilcDListEntryStruct {
55   void *context;
56   struct SilcDListEntryStruct *next;
57 } *SilcDListEntry;
58
59 /* Initializes SilcDList. */
60
61 static inline
62 SilcDList silc_dlist_init()
63 {
64   SilcDList list;
65
66   list = (SilcDList)silc_calloc(1, sizeof(*list));
67   silc_list_init(list->list, struct SilcDListEntryStruct, next);
68
69   return list;
70 }
71
72 /* Uninits and free's all memory. Must be called to free memory. Does NOT
73    free the contexts saved by caller. */
74
75 static inline
76 void silc_dlist_uninit(SilcDList list)
77 {
78   if (list) {
79     SilcDListEntry e;
80     silc_list_start(list->list);
81     while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
82       silc_list_del(list->list, e);
83       silc_free(e);
84     }
85     silc_free(list);
86   }
87 }
88
89 /* Return the number of entries in the list */
90
91 static inline
92 int silc_dlist_count(SilcDList list)
93 {
94   return silc_list_count(list->list);
95 }
96
97 /* Set the start of the list. This prepares the list for traversing entries
98    from the start of the list. */
99
100 static inline
101 void silc_dlist_start(SilcDList list)
102 {
103   silc_list_start(list->list);
104 }
105
106 /* Adds new entry to the list. This is the default function to add new
107    entries to the list. */
108
109 static inline
110 void silc_dlist_add(SilcDList list, void *context)
111 {
112   SilcDListEntry e = (SilcDListEntry)silc_calloc(1, sizeof(*e));
113   e->context = context;
114   silc_list_add(list->list, e);
115 }
116
117 /* Remove entry from the list. Returns < 0 on error, 0 otherwise. */
118
119 static inline
120 void silc_dlist_del(SilcDList list, void *context)
121 {
122   SilcDListEntry e;
123
124   silc_list_start(list->list);
125   while ((e = (SilcDListEntry)silc_list_get(list->list)) != SILC_LIST_END) {
126     if (e->context == context) {
127       silc_list_del(list->list, e);
128       silc_free(e);
129       break;
130     }
131   }
132 }
133
134 /* Returns current entry from the list and moves the list pointer forward
135    so that calling this next time returns the next entry from the list. This
136    can be used to traverse the list. Return SILC_LIST_END when the entire
137    list has ben traversed. Later, silc_list_start must be called again when 
138    re-starting list traversing. Example:
139
140    // Traverse the list from the beginning to the end 
141    silc_dlist_start(list)
142    while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
143      ...
144    }
145    
146 */
147 static inline
148 void *silc_dlist_get(SilcDList list)
149 {
150   SilcDListEntry e = (SilcDListEntry)silc_list_get(list->list);
151   if (e != SILC_LIST_END)
152     return e->context;
153   return SILC_LIST_END;
154 }
155
156 #endif