utlist: linked list macros for C structures =========================================== Troy D. Hanson v1.9.8, March 2013 Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. Introduction ------------ A set of general-purpose 'linked list' macros for C structures are included with uthash in `utlist.h`. To use these macros in your own C program, just copy `utlist.h` into your source directory and use it in your programs. #include "utlist.h" These macros support the basic linked list operations: adding and deleting elements, sorting them and iterating over them. Download ~~~~~~~~ To download the `utlist.h` header file, follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file, then look in the src/ sub-directory. BSD licensed ~~~~~~~~~~~~ This software is made available under the link:license.html[revised BSD license]. It is free and open source. Platforms ~~~~~~~~~ The 'utlist' macros have been tested on: * Linux, * Mac OS X, and * Windows, using Visual Studio 2008, Visual Studio 2010, or Cygwin/MinGW. Using utlist ------------ Types of lists ~~~~~~~~~~~~~~ Three types of linked lists are supported: - *singly-linked* lists, - *doubly-linked* lists, and - *circular, doubly-linked* lists Efficiency ^^^^^^^^^^ For all types of lists, prepending elements and deleting elements are constant-time operations. Appending to a singly-linked list is an 'O(n)' operation but appending to a doubly-linked list is constant time using these macros. (This is because, in the utlist implementation of the doubly-linked list, the head element's `prev` member points back to the list tail, even when the list is non-circular). Sorting is an 'O(n log(n))' operation. Iteration and searching are `O(n)` for all list types. List elements ~~~~~~~~~~~~~ You can use any structure with these macros, as long as the structure contains a `next` pointer. If you want to make a doubly-linked list, the element also needs to have a `prev` pointer. typedef struct element { char *name; struct element *prev; /* needed for a doubly-linked list only */ struct element *next; /* needed for singly- or doubly-linked lists */ } element; You can name your structure anything. In the example above it is called `element`. Within a particular list, all elements must be of the same type. Flexible prev/next naming ^^^^^^^^^^^^^^^^^^^^^^^^^ You can name your `prev` and `next` pointers something else. If you do, there is a <> that work identically but take these names as extra arguments. List head ~~~~~~~~~ The list head is simply a pointer to your element structure. You can name it anything. *It must be initialized to `NULL`*. element *head = NULL; List operations ~~~~~~~~~~~~~~~ The lists support inserting or deleting elements, sorting the elements and iterating over them. [width="100%",cols="10 #include #include #include "utlist.h" #define BUFLEN 20 typedef struct el { char bname[BUFLEN]; struct el *next, *prev; } el; int namecmp(el *a, el *b) { return strcmp(a->bname,b->bname); } el *head = NULL; /* important- initialize to NULL! */ int main(int argc, char *argv[]) { el *name, *elt, *tmp, etmp; char linebuf[BUFLEN]; FILE *file; if ( (file = fopen( "test11.dat", "r" )) == NULL ) { perror("can't open: "); exit(-1); } while (fgets(linebuf,BUFLEN,file) != NULL) { if ( (name = (el*)malloc(sizeof(el))) == NULL) exit(-1); strncpy(name->bname,linebuf,BUFLEN); DL_APPEND(head, name); } DL_SORT(head, namecmp); DL_FOREACH(head,elt) printf("%s", elt->bname); memcpy(&etmp.bname, "WES\n", 5); DL_SEARCH(head,elt,&etmp,namecmp); if (elt) printf("found %s\n", elt->bname); /* now delete each element, use the safe iterator */ DL_FOREACH_SAFE(head,elt,tmp) { DL_DELETE(head,elt); } fclose(file); return 0; } -------------------------------------------------------------------------------- [[flex_names]] Other names for prev and next ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the `prev` and `next` fields are named something else, a separate group of macros must be used. These work the same as the regular macros, but take the field names as extra parameters. These "flexible field name" macros are shown below. They all end with "2". Each operates the same as its counterpart without the 2, but they take the name of the `prev` and `next` fields (as applicable) as trailing arguments. .Flexible field name macros LL_SORT2(list, cmp, next) DL_SORT2(list, cmp, prev, next) CDL_SORT2(list, cmp, prev, next) LL_PREPEND2(head,add,next) LL_CONCAT2(head1,head2,next) LL_APPEND2(head,add,next) LL_DELETE2(head,del,next) LL_FOREACH2(head,el,next) LL_FOREACH_SAFE2(head,el,tmp,next) LL_SEARCH_SCALAR2(head,out,field,val,next) LL_SEARCH2(head,out,elt,cmp,next) DL_PREPEND2(head,add,prev,next) DL_APPEND2(head,add,prev,next) DL_CONCAT2(head1,head2,prev,next) DL_DELETE2(head,del,prev,next) DL_FOREACH2(head,el,next) DL_FOREACH_SAFE2(head,el,tmp,next) CDL_PREPEND2(head,add,prev,next) CDL_DELETE2(head,del,prev,next) CDL_FOREACH2(head,el,next) CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) CDL_SEARCH_SCALAR2(head,out,field,val,next) CDL_SEARCH2(head,out,elt,cmp,next) // vim: set tw=80 wm=2 syntax=asciidoc: