From c8bf38e5fb717d40635a2a89b22ed71b0de4266b Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Tue, 1 Dec 2020 13:33:34 +0100 Subject: Squashed 'dependencies/uthash/' content from commit 8e67ced git-subtree-dir: dependencies/uthash git-subtree-split: 8e67ced1d1c5bd8141c542a22630e6de78aa6b90 --- doc/utlist.txt | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 doc/utlist.txt (limited to 'doc/utlist.txt') diff --git a/doc/utlist.txt b/doc/utlist.txt new file mode 100644 index 000000000..06b6b00dc --- /dev/null +++ b/doc/utlist.txt @@ -0,0 +1,293 @@ +utlist: linked list macros for C structures +=========================================== +Troy D. Hanson +v2.1.0, December 2018 + +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 +^^^^^^^^^^ +Prepending elements:: + Constant-time on all list types. +Appending:: + 'O(n)' on singly-linked lists; constant-time on doubly-linked list. + (The utlist implementation of the doubly-linked list keeps a tail pointer in + `head->prev` so that append can be done in constant time). +Deleting elements:: + 'O(n)' on singly-linked lists; constant-time on doubly-linked list. +Sorting:: + 'O(n log(n))' for all list types. +Insertion in order (for sorted lists):: + 'O(n)' for all list types. +Iteration, counting and searching:: + '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="10next`. + +The 'count' operation iterates over the list and increments a supplied counter. + +The parameters shown in the table above are explained here: + +head:: + The list head (a pointer to your list element structure). +add:: + A pointer to the list element structure you are adding to the list. +del:: + A pointer to the list element structure you are replacing or + deleting from the list. +elt:: + A pointer that will be assigned to each list element in succession (see + example) in the case of iteration macros; or, the output pointer from + the search macros. +ref:: + Reference element for prepend and append operations that will be + prepended before or appended after. + If `ref` is a pointer with value NULL, the new element will be appended to the + list for _PREPEND_ELEM() operations and prepended for _APPEND_ELEM() operations. + `ref` must be the name of a pointer variable and cannot be literally NULL, + use _PREPEND() and _APPEND() macro family instead. +like:: + An element pointer, having the same type as `elt`, for which the search macro + seeks a match (if found, the match is stored in `elt`). A match is determined + by the given `cmp` function. +cmp:: + pointer to comparison function which accepts two arguments-- these are + pointers to two element structures to be compared. The comparison function + must return an `int` that is negative, zero, or positive, which specifies + whether the first item should sort before, equal to, or after the second item, + respectively. (In other words, the same convention that is used by `strcmp`). + Note that under Visual Studio 2008 you may need to declare the two arguments + as `void *` and then cast them back to their actual types. +tmp:: + A pointer of the same type as `elt`. Used internally. Need not be initialized. +mbr:: + In the scalar search macro, the name of a member within the `elt` structure which + will be tested (using `==`) for equality with the value `val`. +val:: + In the scalar search macro, specifies the value of (of structure member + `field`) of the element being sought. +count:: + integer which will be set to the length of the list + +Example +~~~~~~~ +This example program reads names from a text file (one name per line), and +appends each name to a doubly-linked list. Then it sorts and prints them. + +.A doubly-linked list +-------------------------------------------------------------------------------- +#include +#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]; + int count; + 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 *name)) == NULL) exit(-1); + strcpy(name->bname, linebuf); + DL_APPEND(head, name); + } + DL_SORT(head, namecmp); + DL_FOREACH(head,elt) printf("%s", elt->bname); + DL_COUNT(head, elt, count); + printf("%d number of elements in list\n", count); + + 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); + free(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. + +[width="100%",cols="10