1 utlist: linked list macros for C structures
2 ===========================================
3 Troy D. Hanson <tdh@tkhanson.net>
6 Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
10 A set of general-purpose 'linked list' macros for C structures are included with
11 uthash in `utlist.h`. To use these macros in your own C program, just
12 copy `utlist.h` into your source directory and use it in your programs.
16 These macros support the basic linked list operations: adding and deleting
17 elements, sorting them and iterating over them.
21 To download the `utlist.h` header file,
22 follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file,
23 then look in the src/ sub-directory.
27 This software is made available under the
28 link:license.html[revised BSD license].
29 It is free and open source.
33 The 'utlist' macros have been tested on:
37 * Windows, using Visual Studio 2008, Visual Studio 2010, or Cygwin/MinGW.
44 Three types of linked lists are supported:
46 - *singly-linked* lists,
47 - *doubly-linked* lists, and
48 - *circular, doubly-linked* lists
53 Constant-time on all list types.
55 'O(n)' on singly-linked lists; constant-time on doubly-linked list.
56 (The utlist implementation of the doubly-linked list keeps a tail pointer in
57 `head->prev` so that append can be done in constant time).
59 'O(n)' on singly-linked lists; constant-time on doubly-linked list.
61 'O(n log(n))' for all list types.
62 Iteration, counting and searching::
63 'O(n)' for all list types.
67 You can use any structure with these macros, as long as the structure
68 contains a `next` pointer. If you want to make a doubly-linked list,
69 the element also needs to have a `prev` pointer.
71 typedef struct element {
73 struct element *prev; /* needed for a doubly-linked list only */
74 struct element *next; /* needed for singly- or doubly-linked lists */
77 You can name your structure anything. In the example above it is called `element`.
78 Within a particular list, all elements must be of the same type.
80 Flexible prev/next naming
81 ^^^^^^^^^^^^^^^^^^^^^^^^^
82 You can name your `prev` and `next` pointers something else. If you do, there is
83 a <<flex_names,family of macros>> that work identically but take these names as
88 The list head is simply a pointer to your element structure. You can name it
89 anything. *It must be initialized to `NULL`*.
95 The lists support inserting or deleting elements, sorting the elements and
98 [width="100%",cols="10<m,10<m,10<m",grid="cols",options="header"]
99 |===============================================================================
100 |Singly-linked | Doubly-linked | Circular, doubly-linked
101 |LL_PREPEND(head,add); | DL_PREPEND(head,add); | CDL_PREPEND(head,add);
102 |LL_PREPEND_ELEM(head,ref,add); | DL_PREPEND_ELEM(head,ref,add); | CDL_PREPEND_ELEM(head,ref,add);
103 |LL_APPEND_ELEM(head,ref,add); | DL_APPEND_ELEM(head,ref,add); | CDL_APPEND_ELEM(head,ref,add);
104 |LL_REPLACE_ELEM(head,del,add); | DL_REPLACE_ELEM(head,del,add); | CDL_REPLACE_ELEM(head,del,add);
105 |LL_APPEND(head,add); | DL_APPEND(head,add); | CDL_APPEND(head,add);
106 |LL_CONCAT(head1,head2); | DL_CONCAT(head1,head2); |
107 |LL_DELETE(head,del); | DL_DELETE(head,del); | CDL_DELETE(head,del);
108 |LL_SORT(head,cmp); | DL_SORT(head,cmp); | CDL_SORT(head,cmp);
109 |LL_FOREACH(head,elt) {...}| DL_FOREACH(head,elt) {...} | CDL_FOREACH(head,elt) {...}
110 |LL_FOREACH_SAFE(head,elt,tmp) {...}| DL_FOREACH_SAFE(head,elt,tmp) {...} | CDL_FOREACH_SAFE(head,elt,tmp1,tmp2) {...}
111 |LL_SEARCH_SCALAR(head,elt,mbr,val);| DL_SEARCH_SCALAR(head,elt,mbr,val); | CDL_SEARCH_SCALAR(head,elt,mbr,val);
112 |LL_SEARCH(head,elt,like,cmp);| DL_SEARCH(head,elt,like,cmp); | CDL_SEARCH(head,elt,like,cmp);
113 |LL_COUNT(head,elt,count); | DL_COUNT(head,elt,count); | CDL_COUNT(head,elt,count);
114 |===============================================================================
116 'Prepend' means to insert an element in front of the existing list head (if any),
117 changing the list head to the new element. 'Append' means to add an element at the
118 end of the list, so it becomes the new tail element. 'Concatenate' takes two
119 properly constructed lists and appends the second list to the first. (Visual
120 Studio 2008 does not support `LL_CONCAT` and `DL_CONCAT`, but VS2010 is ok.)
121 To prepend before an arbitrary element instead of the list head, use the
122 `_PREPEND_ELEM` macro family.
123 To append after an arbitrary element element instead of the list head, use the
124 `_APPEND_ELEM` macro family.
125 To 'replace' an arbitrary list element with another element use the `_REPLACE_ELEM`
128 The 'sort' operation never moves the elements in memory; rather it only adjusts
129 the list order by altering the `prev` and `next` pointers in each element. Also
130 the sort operation can change the list head to point to a new element.
132 The 'foreach' operation is for easy iteration over the list from the head to the
133 tail. A usage example is shown below. You can of course just use the `prev` and
134 `next` pointers directly instead of using the 'foreach' macros.
135 The 'foreach_safe' operation should be used if you plan to delete any of the list
136 elements while iterating.
138 The 'search' operation is a shortcut for iteration in search of a particular
139 element. It is not any faster than manually iterating and testing each element.
140 There are two forms: the "scalar" version searches for an element using a
141 simple equality test on a given structure member, while the general version takes an
142 element to which all others in the list will be compared using a `cmp` function.
144 The 'count' operation iterates over the list and increments a supplied counter.
146 The parameters shown in the table above are explained here:
149 The list head (a pointer to your list element structure).
151 A pointer to the list element structure you are adding to the list.
153 A pointer to the list element structure you are replacing or
154 deleting from the list.
156 A pointer that will be assigned to each list element in succession (see
157 example) in the case of iteration macros; or, the output pointer from
160 Reference element for prepend and append operations that will be
161 prepended before or appended after.
162 If `ref` is a pointer with value NULL, the new element will be appended to the
163 list for _PREPEND_ELEM() operations and prepended for _APPEND_ELEM() operations.
164 `ref` must be the name of a pointer variable and cannot be literally NULL,
165 use _PREPEND() and _APPEND() macro family instead.
167 An element pointer, having the same type as `elt`, for which the search macro
168 seeks a match (if found, the match is stored in `elt`). A match is determined
169 by the given `cmp` function.
171 pointer to comparison function which accepts two arguments-- these are
172 pointers to two element structures to be compared. The comparison function
173 must return an `int` that is negative, zero, or positive, which specifies
174 whether the first item should sort before, equal to, or after the second item,
175 respectively. (In other words, the same convention that is used by `strcmp`).
176 Note that under Visual Studio 2008 you may need to declare the two arguments
177 as `void *` and then cast them back to their actual types.
179 A pointer of the same type as `elt`. Used internally. Need not be initialized.
181 In the scalar search macro, the name of a member within the `elt` structure which
182 will be tested (using `==`) for equality with the value `val`.
184 In the scalar search macro, specifies the value of (of structure member
185 `field`) of the element being sought.
187 integer which will be set to the length of the list
191 This example program reads names from a text file (one name per line), and
192 appends each name to a doubly-linked list. Then it sorts and prints them.
194 .A doubly-linked list
195 --------------------------------------------------------------------------------
205 struct el *next, *prev;
208 int namecmp(el *a, el *b) {
209 return strcmp(a->bname,b->bname);
212 el *head = NULL; /* important- initialize to NULL! */
214 int main(int argc, char *argv[]) {
215 el *name, *elt, *tmp, etmp;
217 char linebuf[BUFLEN];
221 if ( (file = fopen( "test11.dat", "r" )) == NULL ) {
222 perror("can't open: ");
226 while (fgets(linebuf,BUFLEN,file) != NULL) {
227 if ( (name = (el*)malloc(sizeof(el))) == NULL) exit(-1);
228 strncpy(name->bname,linebuf,BUFLEN);
229 DL_APPEND(head, name);
231 DL_SORT(head, namecmp);
232 DL_FOREACH(head,elt) printf("%s", elt->bname);
233 DL_COUNT(head, elt, count);
234 printf("%d number of elements in list\n", count);
236 memcpy(&etmp.bname, "WES\n", 5);
237 DL_SEARCH(head,elt,&etmp,namecmp);
238 if (elt) printf("found %s\n", elt->bname);
240 /* now delete each element, use the safe iterator */
241 DL_FOREACH_SAFE(head,elt,tmp) {
250 --------------------------------------------------------------------------------
253 Other names for prev and next
254 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
255 If the `prev` and `next` fields are named something else, a separate group of
256 macros must be used. These work the same as the regular macros, but take the
257 field names as extra parameters.
259 These "flexible field name" macros are shown below. They all end with "2". Each
260 operates the same as its counterpart without the 2, but they take the name of
261 the `prev` and `next` fields (as applicable) as trailing arguments.
263 .Flexible field name macros
264 LL_SORT2(list, cmp, next);
265 DL_SORT2(list, cmp, prev, next);
266 CDL_SORT2(list, cmp, prev, next);
267 LL_PREPEND2(head, add, next);
268 LL_PREPEND_ELEM2(head, ref, add, next);
269 LL_APPEND_ELEM2(head, ref, add, next);
270 LL_REPLACE_ELEM(head, del, add, next);
271 LL_CONCAT2(head1, head2, next);
272 LL_APPEND2(head, add, next);
273 LL_DELETE2(head, del, next);
274 LL_FOREACH2(head, elt, next) {...}
275 LL_FOREACH_SAFE2(head, elt, tmp, next) {...}
276 LL_SEARCH_SCALAR2(head, out, field, val, next);
277 LL_SEARCH2(head, out, elt, cmp, next);
278 LL_COUNT2(head, elt, count, next);
279 DL_PREPEND2(head, add, prev, next);
280 DL_PREPEND_ELEM2(head, ref, add, prev, next);
281 DL_APPEND_ELEM2(head, ref, add, prev, next);
282 DL_REPLACE_ELEM2(head, del, add, prev, next);
283 DL_CONCAT2(head1, head2, prev, next);
284 DL_APPEND2(head, add, prev, next);
285 DL_DELETE2(head, del, prev, next);
286 DL_FOREACH2(head, elt, next) {...}
287 DL_FOREACH_SAFE2(head, elt, tmp, next) {...}
288 DL_SEARCH_SCALAR2(head, out, field, val, next);
289 DL_COUNT2(head, elt, count, next);
290 CDL_PREPEND2(head, add, prev, next);
291 CDL_PREPEND_ELEM2(head, ref, add, prev, next);
292 CDL_APPEND_ELEM2(head, ref, add, prev, next);
293 CDL_REPLACE_ELEM2(head, del, add, prev, next);
294 CDL_APPEND2(head, add, prev, next);
295 CDL_DELETE2(head, del, prev, next);
296 CDL_FOREACH2(head, elt, next) {...}
297 CDL_FOREACH_SAFE2(head, elt, tmp1, tmp2, prev, next) {...}
298 CDL_SEARCH_SCALAR2(head, out, field, val, next);
299 CDL_SEARCH2(head, out, elt, cmp, next);
300 CDL_COUNT2(head, elt, count, next);
302 // vim: set tw=80 wm=2 syntax=asciidoc: