From fb29b7e9ac74ccb6d6fc971193c1f4fd1048024d Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Thu, 15 Apr 2021 16:05:32 +0200 Subject: [PATCH] + add: dev doc for uthash --- doc/uthash/.gitignore | 7 + doc/uthash/ChangeLog.txt | 267 ++++ doc/uthash/Makefile | 18 + doc/uthash/banner.png | Bin 0 -> 20477 bytes doc/uthash/banner.svg | 451 ++++++ doc/uthash/google315d692c9c632ed0.html | 1 + doc/uthash/index.html | 122 ++ doc/uthash/license.html | 55 + doc/uthash/rss.png | Bin 0 -> 689 bytes doc/uthash/styles.css | 141 ++ doc/uthash/userguide.txt | 1901 ++++++++++++++++++++++++ doc/uthash/utarray.txt | 383 +++++ doc/uthash/uthash-mini.png | Bin 0 -> 3611 bytes doc/uthash/uthash-mini.svg | 288 ++++ doc/uthash/uthash.png | Bin 0 -> 21518 bytes doc/uthash/utlist.txt | 293 ++++ doc/uthash/utringbuffer.txt | 374 +++++ doc/uthash/utstack.txt | 158 ++ doc/uthash/utstring.txt | 239 +++ 19 files changed, 4698 insertions(+) create mode 100644 doc/uthash/.gitignore create mode 100644 doc/uthash/ChangeLog.txt create mode 100644 doc/uthash/Makefile create mode 100644 doc/uthash/banner.png create mode 100644 doc/uthash/banner.svg create mode 100644 doc/uthash/google315d692c9c632ed0.html create mode 100644 doc/uthash/index.html create mode 100644 doc/uthash/license.html create mode 100644 doc/uthash/rss.png create mode 100644 doc/uthash/styles.css create mode 100644 doc/uthash/userguide.txt create mode 100644 doc/uthash/utarray.txt create mode 100644 doc/uthash/uthash-mini.png create mode 100644 doc/uthash/uthash-mini.svg create mode 100644 doc/uthash/uthash.png create mode 100644 doc/uthash/utlist.txt create mode 100644 doc/uthash/utringbuffer.txt create mode 100644 doc/uthash/utstack.txt create mode 100644 doc/uthash/utstring.txt diff --git a/doc/uthash/.gitignore b/doc/uthash/.gitignore new file mode 100644 index 000000000..9a2594e2a --- /dev/null +++ b/doc/uthash/.gitignore @@ -0,0 +1,7 @@ +ChangeLog.html +userguide.html +utarray.html +utlist.html +utringbuffer.html +utstack.html +utstring.html diff --git a/doc/uthash/ChangeLog.txt b/doc/uthash/ChangeLog.txt new file mode 100644 index 000000000..281de80fe --- /dev/null +++ b/doc/uthash/ChangeLog.txt @@ -0,0 +1,267 @@ +uthash ChangeLog +================ + +Click to return to the link:index.html[uthash home page]. + +NOTE: This ChangeLog may be incomplete and/or incorrect. See the git commit log. + +Version 2.1.0 (2018-12-20) +-------------------------- +* silence some Clang static analysis warnings +* add LL_INSERT_INORDER and LL_LOWER_BOUND etc (thanks, Jeffrey Lovitz and Mattias Eriksson!) +* add uthash_bzero for platforms without +* fix a missing HASH_BLOOM_ADD in HASH_SELECT (thanks, Pawel Veselov!) +* permit malloc failure to be recoverable via HASH_NONFATAL_OOM (thanks, Pawel Veselov!) +* avoid repeated calls to uthash_strlen in HASH_FIND_STR +* rename uthash_memcmp to HASH_KEYCMP, leaving the old name for compatibility +* add utstack.h +* remove libut + +Version 2.0.2 (2017-03-02) +-------------------------- +* fix segfault in HASH_ADD_INORDER etc (thanks, Yana Kireyonok!) +* remove spurious cast to unsigned in utstring_len (thanks, Michal Sestrienka!) +* add uthash_memcmp and uthash_strlen for platforms without (thanks, Pawel Veselov!) +* fix a C++ incompatibility in utringbuffer + +Version 2.0.1 (2016-07-05) +-------------------------- +* in-order insertion macros HASH_ADD_INORDER etc (thanks, Thilo Schulz!) +* by-hashvalue insertion macros HASH_ADD_BYHASHVALUE etc +* during key comparison, check hashvalue before doing a full memcmp +* add utringbuffer.h + +Version 1.9.9.1 (2014-11-18) +---------------------------- +* inclusion of experimental libut bundle with utvector in opt/ +* use shift in Bernstein hash instead of multiply (thanks, Jimmy Zhuo!) +* switch ssize_t types in utarray/utstring to size_t (thanks, Hong Xu!) +* fix utstring pointer math on >4GB strings (thanks, Thomas Bottesch!) +* change FNV hash to FNV-1a varation (thanks, dwest1975!) +* fix bug in HASH_REPLACE_STR (thanks, Ilya Kaliman!) + +Version 1.9.9 (2014-02-25) +-------------------------- +* made HASH_ADD_STR compatible with char* or char[] (thanks, Samuel Thibault!) +* fixed header inclusion of sys/types.h for ssize_t (thanks, Fernando Campos!) +* added LL_COUNT/DL_COUNT/CDL_COUNT (thansk, Paul Praet!) +* added LRU cache example in `tests/lru_cache` (thanks, Oliver Lorenz!) +* fix LL_DELETE2 for VS2008 (thanks, Greg Davydouski!) +* fix missing argument in `HASH_REPLACE_STR` (thanks, Alex!) +* bump version number in source files to match docs (thanks, John Crow!) +* add `HASH_OVERHEAD` macro to get overhead size for hash table + +Version 1.9.8 (2013-03-10) +-------------------------- +* `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!) +* fixed clang warnings (thanks wynnw!) +* fixed `utarray_insert` when inserting past array end (thanks Rob Willett!) +* you can now find http://troydhanson.github.com/uthash/[uthash on GitHub] +* there's a https://groups.google.com/d/forum/uthash[uthash Google Group] +* uthash has been downloaded 29,000+ times since 2006 on SourceForge + +Version 1.9.7 (2012-10-09) +-------------------------- +* utstring now supports substring search using `utstring_find` (thanks, Joe Wei!) +* utlist now supports element 'prepend' and 'replace' (thanks, Zoltán Lajos Kis!) +* utlist element prev/next fields can now have any names (thanks, Pawel S. Veselov!) +* uthash cast quiets a clang warning (thanks, Roman Divacky and Baptiste Daroussin!) +* uthash userguide example shows how to check key uniqueness (thanks, Richard Cook!) +* uthash HASH_MUR compiles under MSVC++ 10 in C mode (thanks, Arun Kirthi Cherian!) +* `utstring_printf` now supports format checking (thanks, Donald Carr!) + +Version 1.9.6 (2012-04-28) +-------------------------- +* add utarray_prev (thanks, Ben Hiett!) +* add parens/casts for greater compatibility (thanks, Atis, Debasis Ganguly, and Steve McClellan!) +* added ifndef to uthash_malloc and related hooks (thanks, Holger Machens!) +* edit examples so they do not leak memory (thanks, 任晶磊!) + +Version 1.9.5 (2011-11-16) +-------------------------- +* added `utarray_renew` +* fixed memory leak in `uthash_clear` when using Bloom filter (thanks, Jan Hättig!) +* utarray now copies the UT_icd on array creation rather than storing a pointer +* add parentheses to `HASH_ADD` to fix preprocessing of certain arguments (thanks, Aaron Rosen!) +* more parenthesizations for greater macro argument flexibility + +Version 1.9.4 (2011-06-05) +-------------------------- +* uthash now supports MurmurHash v3 +* utlist now includes concatenation macros (`LL_CONCAT` and `DL_CONCAT`) +* utarray now supports binary search (`utarray_find`) +* utstring now supports a new-or-clear-existing macro (`utstring_renew`) +* documented technique for a multi-level hash table +* clarified scope requirements for `UT_icd` in the utarray documentation +* fixed termination when `utstring_clear` is followed by `utstring_body` +* fixed utarray_inserta macro when used with complex arguments +* on Visual Studio define missing type `uint8_t` +* Debian/Ubuntu include uthash in the package `uthash-dev`. +* uthash has been downloaded 16,211 times. + +Thanks to Yu Feng, Richard Cook, Dino Ciuffetti, Chris Groer, and Arun Cherian +for feedback and fixes in this release! + +Version 1.9.3 (2010-10-31) +-------------------------- +* fix an `ifdef` for compatibility with Intel compiler (thanks, degski!) +* fix `HASH_ITER` macro to satisfy C++ casting rules (thanks, Erik Bai!) + +Version 1.9.2 (2010-10-04) +-------------------------- +* new `HASH_ITER` macro for more convenient deletion-safe iteration +* `hashscan` can now run on FreeBSD 8.1 and later (thanks, Markus Gebert!) +* More parens to evaluate complex macro arguments properly (thanks, ngg!) +* Add sz parameter to the `uthash_free` hook for platforms that do their own memory management. Hopefully this minor API change doesn't cause too much breakage for people. (thanks, Niall Douglas!) +* uthash has been downloaded 12,294 times + +Version 1.9.1 (2010-05-15) +-------------------------- +* Fix a redefinition warning when using `uthash.h` and `utstring.h` together +* Fix a bug in `utstring_init` +* Added `HASH_FIND_PTR` and `HASH_ADD_PTR` (thanks, Niall Douglas!) + +Version 1.9 (2010-03-31) +-------------------------- +* uthash now supports Visual Studio 2008 and 2010 in C or C++ code! +* new headers link:utarray.html[utarray.h] and link:utstring.html[utstring.h] + are now included. These implement dynamic arrays and strings using macros +* link:utlist.html[utlist.h] now has deletion-safe iterators and search macros +* the test suite now runs under Visual Studio (thanks again degski!) +* special thanks for suggesting utarray and utlist features to Charalampos P.! +* uthash has been downloaded 9,616 times + +Version 1.8 (2009-09-08) +-------------------------- +* Added the `hashscan` utility that can report on the size and quality of + hash tables in a running process (Linux-only) +* Added Bloom filter support. This has the potential to speed up certain + types of programs that look up non-existant keys in sufficient numbers. +* Restored the MurmurHash, which can once again be used, if an additional + symbol is defined. This is a "safety" by which the user declares they + understand that `-fno-strict-aliasing` flag must be used if they are + using MurmurHash under gcc with optimization. +* Unified the bucket/table malloc hooks; now there is only one malloc hook +* Re-organized the manual into a main section and advanced topics section +* Fixed a bug in `utlist.h` where sorting a singly-linked list threw a + compile-time error. +* Fixed a bug in `utlist.h` where a doubly-linked list that is sorted + did not maintain the special `head->prev` pointer back to the list tail. + +Version 1.7 (2009-06-11) +-------------------------- +* The MurmurHash has been removed, and Jenkin's hash is once again the default. + While MurmurHash performed well, it's unsafe with regard to the strict + aliasing rule. This results in incorrect code when compiled with optimization. + It's not possible to enable `-fno-strict-aliasing` from within a header file. +* The linked list macros in `utlist.h` now comply with the strict-aliasing + rule so they generate correct code under high optimization levels (O2 or O3). + The use of the `__typeof__` extension, which was originally a GNU extension, + may reduce portability to other compilers that do not support this extension. + This extension is used in the singly-linked list macros and the sort macros. + +Version 1.6 (2009-05-08) +-------------------------- +Special thanks to Alfred Heisner for contributing several enhancements: + +* Support for two new hash functions: + - the Paul Hsieh hash function (`HASH_SFH`) + - Austin Appleby's MurmurHash function (`HASH_MUR`) +* Because of its excellent performance, MurmurHash is now the default hash function. +* `keystats` now has much better elapsed time accuracy under Cygwin and MinGW +* fixed casting in `HASH_FNV`, `HASH_SAX` and `HASH_OAT` for non-char keys + +This release also includes: + +* a new `HASH_CLEAR` operation clears a hash table in one step. +* a new `HASH_SELECT` operation inserts those elements from one hash that + satisfy a given condition into another hash. The selected items have + dual presence in both hash tables. For example a game could select the + visible polygons from a hash of all polygons. +* fixed a compile-time error which occurred if the final argument to + `HASH_ADD_KEYPTR` was a pointer to an array member like `&a[i]` +* added another test script `tests/all_funcs` which executes the test suite + using every supported hash function + +And lastly, + +* a new, separate header called link:utlist.html[utlist.h] is included which + provides 'linked list macros' for C structures, similar in style to the + uthash macros + +Version 1.5 (2009-02-19) +-------------------------- +* now thread-safe for concurrent readers +* use scratch variables on stack rather than in table (thanks, Petter Arvidsson!). + This change made HASH_FIND about 13% faster and enabled reader concurrency. +* made link:license.html[BSD license] terms even more permissive +* added link:userguide.pdf[PDF version] of User Guide +* added http://troydhanson.wordpress.com/feed/[update news] image:rss.png[(RSS)] + +Version 1.4 (2008-09-23) +-------------------------- +* Add `HASH_COUNT` for counting items in the hash +* Compatibility with C\+\+. Satisfy additional casting requirements. + Also in the `tests/` directory, running `make cplusplus` now compiles + all the test programs with the C++ compiler. +* Eliminate `elmt` pointer from the UT_hash_handle. Calculate elmt + from hash handle address by subtracting `hho` (hash handle offset). +* Contributed by L.S.Chin: + Cast `void*` to char* before pointer arithmetic to suppress compiler + warnings. We assume compilers abide to C standards which impose + requirement that `sizeof(void*) == sizeof(char*)`. +* Return meaningful exit status from do_tests per Tiago Cunha, + so that package manager-based install can verify tests are successful + + +Version 1.3 (2008-07-27) +------------------------ +* use integer-only math-- no floating point! Support FPU-less CPU's. +* eliminate `hash_q` metric, which measured the fraction of items with + non-ideal chain positions. We only need to know if this fraction + is below 0.5. This is now determined using fast bitwise tests. +* when an item is added to the hash, calculate the key's hash value + upfront and store it, instead of recomputing it as needed. This hashv + is stored in the hash handle. Potentially major speed benefit for + bucket expansion algorithm. Deleting is marginally improved too. +* fixed a minor bug in the calculation of the max ideal chain length; + line 446 in v1.2 erroneously calculated a/b*2 instead of a/(b*2). + The effect of this bug was that bucket expansion could occur more + readily because the per-bucket 'max chain length multiplier factor' + (which delays bucket expansion when certain buckets are overused) + was set to a lower, expansion-favoring value than intended. +* improved source commenting and improved variable names in structures +* remove `HASH_JSW`. Lengthy random number array made code less readable +* add `HASH_SRT(hh,hash,cmp)` as a generalized `HASH_SORT(hash,cmp)`. + It was an omission in uthash 1.2 that there was no sort macro for + hash handles with names other than hh. +* Corrected `HASH_FSCK` so it works with any name for the hash handle. +* behave properly in pathological `HASH_DEL(a,a)` case where the same + variable references the head and the deletee (advancing the head + then loses the correct reference to the deletee); fix by using + scratch area in the hash table to store deletee hash handle. +* made tests runnable on MinGW +* 3000+ downloads since uthash-1.0 + + +Version 1.2 (2006-11-22) +------------------------ +* new `HASH_SORT` macro +* Cygwin support +* User Guide now features a clickable Table of Contents. + (The technique for generating the TOC on the browser was contributed + back to the AsciiDoc project and incorporated into AsciiDoc v8.1.0). + + +Version 1.1 (2006-06-28) +------------------------ +* uthash-1.1 released +* supports several built-in user-selectable hash functions +* new keystats utility quantifies performance of hash functions + + +Version 1.0 (2006-06-02) +------------------------ +* Initial release + +// vim: set syntax=asciidoc: diff --git a/doc/uthash/Makefile b/doc/uthash/Makefile new file mode 100644 index 000000000..099a373d5 --- /dev/null +++ b/doc/uthash/Makefile @@ -0,0 +1,18 @@ +HTML=$(patsubst %.txt,%.html,$(wildcard *.txt)) + +all: $(HTML) + +# when each target of a multi-target rule has its own prereq +# we use a static pattern rule. +$(HTML): %.html: %.txt + asciidoc -a toc2 $< + +TMP=/tmp/uthash-gh-pages +stage: + mkdir -p ${TMP} + rm -if ${TMP}/* + cp *.html *.css *.png ${TMP} + +.PHONY: clean +clean: + $(RM) $(HTML) diff --git a/doc/uthash/banner.png b/doc/uthash/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..de4f310b9fec8cfda8f394e26cc7850968e1c673 GIT binary patch literal 20477 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ut hash + + + + + + + + + + + + + + + + + + + + + + + a hash tablefor C structures + + + diff --git a/doc/uthash/google315d692c9c632ed0.html b/doc/uthash/google315d692c9c632ed0.html new file mode 100644 index 000000000..c79038e6e --- /dev/null +++ b/doc/uthash/google315d692c9c632ed0.html @@ -0,0 +1 @@ +google-site-verification: google315d692c9c632ed0.html \ No newline at end of file diff --git a/doc/uthash/index.html b/doc/uthash/index.html new file mode 100644 index 000000000..11b120e22 --- /dev/null +++ b/doc/uthash/index.html @@ -0,0 +1,122 @@ + + + + + uthash: a hash table for C structures + + + + + +
+ GitHub page > + uthash home + + + +
+ +
+
+ + + +
+ Any C structure can be stored in a hash table using uthash. Just add a + UT_hash_handle to the structure and choose one or more fields + in your structure to act as the key. Then use these macros to store, + retrieve or delete items from the hash table. + +
+Example 1. Adding an item to a hash. +
+
+#include "uthash.h"
+
+struct my_struct {
+    int id;            /* we'll use this field as the key */
+    char name[10];
+    UT_hash_handle hh; /* makes this structure hashable */
+};
+
+struct my_struct *users = NULL;
+
+void add_user(struct my_struct *s) {
+    HASH_ADD_INT( users, id, s );
+}
+
+
+
+
+ +
+Example 2. Looking up an item in a hash. +
+
+struct my_struct *find_user(int user_id) {
+    struct my_struct *s;
+
+    HASH_FIND_INT( users, &user_id, s );
+    return s;
+}
+
+
+
+
+ +
+Example 3. Deleting an item from a hash. +
+ +
+void delete_user(struct my_struct *user) {
+    HASH_DEL( users, user);
+}
+
+
+
+
+ + For more information and examples, please see the User Guide. + +
+
+ +
+ + + + + + diff --git a/doc/uthash/license.html b/doc/uthash/license.html new file mode 100644 index 000000000..c70684558 --- /dev/null +++ b/doc/uthash/license.html @@ -0,0 +1,55 @@ + + + + + uthash: a hash table for C structures + + + + + +
+ uthash home > + BSD license +
+ +
+
+
+
+Copyright (c) 2005-2018, Troy D. Hanson  http://troydhanson.github.com/uthash/
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+ +
+ + + + + + diff --git a/doc/uthash/rss.png b/doc/uthash/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..b3c949d2244f2c0c81d65e74719af2a1b56d06a3 GIT binary patch literal 689 zcmV;i0#5yjP)(tky!*UETcH-TCU7SrqEjJM#?B`_A)!p7(kFf9-P@=@15kkTkGK zgFusyy#KECqZzRdBLb=P?$(kUP;>kYTDeG&{|a+iOiRbI6nbQ)j#7bOf>iF=C+|_py<&Fo1F5cC*iEM?zZGC{ejNg4LWYp=S$L6Qaby6y zp$+F`250{%tU{Lg$5*ROH}y!1UKJS4*xqd7P(Y3JQF?lrnf?yerr%&6yGXLG1ur*B z{$&R1@Oj)yl@%rY5rh?j(j10Yz_DBs`AKFU_QnB;)(aqQmGi&ieOS|21^NP9UMpa< zU&p!f6RZ6Owp^X!EXA=0SbN&h?CrQK%Q3(=YBqqHD^9ZUM0Hxt-6-KT;>lf@j?Z+v zHm(}`>85I&E<7e}oz?6UwjAogowzGO8kSN7+2`b^$Az9L{K5*ko87EV45LT-`_##3 z>d3AGh@>=mbg34|6}+-gT9N+6Dr@44VEl44O&{&|w=qpbzC#iWMKa?5)>tI+KLQK@ Xq0QFqn(9Yl00000NkvXXu0mjfZ8t>. + +Is it a library? +~~~~~~~~~~~~~~~~ +No, it's just a single header file: `uthash.h`. All you need to do is copy +the header file into your project, and: + + #include "uthash.h" + +Since uthash is a header file only, there is no library code to link against. + +C/C++ and platforms +~~~~~~~~~~~~~~~~~~~ +This software can be used in C and C++ programs. It has been tested on: + + * Linux + * Windows using Visual Studio 2008 and 2010 + * Solaris + * OpenBSD + * FreeBSD + * Android + +Test suite +^^^^^^^^^^ +To run the test suite, enter the `tests` directory. Then, + + * on Unix platforms, run `make` + * on Windows, run the "do_tests_win32.cmd" batch file. (You may edit the + batch file if your Visual Studio is installed in a non-standard location). + +BSD licensed +~~~~~~~~~~~~ +This software is made available under the +link:license.html[revised BSD license]. +It is free and open source. + +Download uthash +~~~~~~~~~~~~~~~ +Follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file. + +Getting help +~~~~~~~~~~~~ +Please use the https://groups.google.com/d/forum/uthash[uthash Google Group] to +ask questions. You can email it at uthash@googlegroups.com. + +Contributing +~~~~~~~~~~~~ +You may submit pull requests through GitHub. However, the maintainers of uthash +value keeping it unchanged, rather than adding bells and whistles. + +Extras included +~~~~~~~~~~~~~~~ +Three "extras" come with uthash. These provide lists, dynamic arrays and +strings: + + * link:utlist.html[utlist.h] provides linked list macros for C structures. + * link:utarray.html[utarray.h] implements dynamic arrays using macros. + * link:utstring.html[utstring.h] implements a basic dynamic string. + +History +~~~~~~~ +I wrote uthash in 2004-2006 for my own purposes. Originally it was hosted on +SourceForge. Uthash was downloaded around 30,000 times between 2006-2013 then +transitioned to GitHub. It's been incorporated into commercial software, +academic research, and into other open-source software. It has also been added +to the native package repositories for a number of Unix-y distros. + +When uthash was written, there were fewer options for doing generic hash tables +in C than exist today. There are faster hash tables, more memory-efficient hash +tables, with very different API's today. But, like driving a minivan, uthash is +convenient, and gets the job done for many purposes. + +As of July 2016, uthash is maintained by Arthur O'Dwyer. + +Your structure +-------------- + +In uthash, a hash table is comprised of structures. Each structure represents a +key-value association. One or more of the structure fields constitute the key. +The structure pointer itself is the value. + +.Defining a structure that can be hashed +---------------------------------------------------------------------- +#include "uthash.h" + +struct my_struct { + int id; /* key */ + char name[10]; + UT_hash_handle hh; /* makes this structure hashable */ +}; +---------------------------------------------------------------------- + +Note that, in uthash, your structure will never be moved or copied into another +location when you add it into a hash table. This means that you can keep other +data structures that safely point to your structure-- regardless of whether you +add or delete it from a hash table during your program's lifetime. + +The key +~~~~~~~ +There are no restrictions on the data type or name of the key field. The key +can also comprise multiple contiguous fields, having any names and data types. + +.Any data type... really? +***************************************************************************** +Yes, your key and structure can have any data type. Unlike function calls with +fixed prototypes, uthash consists of macros-- whose arguments are untyped-- and +thus able to work with any type of structure or key. +***************************************************************************** + +Unique keys +^^^^^^^^^^^ +As with any hash, every item must have a unique key. Your application must +enforce key uniqueness. Before you add an item to the hash table, you must +first know (if in doubt, check!) that the key is not already in use. You +can check whether a key already exists in the hash table using `HASH_FIND`. + +The hash handle +~~~~~~~~~~~~~~~ +The `UT_hash_handle` field must be present in your structure. It is used for +the internal bookkeeping that makes the hash work. It does not require +initialization. It can be named anything, but you can simplify matters by +naming it `hh`. This allows you to use the easier "convenience" macros to add, +find and delete items. + +A word about memory +~~~~~~~~~~~~~~~~~~~ + +Overhead +^^^^^^^^ +The hash handle consumes about 32 bytes per item on a 32-bit system, or 56 bytes +per item on a 64-bit system. The other overhead costs-- the buckets and the +table-- are negligible in comparison. You can use `HASH_OVERHEAD` to get the +overhead size, in bytes, for a hash table. See <>. + +How clean up occurs +^^^^^^^^^^^^^^^^^^^ +Some have asked how uthash cleans up its internal memory. The answer is simple: +'when you delete the final item' from a hash table, uthash releases all the +internal memory associated with that hash table, and sets its pointer to NULL. + + +Hash operations +--------------- + +This section introduces the uthash macros by example. For a more succinct +listing, see <>. + +.Convenience vs. general macros: +***************************************************************************** +The uthash macros fall into two categories. The 'convenience' macros can be used +with integer, pointer or string keys (and require that you chose the conventional +name `hh` for the `UT_hash_handle` field). The convenience macros take fewer +arguments than the general macros, making their usage a bit simpler for these +common types of keys. + +The 'general' macros can be used for any types of keys, or for multi-field keys, +or when the `UT_hash_handle` has been named something other than `hh`. These +macros take more arguments and offer greater flexibility in return. But if the +convenience macros suit your needs, use them-- your code will be more readable. +***************************************************************************** + +Declare the hash +~~~~~~~~~~~~~~~~ +Your hash must be declared as a `NULL`-initialized pointer to your structure. + + struct my_struct *users = NULL; /* important! initialize to NULL */ + +Add item +~~~~~~~~ +Allocate and initialize your structure as you see fit. The only aspect +of this that matters to uthash is that your key must be initialized to +a unique value. Then call `HASH_ADD`. (Here we use the convenience macro +`HASH_ADD_INT`, which offers simplified usage for keys of type `int`). + +.Add an item to a hash +---------------------------------------------------------------------- +void add_user(int user_id, char *name) { + struct my_struct *s; + + s = malloc(sizeof(struct my_struct)); + s->id = user_id; + strcpy(s->name, name); + HASH_ADD_INT( users, id, s ); /* id: name of key field */ +} +---------------------------------------------------------------------- + +The first parameter to `HASH_ADD_INT` is the hash table, and the +second parameter is the 'name' of the key field. Here, this is `id`. The +last parameter is a pointer to the structure being added. + +[[validc]] +.Wait.. the field name is a parameter? +******************************************************************************* +If you find it strange that `id`, which is the 'name of a field' in the +structure, can be passed as a parameter... welcome to the world of macros. Don't +worry; the C preprocessor expands this to valid C code. +******************************************************************************* + +Key must not be modified while in-use +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Once a structure has been added to the hash, do not change the value of its key. +Instead, delete the item from the hash, change the key, and then re-add it. + +Checking uniqueness +^^^^^^^^^^^^^^^^^^^ +In the example above, we didn't check to see if `user_id` was already a key +of some existing item in the hash. *If there's any chance that duplicate keys +could be generated by your program, you must explicitly check the uniqueness* +before adding the key to the hash. If the key is already in the hash, you can +simply modify the existing structure in the hash rather than adding the item. +'It is an error to add two items with the same key to the hash table'. + +Let's rewrite the `add_user` function to check whether the id is in the hash. +Only if the id is not present in the hash, do we create the item and add it. +Otherwise we just modify the structure that already exists. + + void add_user(int user_id, char *name) { + struct my_struct *s; + + HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ + if (s==NULL) { + s = (struct my_struct *)malloc(sizeof *s); + s->id = user_id; + HASH_ADD_INT( users, id, s ); /* id: name of key field */ + } + strcpy(s->name, name); + } + + +Why doesn't uthash check key uniqueness for you? It saves the cost of a hash +lookup for those programs which don't need it- for example, programs whose keys +are generated by an incrementing, non-repeating counter. + +However, if replacement is a common operation, it is possible to use the +`HASH_REPLACE` macro. This macro, before adding the item, will try to find an +item with the same key and delete it first. It also returns a pointer to the +replaced item, so the user has a chance to de-allocate its memory. + +Passing the hash pointer into functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the example above `users` is a global variable, but what if the caller wanted +to pass the hash pointer 'into' the `add_user` function? At first glance it would +appear that you could simply pass `users` as an argument, but that won't work +right. + + /* bad */ + void add_user(struct my_struct *users, int user_id, char *name) { + ... + HASH_ADD_INT( users, id, s ); + } + +You really need to pass 'a pointer' to the hash pointer: + + /* good */ + void add_user(struct my_struct **users, int user_id, char *name) { ... + ... + HASH_ADD_INT( *users, id, s ); + } + +Note that we dereferenced the pointer in the `HASH_ADD` also. + +The reason it's necessary to deal with a pointer to the hash pointer is simple: +the hash macros modify it (in other words, they modify the 'pointer itself' not +just what it points to). + + +Replace item +~~~~~~~~~~~~ +`HASH_REPLACE` macros are equivalent to HASH_ADD macros except they attempt +to find and delete the item first. If it finds and deletes an item, it will +also return that items pointer as an output parameter. + + +Find item +~~~~~~~~~ +To look up a structure in a hash, you need its key. Then call `HASH_FIND`. +(Here we use the convenience macro `HASH_FIND_INT` for keys of type `int`). + +.Find a structure using its key +---------------------------------------------------------------------- +struct my_struct *find_user(int user_id) { + struct my_struct *s; + + HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ + return s; +} +---------------------------------------------------------------------- + +Here, the hash table is `users`, and `&user_id` points to the key (an integer +in this case). Last, `s` is the 'output' variable of `HASH_FIND_INT`. The +final result is that `s` points to the structure with the given key, or +is `NULL` if the key wasn't found in the hash. + +[NOTE] +The middle argument is a 'pointer' to the key. You can't pass a literal key +value to `HASH_FIND`. Instead assign the literal value to a variable, and pass +a pointer to the variable. + + +Delete item +~~~~~~~~~~~ +To delete a structure from a hash, you must have a pointer to it. (If you only +have the key, first do a `HASH_FIND` to get the structure pointer). + +.Delete an item from a hash +---------------------------------------------------------------------- +void delete_user(struct my_struct *user) { + HASH_DEL(users, user); /* user: pointer to deletee */ + free(user); /* optional; it's up to you! */ +} +---------------------------------------------------------------------- + +Here again, `users` is the hash table, and `user` is a pointer to the +structure we want to remove from the hash. + +uthash never frees your structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Deleting a structure just removes it from the hash table-- it doesn't `free` +it. The choice of when to free your structure is entirely up to you; uthash +will never free your structure. For example when using `HASH_REPLACE` macros, +a replaced output argument is returned back, in order to make it possible for +the user to de-allocate it. + +Delete can change the pointer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The hash table pointer (which initially points to the first item added to the +hash) can change in response to `HASH_DEL` (i.e. if you delete the first item +in the hash table). + +Iterative deletion +^^^^^^^^^^^^^^^^^^ +The `HASH_ITER` macro is a deletion-safe iteration construct which expands +to a simple 'for' loop. + +.Delete all items from a hash +---------------------------------------------------------------------- +void delete_all() { + struct my_struct *current_user, *tmp; + + HASH_ITER(hh, users, current_user, tmp) { + HASH_DEL(users,current_user); /* delete; users advances to next */ + free(current_user); /* optional- if you want to free */ + } +} +---------------------------------------------------------------------- + +All-at-once deletion +^^^^^^^^^^^^^^^^^^^^ +If you only want to delete all the items, but not free them or do any +per-element clean up, you can do this more efficiently in a single operation: + + HASH_CLEAR(hh,users); + +Afterward, the list head (here, `users`) will be set to `NULL`. + +Count items +~~~~~~~~~~~ + +The number of items in the hash table can be obtained using `HASH_COUNT`: + +.Count of items in the hash table +---------------------------------------------------------------------- +unsigned int num_users; +num_users = HASH_COUNT(users); +printf("there are %u users\n", num_users); +---------------------------------------------------------------------- + +Incidentally, this works even the list (`users`, here) is `NULL`, in +which case the count is 0. + +Iterating and sorting +~~~~~~~~~~~~~~~~~~~~~ + +You can loop over the items in the hash by starting from the beginning and +following the `hh.next` pointer. + +.Iterating over all the items in a hash +---------------------------------------------------------------------- +void print_users() { + struct my_struct *s; + + for(s=users; s != NULL; s=s->hh.next) { + printf("user id %d: name %s\n", s->id, s->name); + } +} +---------------------------------------------------------------------- + +There is also an `hh.prev` pointer you could use to iterate backwards through +the hash, starting from any known item. + +[[deletesafe]] +Deletion-safe iteration +^^^^^^^^^^^^^^^^^^^^^^^ +In the example above, it would not be safe to delete and free `s` in the body +of the 'for' loop, (because `s` is derefenced each time the loop iterates). +This is easy to rewrite correctly (by copying the `s->hh.next` pointer to a +temporary variable 'before' freeing `s`), but it comes up often enough that a +deletion-safe iteration macro, `HASH_ITER`, is included. It expands to a +`for`-loop header. Here is how it could be used to rewrite the last example: + + struct my_struct *s, *tmp; + + HASH_ITER(hh, users, s, tmp) { + printf("user id %d: name %s\n", s->id, s->name); + /* ... it is safe to delete and free s here */ + } + +.A hash is also a doubly-linked list. +******************************************************************************* +Iterating backward and forward through the items in the hash is possible +because of the `hh.prev` and `hh.next` fields. All the items in the hash can +be reached by repeatedly following these pointers, thus the hash is also a +doubly-linked list. +******************************************************************************* + +If you're using uthash in a C++ program, you need an extra cast on the `for` +iterator, e.g., `s=(struct my_struct*)s->hh.next`. + +Sorting +^^^^^^^ +The items in the hash are visited in "insertion order" when you follow the +`hh.next` pointer. You can sort the items into a new order using `HASH_SORT`. + + HASH_SORT( users, name_sort ); + +The second argument is a pointer to a comparison function. It must accept two +pointer arguments (the items to compare), and must return an `int` which is +less than zero, zero, or greater than zero, if the first item sorts before, +equal to, or after the second item, respectively. (This is the same convention +used by `strcmp` or `qsort` in the standard C library). + + int sort_function(void *a, void *b) { + /* compare a to b (cast a and b appropriately) + * return (int) -1 if (a < b) + * return (int) 0 if (a == b) + * return (int) 1 if (a > b) + */ + } + +Below, `name_sort` and `id_sort` are two examples of sort functions. + +.Sorting the items in the hash +---------------------------------------------------------------------- +int name_sort(struct my_struct *a, struct my_struct *b) { + return strcmp(a->name,b->name); +} + +int id_sort(struct my_struct *a, struct my_struct *b) { + return (a->id - b->id); +} + +void sort_by_name() { + HASH_SORT(users, name_sort); +} + +void sort_by_id() { + HASH_SORT(users, id_sort); +} +---------------------------------------------------------------------- + +When the items in the hash are sorted, the first item may change position. In +the example above, `users` may point to a different structure after calling +`HASH_SORT`. + +A complete example +~~~~~~~~~~~~~~~~~~ + +We'll repeat all the code and embellish it with a `main()` function to form a +working example. + +If this code was placed in a file called `example.c` in the same directory as +`uthash.h`, it could be compiled and run like this: + + cc -o example example.c + ./example + +Follow the prompts to try the program. + +.A complete program +---------------------------------------------------------------------- +#include /* gets */ +#include /* atoi, malloc */ +#include /* strcpy */ +#include "uthash.h" + +struct my_struct { + int id; /* key */ + char name[10]; + UT_hash_handle hh; /* makes this structure hashable */ +}; + +struct my_struct *users = NULL; + +void add_user(int user_id, char *name) { + struct my_struct *s; + + HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ + if (s==NULL) { + s = (struct my_struct *)malloc(sizeof *s); + s->id = user_id; + HASH_ADD_INT( users, id, s ); /* id: name of key field */ + } + strcpy(s->name, name); +} + +struct my_struct *find_user(int user_id) { + struct my_struct *s; + + HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ + return s; +} + +void delete_user(struct my_struct *user) { + HASH_DEL(users, user); /* user: pointer to deletee */ + free(user); +} + +void delete_all() { + struct my_struct *current_user, *tmp; + + HASH_ITER(hh, users, current_user, tmp) { + HASH_DEL(users, current_user); /* delete it (users advances to next) */ + free(current_user); /* free it */ + } +} + +void print_users() { + struct my_struct *s; + + for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) { + printf("user id %d: name %s\n", s->id, s->name); + } +} + +int name_sort(struct my_struct *a, struct my_struct *b) { + return strcmp(a->name,b->name); +} + +int id_sort(struct my_struct *a, struct my_struct *b) { + return (a->id - b->id); +} + +void sort_by_name() { + HASH_SORT(users, name_sort); +} + +void sort_by_id() { + HASH_SORT(users, id_sort); +} + +int main(int argc, char *argv[]) { + char in[10]; + int id=1, running=1; + struct my_struct *s; + unsigned num_users; + + while (running) { + printf(" 1. add user\n"); + printf(" 2. add/rename user by id\n"); + printf(" 3. find user\n"); + printf(" 4. delete user\n"); + printf(" 5. delete all users\n"); + printf(" 6. sort items by name\n"); + printf(" 7. sort items by id\n"); + printf(" 8. print users\n"); + printf(" 9. count users\n"); + printf("10. quit\n"); + gets(in); + switch(atoi(in)) { + case 1: + printf("name?\n"); + add_user(id++, gets(in)); + break; + case 2: + printf("id?\n"); + gets(in); id = atoi(in); + printf("name?\n"); + add_user(id, gets(in)); + break; + case 3: + printf("id?\n"); + s = find_user(atoi(gets(in))); + printf("user: %s\n", s ? s->name : "unknown"); + break; + case 4: + printf("id?\n"); + s = find_user(atoi(gets(in))); + if (s) delete_user(s); + else printf("id unknown\n"); + break; + case 5: + delete_all(); + break; + case 6: + sort_by_name(); + break; + case 7: + sort_by_id(); + break; + case 8: + print_users(); + break; + case 9: + num_users=HASH_COUNT(users); + printf("there are %u users\n", num_users); + break; + case 10: + running=0; + break; + } + } + + delete_all(); /* free any structures */ + return 0; +} +---------------------------------------------------------------------- + +This program is included in the distribution in `tests/example.c`. You can run +`make example` in that directory to compile it easily. + +Standard key types +------------------ +This section goes into specifics of how to work with different kinds of keys. +You can use nearly any type of key-- integers, strings, pointers, structures, etc. + +[NOTE] +.A note about float +================================================================================ +You can use floating point keys. This comes with the same caveats as with any +program that tests floating point equality. In other words, even the tiniest +difference in two floating point numbers makes them distinct keys. +================================================================================ + +Integer keys +~~~~~~~~~~~~ +The preceding examples demonstrated use of integer keys. To recap, use the +convenience macros `HASH_ADD_INT` and `HASH_FIND_INT` for structures with +integer keys. (The other operations such as `HASH_DELETE` and `HASH_SORT` are +the same for all types of keys). + +String keys +~~~~~~~~~~~ +If your structure has a string key, the operations to use depend on whether your +structure 'points to' the key (`char *`) or the string resides `within` the +structure (`char a[10]`). *This distinction is important*. As we'll see below, +you need to use `HASH_ADD_KEYPTR` when your structure 'points' to a key (that is, +the key itself is 'outside' of the structure); in contrast, use `HASH_ADD_STR` +for a string key that is contained *within* your structure. + +[NOTE] +.char[ ] vs. char* +================================================================================ +The string is 'within' the structure in the first example below-- `name` is a +`char[10]` field. In the second example, the key is 'outside' of the +structure-- `name` is a `char *`. So the first example uses `HASH_ADD_STR` but +the second example uses `HASH_ADD_KEYPTR`. For information on this macro, see +the <>. +================================================================================ + +String 'within' structure +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.A string-keyed hash (string within structure) +---------------------------------------------------------------------- +#include /* strcpy */ +#include /* malloc */ +#include /* printf */ +#include "uthash.h" + +struct my_struct { + char name[10]; /* key (string is WITHIN the structure) */ + int id; + UT_hash_handle hh; /* makes this structure hashable */ +}; + + +int main(int argc, char *argv[]) { + const char *names[] = { "joe", "bob", "betty", NULL }; + struct my_struct *s, *tmp, *users = NULL; + + for (int i = 0; names[i]; ++i) { + s = (struct my_struct *)malloc(sizeof *s); + strcpy(s->name, names[i]); + s->id = i; + HASH_ADD_STR( users, name, s ); + } + + HASH_FIND_STR( users, "betty", s); + if (s) printf("betty's id is %d\n", s->id); + + /* free the hash table contents */ + HASH_ITER(hh, users, s, tmp) { + HASH_DEL(users, s); + free(s); + } + return 0; +} +---------------------------------------------------------------------- + +This example is included in the distribution in `tests/test15.c`. It prints: + + betty's id is 2 + +String 'pointer' in structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now, here is the same example but using a `char *` key instead of `char [ ]`: + +.A string-keyed hash (structure points to string) +---------------------------------------------------------------------- +#include /* strcpy */ +#include /* malloc */ +#include /* printf */ +#include "uthash.h" + +struct my_struct { + const char *name; /* key */ + int id; + UT_hash_handle hh; /* makes this structure hashable */ +}; + + +int main(int argc, char *argv[]) { + const char *names[] = { "joe", "bob", "betty", NULL }; + struct my_struct *s, *tmp, *users = NULL; + + for (int i = 0; names[i]; ++i) { + s = (struct my_struct *)malloc(sizeof *s); + s->name = names[i]; + s->id = i; + HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s ); + } + + HASH_FIND_STR( users, "betty", s); + if (s) printf("betty's id is %d\n", s->id); + + /* free the hash table contents */ + HASH_ITER(hh, users, s, tmp) { + HASH_DEL(users, s); + free(s); + } + return 0; +} +---------------------------------------------------------------------- + +This example is included in `tests/test40.c`. + +Pointer keys +~~~~~~~~~~~~ +Your key can be a pointer. To be very clear, this means the 'pointer itself' +can be the key (in contrast, if the thing 'pointed to' is the key, this is a +different use case handled by `HASH_ADD_KEYPTR`). + +Here is a simple example where a structure has a pointer member, called `key`. + +.A pointer key +---------------------------------------------------------------------- +#include +#include +#include "uthash.h" + +typedef struct { + void *key; + int i; + UT_hash_handle hh; +} el_t; + +el_t *hash = NULL; +char *someaddr = NULL; + +int main() { + el_t *d; + el_t *e = (el_t *)malloc(sizeof *e); + if (!e) return -1; + e->key = (void*)someaddr; + e->i = 1; + HASH_ADD_PTR(hash,key,e); + HASH_FIND_PTR(hash, &someaddr, d); + if (d) printf("found\n"); + + /* release memory */ + HASH_DEL(hash,e); + free(e); + return 0; +} +---------------------------------------------------------------------- + +This example is included in `tests/test57.c`. Note that the end of the program +deletes the element out of the hash, (and since no more elements remain in the +hash), uthash releases its internal memory. + +Structure keys +~~~~~~~~~~~~~~ +Your key field can have any data type. To uthash, it is just a sequence of +bytes. Therefore, even a nested structure can be used as a key. We'll use the +general macros `HASH_ADD` and `HASH_FIND` to demonstrate. + +NOTE: Structures contain padding (wasted internal space used to fulfill +alignment requirements for the members of the structure). These padding bytes +'must be zeroed' before adding an item to the hash or looking up an item. +Therefore always zero the whole structure before setting the members of +interest. The example below does this-- see the two calls to `memset`. + +.A key which is a structure +---------------------------------------------------------------------- +#include +#include +#include "uthash.h" + +typedef struct { + char a; + int b; +} record_key_t; + +typedef struct { + record_key_t key; + /* ... other data ... */ + UT_hash_handle hh; +} record_t; + +int main(int argc, char *argv[]) { + record_t l, *p, *r, *tmp, *records = NULL; + + r = (record_t *)malloc(sizeof *r); + memset(r, 0, sizeof *r); + r->key.a = 'a'; + r->key.b = 1; + HASH_ADD(hh, records, key, sizeof(record_key_t), r); + + memset(&l, 0, sizeof(record_t)); + l.key.a = 'a'; + l.key.b = 1; + HASH_FIND(hh, records, &l.key, sizeof(record_key_t), p); + + if (p) printf("found %c %d\n", p->key.a, p->key.b); + + HASH_ITER(hh, records, p, tmp) { + HASH_DEL(records, p); + free(p); + } + return 0; +} + +---------------------------------------------------------------------- + +This usage is nearly the same as use of a compound key explained below. + +Note that the general macros require the name of the `UT_hash_handle` to be +passed as the first argument (here, this is `hh`). The general macros are +documented in <>. + +Advanced Topics +--------------- + +Compound keys +~~~~~~~~~~~~~ +Your key can even comprise multiple contiguous fields. + +.A multi-field key +---------------------------------------------------------------------- +#include /* malloc */ +#include /* offsetof */ +#include /* printf */ +#include /* memset */ +#include "uthash.h" + +#define UTF32 1 + +typedef struct { + UT_hash_handle hh; + int len; + char encoding; /* these two fields */ + int text[]; /* comprise the key */ +} msg_t; + +typedef struct { + char encoding; + int text[]; +} lookup_key_t; + +int main(int argc, char *argv[]) { + unsigned keylen; + msg_t *msg, *tmp, *msgs = NULL; + lookup_key_t *lookup_key; + + int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ + + /* allocate and initialize our structure */ + msg = (msg_t *)malloc( sizeof(msg_t) + sizeof(beijing) ); + memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */ + msg->len = sizeof(beijing); + msg->encoding = UTF32; + memcpy(msg->text, beijing, sizeof(beijing)); + + /* calculate the key length including padding, using formula */ + keylen = offsetof(msg_t, text) /* offset of last key field */ + + sizeof(beijing) /* size of last key field */ + - offsetof(msg_t, encoding); /* offset of first key field */ + + /* add our structure to the hash table */ + HASH_ADD( hh, msgs, encoding, keylen, msg); + + /* look it up to prove that it worked :-) */ + msg=NULL; + + lookup_key = (lookup_key_t *)malloc(sizeof(*lookup_key) + sizeof(beijing)); + memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing)); + lookup_key->encoding = UTF32; + memcpy(lookup_key->text, beijing, sizeof(beijing)); + HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg ); + if (msg) printf("found \n"); + free(lookup_key); + + HASH_ITER(hh, msgs, msg, tmp) { + HASH_DEL(msgs, msg); + free(msg); + } + return 0; +} +---------------------------------------------------------------------- + +This example is included in the distribution in `tests/test22.c`. + +If you use multi-field keys, recognize that the compiler pads adjacent fields +(by inserting unused space between them) in order to fulfill the alignment +requirement of each field. For example a structure containing a `char` followed +by an `int` will normally have 3 "wasted" bytes of padding after the char, in +order to make the `int` field start on a multiple-of-4 address (4 is the length +of the int). + +[[multifield_note]] +.Calculating the length of a multi-field key: +******************************************************************************* +To determine the key length when using a multi-field key, you must include any +intervening structure padding the compiler adds for alignment purposes. + +An easy way to calculate the key length is to use the `offsetof` macro from +``. The formula is: + + key length = offsetof(last_key_field) + + sizeof(last_key_field) + - offsetof(first_key_field) + +In the example above, the `keylen` variable is set using this formula. +******************************************************************************* + +When dealing with a multi-field key, you must zero-fill your structure before +`HASH_ADD`'ing it to a hash table, or using its fields in a `HASH_FIND` key. + +In the previous example, `memset` is used to initialize the structure by +zero-filling it. This zeroes out any padding between the key fields. If we +didn't zero-fill the structure, this padding would contain random values. The +random values would lead to `HASH_FIND` failures; as two "identical" keys will +appear to mismatch if there are any differences within their padding. + +Alternatively, you can customize the global <> +and <> to ignore the padding in your key. +See <>. + +[[multilevel]] +Multi-level hash tables +~~~~~~~~~~~~~~~~~~~~~~~ +A multi-level hash table arises when each element of a hash table contains its +own secondary hash table. There can be any number of levels. In a scripting +language you might see: + + $items{bob}{age}=37 + +The C program below builds this example in uthash: the hash table is called +`items`. It contains one element (`bob`) whose own hash table contains one +element (`age`) with value 37. No special functions are necessary to build +a multi-level hash table. + +While this example represents both levels (`bob` and `age`) using the same +structure, it would also be fine to use two different structure definitions. +It would also be fine if there were three or more levels instead of two. + +.Multi-level hash table +---------------------------------------------------------------------- +#include +#include +#include +#include "uthash.h" + +/* hash of hashes */ +typedef struct item { + char name[10]; + struct item *sub; + int val; + UT_hash_handle hh; +} item_t; + +item_t *items=NULL; + +int main(int argc, char *argvp[]) { + item_t *item1, *item2, *tmp1, *tmp2; + + /* make initial element */ + item_t *i = malloc(sizeof(*i)); + strcpy(i->name, "bob"); + i->sub = NULL; + i->val = 0; + HASH_ADD_STR(items, name, i); + + /* add a sub hash table off this element */ + item_t *s = malloc(sizeof(*s)); + strcpy(s->name, "age"); + s->sub = NULL; + s->val = 37; + HASH_ADD_STR(i->sub, name, s); + + /* iterate over hash elements */ + HASH_ITER(hh, items, item1, tmp1) { + HASH_ITER(hh, item1->sub, item2, tmp2) { + printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); + } + } + + /* clean up both hash tables */ + HASH_ITER(hh, items, item1, tmp1) { + HASH_ITER(hh, item1->sub, item2, tmp2) { + HASH_DEL(item1->sub, item2); + free(item2); + } + HASH_DEL(items, item1); + free(item1); + } + + return 0; +} +---------------------------------------------------------------------- +The example above is included in `tests/test59.c`. + +[[multihash]] +Items in several hash tables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A structure can be added to more than one hash table. A few reasons you might do +this include: + +- each hash table may use a different key; +- each hash table may have its own sort order; +- or you might simply use multiple hash tables for grouping purposes. E.g., + you could have users in an `admin_users` and a `users` hash table. + +Your structure needs to have a `UT_hash_handle` field for each hash table to +which it might be added. You can name them anything. E.g., + + UT_hash_handle hh1, hh2; + +Items with multiple keys +~~~~~~~~~~~~~~~~~~~~~~~~ +You might create a hash table keyed on an ID field, and another hash table keyed +on username (if usernames are unique). You can add the same user structure to +both hash tables (without duplication of the structure), allowing lookup of a +user structure by their name or ID. The way to achieve this is to have a +separate `UT_hash_handle` for each hash to which the structure may be added. + +.A structure with two different keys +---------------------------------------------------------------------- +struct my_struct { + int id; /* first key */ + char username[10]; /* second key */ + UT_hash_handle hh1; /* handle for first hash table */ + UT_hash_handle hh2; /* handle for second hash table */ +}; +---------------------------------------------------------------------- + +In the example above, the structure can now be added to two separate hash +tables. In one hash, `id` is its key, while in the other hash, `username` is +its key. (There is no requirement that the two hashes have different key +fields. They could both use the same key, such as `id`). + +Notice the structure has two hash handles (`hh1` and `hh2`). In the code +below, notice that each hash handle is used exclusively with a particular hash +table. (`hh1` is always used with the `users_by_id` hash, while `hh2` is +always used with the `users_by_name` hash table). + +.Two keys on a structure +---------------------------------------------------------------------- + struct my_struct *users_by_id = NULL, *users_by_name = NULL, *s; + int i; + char *name; + + s = malloc(sizeof(struct my_struct)); + s->id = 1; + strcpy(s->username, "thanson"); + + /* add the structure to both hash tables */ + HASH_ADD(hh1, users_by_id, id, sizeof(int), s); + HASH_ADD(hh2, users_by_name, username, strlen(s->username), s); + + /* find user by ID in the "users_by_id" hash table */ + i=1; + HASH_FIND(hh1, users_by_id, &i, sizeof(int), s); + if (s) printf("found id %d: %s\n", i, s->username); + + /* find user by username in the "users_by_name" hash table */ + name = "thanson"; + HASH_FIND(hh2, users_by_name, name, strlen(name), s); + if (s) printf("found user %s: %d\n", name, s->id); +---------------------------------------------------------------------- + + +Sorted insertion of new items +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If you would like to maintain a sorted hash you have two options. The first +option is to use the HASH_SRT() macro, which will sort any unordered list in +'O(n log(n))'. This is the best strategy if you're just filling up a hash +table with items in random order with a single final HASH_SRT() operation +when all is done. Obviously, this won't do what you want if you need +the list to be in an ordered state at times between insertion of +items. You can use HASH_SRT() after every insertion operation, but that will +yield a computational complexity of 'O(n^2 log n)'. + +The second route you can take is via the in-order add and replace macros. +The `HASH_ADD_INORDER*` macros work just like their `HASH_ADD*` counterparts, but +with an additional comparison-function argument: + + int name_sort(struct my_struct *a, struct my_struct *b) { + return strcmp(a->name,b->name); + } + + HASH_ADD_KEYPTR_INORDER(hh, items, &item->name, strlen(item->name), item, name_sort); + +New items are sorted at insertion time in 'O(n)', thus resulting in a +total computational complexity of 'O(n^2)' for the creation of the hash +table with all items. +For in-order add to work, the list must be in an ordered state before +insertion of the new item. + +Several sort orders +~~~~~~~~~~~~~~~~~~~ +It comes as no surprise that two hash tables can have different sort orders, but +this fact can also be used advantageously to sort the 'same items' in several +ways. This is based on the ability to store a structure in several hash tables. + +Extending the previous example, suppose we have many users. We have added each +user structure to the `users_by_id` hash table and the `users_by_name` hash table. +(To reiterate, this is done without the need to have two copies of each structure.) +Now we can define two sort functions, then use `HASH_SRT`. + + int sort_by_id(struct my_struct *a, struct my_struct *b) { + if (a->id == b->id) return 0; + return (a->id < b->id) ? -1 : 1; + } + + int sort_by_name(struct my_struct *a, struct my_struct *b) { + return strcmp(a->username,b->username); + } + + HASH_SRT(hh1, users_by_id, sort_by_id); + HASH_SRT(hh2, users_by_name, sort_by_name); + +Now iterating over the items in `users_by_id` will traverse them in id-order +while, naturally, iterating over `users_by_name` will traverse them in +name-order. The items are fully forward-and-backward linked in each order. +So even for one set of users, we might store them in two hash tables to provide +easy iteration in two different sort orders. + +Bloom filter (faster misses) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Programs that generate a fair miss rate (`HASH_FIND` that result in `NULL`) may +benefit from the built-in Bloom filter support. This is disabled by default, +because programs that generate only hits would incur a slight penalty from it. +Also, programs that do deletes should not use the Bloom filter. While the +program would operate correctly, deletes diminish the benefit of the filter. +To enable the Bloom filter, simply compile with `-DHASH_BLOOM=n` like: + + -DHASH_BLOOM=27 + +where the number can be any value up to 32 which determines the amount of memory +used by the filter, as shown below. Using more memory makes the filter more +accurate and has the potential to speed up your program by making misses bail +out faster. + +.Bloom filter sizes for selected values of n +[width="50%",cols="10m,30",grid="none",options="header"] +|===================================================================== +| n | Bloom filter size (per hash table) +| 16 | 8 kilobytes +| 20 | 128 kilobytes +| 24 | 2 megabytes +| 28 | 32 megabytes +| 32 | 512 megabytes +|===================================================================== + +Bloom filters are only a performance feature; they do not change the results of +hash operations in any way. The only way to gauge whether or not a Bloom filter +is right for your program is to test it. Reasonable values for the size of the +Bloom filter are 16-32 bits. + +Select +~~~~~~ +An experimental 'select' operation is provided that inserts those items from a +source hash that satisfy a given condition into a destination hash. This +insertion is done with somewhat more efficiency than if this were using +`HASH_ADD`, namely because the hash function is not recalculated for keys of the +selected items. This operation does not remove any items from the source hash. +Rather the selected items obtain dual presence in both hashes. The destination +hash may already have items in it; the selected items are added to it. In order +for a structure to be usable with `HASH_SELECT`, it must have two or more hash +handles. (As described <>, a structure can exist in many +hash tables at the same time; it must have a separate hash handle for each one). + + user_t *users=NULL, *admins=NULL; /* two hash tables */ + + typedef struct { + int id; + UT_hash_handle hh; /* handle for users hash */ + UT_hash_handle ah; /* handle for admins hash */ + } user_t; + +Now suppose we have added some users, and want to select just the administrator +users who have id's less than 1024. + + #define is_admin(x) (((user_t*)x)->id < 1024) + HASH_SELECT(ah,admins,hh,users,is_admin); + +The first two parameters are the 'destination' hash handle and hash table, the +second two parameters are the 'source' hash handle and hash table, and the last +parameter is the 'select condition'. Here we used a macro `is_admin()` but we +could just as well have used a function. + + int is_admin(void *userv) { + user_t *user = (user_t*)userv; + return (user->id < 1024) ? 1 : 0; + } + +If the select condition always evaluates to true, this operation is +essentially a 'merge' of the source hash into the destination hash. Of course, +the source hash remains unchanged under any use of `HASH_SELECT`. It only adds +items to the destination hash selectively. + +The two hash handles must differ. An example of using `HASH_SELECT` is included +in `tests/test36.c`. + +[[hash_keycompare]] +Specifying an alternate key comparison function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you call `HASH_FIND(hh, head, intfield, sizeof(int), out)`, uthash will +first call <>`(intfield, sizeof(int), hashvalue)` to +determine the bucket `b` in which to search, and then, for each element `elt` +of bucket `b`, uthash will evaluate +`elt->hh.hashv == hashvalue && elt.hh.keylen == sizeof(int) && HASH_KEYCMP(intfield, elt->hh.key, sizeof(int)) == 0`. +`HASH_KEYCMP` should return `0` to indicate that `elt` is a match and should be +returned, and any non-zero value to indicate that the search for a matching +element should continue. + +By default, uthash defines `HASH_KEYCMP` as an alias for `memcmp`. On platforms +that do not provide `memcmp`, you can substitute your own implementation. + +---------------------------------------------------------------------------- +#undef HASH_KEYCMP +#define HASH_KEYCMP(a,b,len) bcmp(a,b,len) +---------------------------------------------------------------------------- + +Another reason to substitute your own key comparison function is if your "key" is not +trivially comparable. In this case you will also need to substitute your own `HASH_FUNCTION`. + +---------------------------------------------------------------------------- +struct Key { + short s; + /* 2 bytes of padding */ + float f; +}; +/* do not compare the padding bytes; do not use memcmp on floats */ +unsigned key_hash(struct Key *s) { return s + (unsigned)f; } +bool key_equal(struct Key *a, struct Key *b) { return a.s == b.s && a.f == b.f; } + +#define HASH_FUNCTION(s,len,hashv) (hashv) = key_hash((struct Key *)s) +#define HASH_KEYCMP(a,b,len) (!key_equal((struct Key *)a, (struct Key *)b)) +---------------------------------------------------------------------------- + +Another reason to substitute your own key comparison function is to trade off +correctness for raw speed. During its linear search of a bucket, uthash always +compares the 32-bit `hashv` first, and calls `HASH_KEYCMP` only if the `hashv` +compares equal. This means that `HASH_KEYCMP` is called at least once per +successful find. Given a good hash function, we expect the `hashv` comparison to +produce a "false positive" equality only once in four billion times. Therefore, +we expect `HASH_KEYCMP` to produce `0` most of the time. If we expect many +successful finds, and our application doesn't mind the occasional false positive, +we might substitute a no-op comparison function: + +---------------------------------------------------------------------------- +#undef HASH_KEYCMP +#define HASH_KEYCMP(a,b,len) 0 /* occasionally wrong, but very fast */ +---------------------------------------------------------------------------- + +Note: The global equality-comparison function `HASH_KEYCMP` has no relationship +at all to the lessthan-comparison function passed as a parameter to `HASH_ADD_INORDER`. + +[[hash_functions]] +Built-in hash functions +~~~~~~~~~~~~~~~~~~~~~~~ +Internally, a hash function transforms a key into a bucket number. You don't +have to take any action to use the default hash function, currently Jenkins. + +Some programs may benefit from using another of the built-in hash functions. +There is a simple analysis utility included with uthash to help you determine +if another hash function will give you better performance. + +You can use a different hash function by compiling your program with +`-DHASH_FUNCTION=HASH_xyz` where `xyz` is one of the symbolic names listed +below. E.g., + + cc -DHASH_FUNCTION=HASH_BER -o program program.c + +.Built-in hash functions +[width="50%",cols="^5m,20",grid="none",options="header"] +|=============================================================================== +|Symbol | Name +|JEN | Jenkins (default) +|BER | Bernstein +|SAX | Shift-Add-Xor +|OAT | One-at-a-time +|FNV | Fowler/Noll/Vo +|SFH | Paul Hsieh +|=============================================================================== + +Which hash function is best? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +You can easily determine the best hash function for your key domain. To do so, +you'll need to run your program once in a data-collection pass, and then run +the collected data through an included analysis utility. + +First you must build the analysis utility. From the top-level directory, + + cd tests/ + make + +We'll use `test14.c` to demonstrate the data-collection and analysis steps +(here using `sh` syntax to redirect file descriptor 3 to a file): + +.Using keystats +-------------------------------------------------------------------------------- +% cc -DHASH_EMIT_KEYS=3 -I../src -o test14 test14.c +% ./test14 3>test14.keys +% ./keystats test14.keys +fcn ideal% #items #buckets dup% fl add_usec find_usec del-all usec +--- ------ ---------- ---------- ----- -- ---------- ---------- ------------ +SFH 91.6% 1219 256 0% ok 92 131 25 +FNV 90.3% 1219 512 0% ok 107 97 31 +SAX 88.7% 1219 512 0% ok 111 109 32 +OAT 87.2% 1219 256 0% ok 99 138 26 +JEN 86.7% 1219 256 0% ok 87 130 27 +BER 86.2% 1219 256 0% ok 121 129 27 +-------------------------------------------------------------------------------- + +[NOTE] +The number 3 in `-DHASH_EMIT_KEYS=3` is a file descriptor. Any file descriptor +that your program doesn't use for its own purposes can be used instead of 3. +The data-collection mode enabled by `-DHASH_EMIT_KEYS=x` should not be used in +production code. + +Usually, you should just pick the first hash function that is listed. Here, this +is `SFH`. This is the function that provides the most even distribution for +your keys. If several have the same `ideal%`, then choose the fastest one +according to the `find_usec` column. + +keystats column reference +^^^^^^^^^^^^^^^^^^^^^^^^^ +fcn:: + symbolic name of hash function +ideal%:: + The percentage of items in the hash table which can be looked up within an + ideal number of steps. (Further explained below). +#items:: + the number of keys that were read in from the emitted key file +#buckets:: + the number of buckets in the hash after all the keys were added +dup%:: + the percent of duplicate keys encountered in the emitted key file. + Duplicates keys are filtered out to maintain key uniqueness. (Duplicates + are normal. For example, if the application adds an item to a hash, + deletes it, then re-adds it, the key is written twice to the emitted file.) +flags:: + this is either `ok`, or `nx` (noexpand) if the expansion inhibited flag is + set, described in <>. It is not recommended + to use a hash function that has the `noexpand` flag set. +add_usec:: + the clock time in microseconds required to add all the keys to a hash +find_usec:: + the clock time in microseconds required to look up every key in the hash +del-all usec:: + the clock time in microseconds required to delete every item in the hash + +[[ideal]] +ideal% +^^^^^^ + +.What is ideal%? +***************************************************************************** +The 'n' items in a hash are distributed into 'k' buckets. Ideally each bucket +would contain an equal share '(n/k)' of the items. In other words, the maximum +linear position of any item in a bucket chain would be 'n/k' if every bucket is +equally used. If some buckets are overused and others are underused, the +overused buckets will contain items whose linear position surpasses 'n/k'. +Such items are considered non-ideal. + +As you might guess, `ideal%` is the percentage of ideal items in the hash. These +items have favorable linear positions in their bucket chains. As `ideal%` +approaches 100%, the hash table approaches constant-time lookup performance. +***************************************************************************** + +[[hashscan]] +hashscan +~~~~~~~~ +NOTE: This utility is only available on Linux, and on FreeBSD (8.1 and up). + +A utility called `hashscan` is included in the `tests/` directory. It +is built automatically when you run `make` in that directory. This tool +examines a running process and reports on the uthash tables that it finds in +that program's memory. It can also save the keys from each table in a format +that can be fed into `keystats`. + +Here is an example of using `hashscan`. First ensure that it is built: + + cd tests/ + make + +Since `hashscan` needs a running program to inspect, we'll start up a simple +program that makes a hash table and then sleeps as our test subject: + + ./test_sleep & + pid: 9711 + +Now that we have a test program, let's run `hashscan` on it: + + ./hashscan 9711 + Address ideal items buckets mc fl bloom/sat fcn keys saved to + ------------------ ----- -------- -------- -- -- --------- --- ------------- + 0x862e038 81% 10000 4096 11 ok 16 14% JEN + +If we wanted to copy out all its keys for external analysis using `keystats`, +add the `-k` flag: + + ./hashscan -k 9711 + Address ideal items buckets mc fl bloom/sat fcn keys saved to + ------------------ ----- -------- -------- -- -- --------- --- ------------- + 0x862e038 81% 10000 4096 11 ok 16 14% JEN /tmp/9711-0.key + +Now we could run `./keystats /tmp/9711-0.key` to analyze which hash function +has the best characteristics on this set of keys. + +hashscan column reference +^^^^^^^^^^^^^^^^^^^^^^^^^ +Address:: + virtual address of the hash table +ideal:: + The percentage of items in the table which can be looked up within an ideal + number of steps. See <> in the `keystats` section. +items:: + number of items in the hash table +buckets:: + number of buckets in the hash table +mc:: + the maximum chain length found in the hash table (uthash usually tries to + keep fewer than 10 items in each bucket, or in some cases a multiple of 10) +fl:: + flags (either `ok`, or `NX` if the expansion-inhibited flag is set) +bloom/sat:: + if the hash table uses a Bloom filter, this is the size (as a power of two) + of the filter (e.g. 16 means the filter is 2^16 bits in size). The second + number is the "saturation" of the bits expressed as a percentage. The lower + the percentage, the more potential benefit to identify cache misses quickly. +fcn:: + symbolic name of hash function +keys saved to:: + file to which keys were saved, if any + +.How hashscan works +***************************************************************************** +When hashscan runs, it attaches itself to the target process, which suspends +the target process momentarily. During this brief suspension, it scans the +target's virtual memory for the signature of a uthash hash table. It then +checks if a valid hash table structure accompanies the signature and reports +what it finds. When it detaches, the target process resumes running normally. +The hashscan is performed "read-only"-- the target process is not modified. +Since hashscan is analyzing a momentary snapshot of a running process, it may +return different results from one run to another. +***************************************************************************** + +[[expansion]] +Expansion internals +~~~~~~~~~~~~~~~~~~~ +Internally this hash manages the number of buckets, with the goal of having +enough buckets so that each one contains only a small number of items. + +.Why does the number of buckets matter? +******************************************************************************** +When looking up an item by its key, this hash scans linearly through the items +in the appropriate bucket. In order for the linear scan to run in constant +time, the number of items in each bucket must be bounded. This is accomplished +by increasing the number of buckets as needed. +******************************************************************************** + +Normal expansion +^^^^^^^^^^^^^^^^ +This hash attempts to keep fewer than 10 items in each bucket. When an item is +added that would cause a bucket to exceed this number, the number of buckets in +the hash is doubled and the items are redistributed into the new buckets. In an +ideal world, each bucket will then contain half as many items as it did before. + +Bucket expansion occurs automatically and invisibly as needed. There is +no need for the application to know when it occurs. + +Per-bucket expansion threshold +++++++++++++++++++++++++++++++ +Normally all buckets share the same threshold (10 items) at which point bucket +expansion is triggered. During the process of bucket expansion, uthash can +adjust this expansion-trigger threshold on a per-bucket basis if it sees that +certain buckets are over-utilized. + +When this threshold is adjusted, it goes from 10 to a multiple of 10 (for that +particular bucket). The multiple is based on how many times greater the actual +chain length is than the ideal length. It is a practical measure to reduce +excess bucket expansion in the case where a hash function over-utilizes a few +buckets but has good overall distribution. However, if the overall distribution +gets too bad, uthash changes tactics. + +Inhibited expansion +^^^^^^^^^^^^^^^^^^^ +You usually don't need to know or worry about this, particularly if you used +the `keystats` utility during development to select a good hash for your keys. + +A hash function may yield an uneven distribution of items across the buckets. +In moderation this is not a problem. Normal bucket expansion takes place as +the chain lengths grow. But when significant imbalance occurs (because the hash +function is not well suited to the key domain), bucket expansion may be +ineffective at reducing the chain lengths. + +Imagine a very bad hash function which always puts every item in bucket 0. No +matter how many times the number of buckets is doubled, the chain length of +bucket 0 stays the same. In a situation like this, the best behavior is to +stop expanding, and accept 'O(n)' lookup performance. This is what uthash +does. It degrades gracefully if the hash function is ill-suited to the keys. + +If two consecutive bucket expansions yield `ideal%` values below 50%, uthash +inhibits expansion for that hash table. Once set, the 'bucket expansion +inhibited' flag remains in effect as long as the hash has items in it. +Inhibited expansion may cause `HASH_FIND` to exhibit worse than constant-time +performance. + +Diagnostic hooks +^^^^^^^^^^^^^^^^ + +There are two "notification" hooks which get executed if uthash is +expanding buckets, or setting the 'bucket expansion inhibited' flag. +There is no need for the application to set these hooks or take action in +response to these events. They are mainly for diagnostic purposes. +Normally both of these hooks are undefined and thus compile away to nothing. + +The `uthash_expand_fyi` hook can be defined to execute code whenever +uthash performs a bucket expansion. + +---------------------------------------------------------------------------- +#undef uthash_expand_fyi +#define uthash_expand_fyi(tbl) printf("expanded to %u buckets\n", tbl->num_buckets) +---------------------------------------------------------------------------- + +The `uthash_noexpand_fyi` hook can be defined to execute code whenever +uthash sets the 'bucket expansion inhibited' flag. + +---------------------------------------------------------------------------- +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) printf("warning: bucket expansion inhibited\n") +---------------------------------------------------------------------------- + +Hooks +~~~~~ +You don't need to use these hooks -- they are only here if you want to modify +the behavior of uthash. Hooks can be used to replace standard library functions +that might be unavailable on some platforms, to change how uthash allocates +memory, or to run code in response to certain internal events. + +The `uthash.h` header will define these hooks to default values, unless they +are already defined. It is safe either to `#undef` and redefine them +after including `uthash.h`, or to define them before inclusion; for +example, by passing `-Duthash_malloc=my_malloc` on the command line. + +Specifying alternate memory management functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, uthash uses `malloc` and `free` to manage memory. +If your application uses its own custom allocator, uthash can use them too. + +---------------------------------------------------------------------------- +#include "uthash.h" + +/* undefine the defaults */ +#undef uthash_malloc +#undef uthash_free + +/* re-define, specifying alternate functions */ +#define uthash_malloc(sz) my_malloc(sz) +#define uthash_free(ptr,sz) my_free(ptr) + +... +---------------------------------------------------------------------------- + +Notice that `uthash_free` receives two parameters. The `sz` parameter is for +convenience on embedded platforms that manage their own memory. + +Specifying alternate standard library functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Uthash also uses `strlen` (in the `HASH_FIND_STR` convenience macro, for +example) and `memset` (used only for zeroing memory). On platforms that do not +provide these functions, you can substitute your own implementations. + +---------------------------------------------------------------------------- +#undef uthash_bzero +#define uthash_bzero(a,len) my_bzero(a,len) + +#undef uthash_strlen +#define uthash_strlen(s) my_strlen(s) +---------------------------------------------------------------------------- + +Out of memory +^^^^^^^^^^^^^ +If memory allocation fails (i.e., the `uthash_malloc` function returns `NULL`), +the default behavior is to terminate the process by calling `exit(-1)`. This +can be modified by re-defining the `uthash_fatal` macro. + +---------------------------------------------------------------------------- +#undef uthash_fatal +#define uthash_fatal(msg) my_fatal_function(msg) +---------------------------------------------------------------------------- + +The fatal function should terminate the process or `longjmp` back to a safe +place. Note that an allocation failure may leave allocated memory that cannot +be recovered. After `uthash_fatal`, the hash table object should be considered +unusable; it might not be safe even to run `HASH_CLEAR` on the hash table +when it is in this state. + +To enable "returning a failure" if memory cannot be allocated, define the +macro `HASH_NONFATAL_OOM` before including the `uthash.h` header file. In this +case, `uthash_fatal` is not used; instead, each allocation failure results in +a single call to `uthash_nonfatal_oom(elt)` where `elt` is the address of the +element whose insertion triggered the failure. The default behavior of +`uthash_nonfatal_oom` is a no-op. + +---------------------------------------------------------------------------- +#undef uthash_nonfatal_oom +#define uthash_nonfatal_oom(elt) perhaps_recover((element_t *) elt) +---------------------------------------------------------------------------- + +Before the call to `uthash_nonfatal_oom`, the hash table is rolled back +to the state it was in prior to the problematic insertion; no memory is +leaked. It is safe to `throw` or `longjmp` out of the `uthash_nonfatal_oom` +handler. + +The `elt` argument will be of the correct pointer-to-element type, unless +`uthash_nonfatal_oom` is invoked from `HASH_SELECT`, in which case it will +be of `void*` type and must be cast before using. In any case, `elt->hh.tbl` +will be `NULL`. + +Allocation failure is possible only when adding elements to the hash table +(including the `ADD`, `REPLACE`, and `SELECT` operations). +`uthash_free` is not allowed to fail. + +Debug mode +~~~~~~~~~~ +If a program that uses this hash is compiled with `-DHASH_DEBUG=1`, a special +internal consistency-checking mode is activated. In this mode, the integrity +of the whole hash is checked following every add or delete operation. This is +for debugging the uthash software only, not for use in production code. + +In the `tests/` directory, running `make debug` will run all the tests in +this mode. + +In this mode, any internal errors in the hash data structure will cause a +message to be printed to `stderr` and the program to exit. + +The `UT_hash_handle` data structure includes `next`, `prev`, `hh_next` and +`hh_prev` fields. The former two fields determine the "application" ordering +(that is, insertion order-- the order the items were added). The latter two +fields determine the "bucket chain" order. These link the `UT_hash_handles` +together in a doubly-linked list that is a bucket chain. + +Checks performed in `-DHASH_DEBUG=1` mode: + +- the hash is walked in its entirety twice: once in 'bucket' order and a + second time in 'application' order +- the total number of items encountered in both walks is checked against the + stored number +- during the walk in 'bucket' order, each item's `hh_prev` pointer is compared + for equality with the last visited item +- during the walk in 'application' order, each item's `prev` pointer is compared + for equality with the last visited item + +.Macro debugging: +******************************************************************************** +Sometimes it's difficult to interpret a compiler warning on a line which +contains a macro call. In the case of uthash, one macro can expand to dozens of +lines. In this case, it is helpful to expand the macros and then recompile. +By doing so, the warning message will refer to the exact line within the macro. + +Here is an example of how to expand the macros and then recompile. This uses the +`test1.c` program in the `tests/` subdirectory. + + gcc -E -I../src test1.c > /tmp/a.c + egrep -v '^#' /tmp/a.c > /tmp/b.c + indent /tmp/b.c + gcc -o /tmp/b /tmp/b.c + +The last line compiles the original program (test1.c) with all macros expanded. +If there was a warning, the referenced line number can be checked in `/tmp/b.c`. +******************************************************************************** + +Thread safety +~~~~~~~~~~~~~ +You can use uthash in a threaded program. But you must do the locking. Use a +read-write lock to protect against concurrent writes. It is ok to have +concurrent readers (since uthash 1.5). + +For example using pthreads you can create an rwlock like this: + + pthread_rwlock_t lock; + if (pthread_rwlock_init(&lock,NULL) != 0) fatal("can't create rwlock"); + +Then, readers must acquire the read lock before doing any `HASH_FIND` calls or +before iterating over the hash elements: + + if (pthread_rwlock_rdlock(&lock) != 0) fatal("can't get rdlock"); + HASH_FIND_INT(elts, &i, e); + pthread_rwlock_unlock(&lock); + +Writers must acquire the exclusive write lock before doing any update. Add, +delete, and sort are all updates that must be locked. + + if (pthread_rwlock_wrlock(&lock) != 0) fatal("can't get wrlock"); + HASH_DEL(elts, e); + pthread_rwlock_unlock(&lock); + +If you prefer, you can use a mutex instead of a read-write lock, but this will +reduce reader concurrency to a single thread at a time. + +An example program using uthash with a read-write lock is included in +`tests/threads/test1.c`. + +[[Macro_reference]] +Macro reference +--------------- + +Convenience macros +~~~~~~~~~~~~~~~~~~ +The convenience macros do the same thing as the generalized macros, but +require fewer arguments. + +In order to use the convenience macros, + +1. the structure's `UT_hash_handle` field must be named `hh`, and +2. for add or find, the key field must be of type `int` or `char[]` or pointer + +.Convenience macros +[width="90%",cols="10m,30m",grid="none",options="header"] +|=============================================================================== +|macro | arguments +|HASH_ADD_INT | (head, keyfield_name, item_ptr) +|HASH_REPLACE_INT | (head, keyfiled_name, item_ptr,replaced_item_ptr) +|HASH_FIND_INT | (head, key_ptr, item_ptr) +|HASH_ADD_STR | (head, keyfield_name, item_ptr) +|HASH_REPLACE_STR | (head,keyfield_name, item_ptr, replaced_item_ptr) +|HASH_FIND_STR | (head, key_ptr, item_ptr) +|HASH_ADD_PTR | (head, keyfield_name, item_ptr) +|HASH_REPLACE_PTR | (head, keyfield_name, item_ptr, replaced_item_ptr) +|HASH_FIND_PTR | (head, key_ptr, item_ptr) +|HASH_DEL | (head, item_ptr) +|HASH_SORT | (head, cmp) +|HASH_COUNT | (head) +|=============================================================================== + +General macros +~~~~~~~~~~~~~~ + +These macros add, find, delete and sort the items in a hash. You need to +use the general macros if your `UT_hash_handle` is named something other +than `hh`, or if your key's data type isn't `int` or `char[]`. + +.General macros +[width="90%",cols="10m,30m",grid="none",options="header"] +|=============================================================================== +|macro | arguments +|HASH_ADD | (hh_name, head, keyfield_name, key_len, item_ptr) +|HASH_ADD_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, hashv, item_ptr) +|HASH_ADD_KEYPTR | (hh_name, head, key_ptr, key_len, item_ptr) +|HASH_ADD_KEYPTR_BYHASHVALUE | (hh_name, head, key_ptr, key_len, hashv, item_ptr) +|HASH_ADD_INORDER | (hh_name, head, keyfield_name, key_len, item_ptr, cmp) +|HASH_ADD_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, cmp) +|HASH_ADD_KEYPTR_INORDER | (hh_name, head, key_ptr, key_len, item_ptr, cmp) +|HASH_ADD_KEYPTR_BYHASHVALUE_INORDER | (hh_name, head, key_ptr, key_len, hashv, item_ptr, cmp) +|HASH_REPLACE | (hh_name, head, keyfield_name, key_len, item_ptr, replaced_item_ptr) +|HASH_REPLACE_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, replaced_item_ptr) +|HASH_REPLACE_INORDER | (hh_name, head, keyfield_name, key_len, item_ptr, replaced_item_ptr, cmp) +|HASH_REPLACE_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, replaced_item_ptr, cmp) +|HASH_FIND | (hh_name, head, key_ptr, key_len, item_ptr) +|HASH_FIND_BYHASHVALUE | (hh_name, head, key_ptr, key_len, hashv, item_ptr) +|HASH_DELETE | (hh_name, head, item_ptr) +|HASH_VALUE | (key_ptr, key_len, hashv) +|HASH_SRT | (hh_name, head, cmp) +|HASH_CNT | (hh_name, head) +|HASH_CLEAR | (hh_name, head) +|HASH_SELECT | (dst_hh_name, dst_head, src_hh_name, src_head, condition) +|HASH_ITER | (hh_name, head, item_ptr, tmp_item_ptr) +|HASH_OVERHEAD | (hh_name, head) +|=============================================================================== + +[NOTE] +`HASH_ADD_KEYPTR` is used when the structure contains a pointer to the +key, rather than the key itself. + +The `HASH_VALUE` and `..._BYHASHVALUE` macros are a performance mechanism mainly for the +special case of having different structures, in different hash tables, having +identical keys. It allows the hash value to be obtained once and then passed +in to the `..._BYHASHVALUE` macros, saving the expense of re-computing the hash value. + + +Argument descriptions +^^^^^^^^^^^^^^^^^^^^^ +hh_name:: + name of the `UT_hash_handle` field in the structure. Conventionally called + `hh`. +head:: + the structure pointer variable which acts as the "head" of the hash. So + named because it initially points to the first item that is added to the hash. +keyfield_name:: + the name of the key field in the structure. (In the case of a multi-field + key, this is the first field of the key). If you're new to macros, it + might seem strange to pass the name of a field as a parameter. See + <>. +key_len:: + the length of the key field in bytes. E.g. for an integer key, this is + `sizeof(int)`, while for a string key it's `strlen(key)`. (For a + multi-field key, see <>.) +key_ptr:: + for `HASH_FIND`, this is a pointer to the key to look up in the hash + (since it's a pointer, you can't directly pass a literal value here). For + `HASH_ADD_KEYPTR`, this is the address of the key of the item being added. +hashv:: + the hash value of the provided key. This is an input parameter for the + `..._BYHASHVALUE` macros, and an output parameter for `HASH_VALUE`. + Reusing a cached hash value can be a performance optimization if + you're going to do repeated lookups for the same key. +item_ptr:: + pointer to the structure being added, deleted, replaced, or looked up, or the current + pointer during iteration. This is an input parameter for the `HASH_ADD`, + `HASH_DELETE`, and `HASH_REPLACE` macros, and an output parameter for `HASH_FIND` + and `HASH_ITER`. (When using `HASH_ITER` to iterate, `tmp_item_ptr` + is another variable of the same type as `item_ptr`, used internally). +replaced_item_ptr:: + used in `HASH_REPLACE` macros. This is an output parameter that is set to point + to the replaced item (if no item is replaced it is set to NULL). +cmp:: + pointer to comparison function which accepts two arguments (pointers to + items to compare) and returns an int specifying whether the first item + should sort before, equal to, or after the second item (like `strcmp`). +condition:: + a function or macro which accepts a single argument (a void pointer to a + structure, which needs to be cast to the appropriate structure type). The + function or macro should evaluate to a non-zero value if the + structure should be "selected" for addition to the destination hash. + +// vim: set tw=80 wm=2 syntax=asciidoc: diff --git a/doc/uthash/utarray.txt b/doc/uthash/utarray.txt new file mode 100644 index 000000000..25d94e260 --- /dev/null +++ b/doc/uthash/utarray.txt @@ -0,0 +1,383 @@ +utarray: dynamic array macros for C +=================================== +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 dynamic array macros for C structures are included with +uthash in `utarray.h`. To use these macros in your own C program, just +copy `utarray.h` into your source directory and use it in your programs. + + #include "utarray.h" + +The dynamic array supports basic operations such as push, pop, and erase on the +array elements. These array elements can be any simple datatype or structure. +The array <> are based loosely on the C++ STL vector methods. + +Internally the dynamic array contains a contiguous memory region into which +the elements are copied. This buffer is grown as needed using `realloc` to +accommodate all the data that is pushed into it. + +Download +~~~~~~~~ +To download the `utarray.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 'utarray' macros have been tested on: + + * Linux, + * Mac OS X, + * Windows, using Visual Studio 2008 and Visual Studio 2010 + +Usage +----- + +Declaration +~~~~~~~~~~~ + +The array itself has the data type `UT_array`, regardless of the type of +elements to be stored in it. It is declared like, + + UT_array *nums; + +New and free +~~~~~~~~~~~~ +The next step is to create the array using `utarray_new`. Later when you're +done with the array, `utarray_free` will free it and all its elements. + +Push, pop, etc +~~~~~~~~~~~~~~ +The central features of the utarray involve putting elements into it, taking +them out, and iterating over them. There are several <> +to pick from that deal with either single elements or ranges of elements at a +time. In the examples below we will use only the push operation to insert +elements. + +Elements +-------- + +Support for dynamic arrays of integers or strings is especially easy. These are +best shown by example: + +Integers +~~~~~~~~ +This example makes a utarray of integers, pushes 0-9 into it, then prints it. +Lastly it frees it. + +.Integer elements +------------------------------------------------------------------------------- +#include +#include "utarray.h" + +int main() { + UT_array *nums; + int i, *p; + + utarray_new(nums,&ut_int_icd); + for(i=0; i < 10; i++) utarray_push_back(nums,&i); + + for(p=(int*)utarray_front(nums); + p!=NULL; + p=(int*)utarray_next(nums,p)) { + printf("%d\n",*p); + } + + utarray_free(nums); + + return 0; +} +------------------------------------------------------------------------------- + +The second argument to `utarray_push_back` is always a 'pointer' to the type +(so a literal cannot be used). So for integers, it is an `int*`. + +Strings +~~~~~~~ +In this example we make a utarray of strings, push two strings into it, print +it and free it. + +.String elements +------------------------------------------------------------------------------- +#include +#include "utarray.h" + +int main() { + UT_array *strs; + char *s, **p; + + utarray_new(strs,&ut_str_icd); + + s = "hello"; utarray_push_back(strs, &s); + s = "world"; utarray_push_back(strs, &s); + p = NULL; + while ( (p=(char**)utarray_next(strs,p))) { + printf("%s\n",*p); + } + + utarray_free(strs); + + return 0; +} +------------------------------------------------------------------------------- + +In this example, since the element is a `char*`, we pass a pointer to it +(`char**`) as the second argument to `utarray_push_back`. Note that "push" makes +a copy of the source string and pushes that copy into the array. + +About UT_icd +~~~~~~~~~~~~ + +Arrays be made of any type of element, not just integers and strings. The +elements can be basic types or structures. Unless you're dealing with integers +and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need +to define a `UT_icd` helper structure. This structure contains everything that +utarray needs to initialize, copy or destruct elements. + + typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; + } UT_icd; + +The three function pointers `init`, `copy`, and `dtor` have these prototypes: + + typedef void (ctor_f)(void *dst, const void *src); + typedef void (dtor_f)(void *elt); + typedef void (init_f)(void *elt); + +The `sz` is just the size of the element being stored in the array. + +The `init` function will be invoked whenever utarray needs to initialize an +empty element. This only happens as a byproduct of `utarray_resize` or +`utarray_extend_back`. If `init` is `NULL`, it defaults to zero filling the +new element using memset. + +The `copy` function is used whenever an element is copied into the array. +It is invoked during `utarray_push_back`, `utarray_insert`, `utarray_inserta`, +or `utarray_concat`. If `copy` is `NULL`, it defaults to a bitwise copy using +memcpy. + +The `dtor` function is used to clean up an element that is being removed from +the array. It may be invoked due to `utarray_resize`, `utarray_pop_back`, +`utarray_erase`, `utarray_clear`, `utarray_done` or `utarray_free`. If the +elements need no cleanup upon destruction, `dtor` may be `NULL`. + +Scalar types +~~~~~~~~~~~~ + +The next example uses `UT_icd` with all its defaults to make a utarray of +`long` elements. This example pushes two longs, prints them, and frees the +array. + +.long elements +------------------------------------------------------------------------------- +#include +#include "utarray.h" + +UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; + +int main() { + UT_array *nums; + long l, *p; + utarray_new(nums, &long_icd); + + l=1; utarray_push_back(nums, &l); + l=2; utarray_push_back(nums, &l); + + p=NULL; + while( (p=(long*)utarray_next(nums,p))) printf("%ld\n", *p); + + utarray_free(nums); + return 0; +} +------------------------------------------------------------------------------- + +Structures +~~~~~~~~~~ + +Structures can be used as utarray elements. If the structure requires no +special effort to initialize, copy or destruct, we can use `UT_icd` with all +its defaults. This example shows a structure that consists of two integers. Here +we push two values, print them and free the array. + +.Structure (simple) +------------------------------------------------------------------------------- +#include +#include "utarray.h" + +typedef struct { + int a; + int b; +} intpair_t; + +UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; + +int main() { + + UT_array *pairs; + intpair_t ip, *p; + utarray_new(pairs,&intpair_icd); + + ip.a=1; ip.b=2; utarray_push_back(pairs, &ip); + ip.a=10; ip.b=20; utarray_push_back(pairs, &ip); + + for(p=(intpair_t*)utarray_front(pairs); + p!=NULL; + p=(intpair_t*)utarray_next(pairs,p)) { + printf("%d %d\n", p->a, p->b); + } + + utarray_free(pairs); + return 0; +} +------------------------------------------------------------------------------- + +The real utility of `UT_icd` is apparent when the elements of the utarray are +structures that require special work to initialize, copy or destruct. + +For example, when a structure contains pointers to related memory areas that +need to be copied when the structure is copied (and freed when the structure is +freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`. + +Here we take an example of a structure that contains an integer and a string. +When this element is copied (such as when an element is pushed into the array), +we want to "deep copy" the `s` pointer (so the original element and the new +element point to their own copies of `s`). When an element is destructed, we +want to "deep free" its copy of `s`. Lastly, this example is written to work +even if `s` has the value `NULL`. + +.Structure (complex) +------------------------------------------------------------------------------- +#include +#include +#include "utarray.h" + +typedef struct { + int a; + char *s; +} intchar_t; + +void intchar_copy(void *_dst, const void *_src) { + intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src; + dst->a = src->a; + dst->s = src->s ? strdup(src->s) : NULL; +} + +void intchar_dtor(void *_elt) { + intchar_t *elt = (intchar_t*)_elt; + if (elt->s) free(elt->s); +} + +UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; + +int main() { + UT_array *intchars; + intchar_t ic, *p; + utarray_new(intchars, &intchar_icd); + + ic.a=1; ic.s="hello"; utarray_push_back(intchars, &ic); + ic.a=2; ic.s="world"; utarray_push_back(intchars, &ic); + + p=NULL; + while( (p=(intchar_t*)utarray_next(intchars,p))) { + printf("%d %s\n", p->a, (p->s ? p->s : "null")); + } + + utarray_free(intchars); + return 0; +} + +------------------------------------------------------------------------------- + +[[operations]] +Reference +--------- +This table lists all the utarray operations. These are loosely based on the C++ +vector class. + +Operations +~~~~~~~~~~ + +[width="100%",cols="50 _b); + } + +4. `utarray_find` uses a binary search to locate an element having a certain value + according to the given comparison function. The utarray must be first sorted + using the same comparison function. An example of using `utarray_find` with + a utarray of strings is included in `tests/test61.c`. + +5. A 'pointer' to a particular element (obtained using `utarray_eltptr` or + `utarray_front`, `utarray_next`, `utarray_prev`, `utarray_back`) becomes invalid whenever + another element is inserted into the utarray. This is because the internal + memory management may need to `realloc` the element storage to a new address. + For this reason, it's usually better to refer to an element by its integer + 'index' in code whose duration may include element insertion. + +6. To override the default out-of-memory handling behavior (which calls `exit(-1)`), + override the `utarray_oom()` macro before including `utarray.h`. + For example, + + #define utarray_oom() do { longjmp(error_handling_location); } while (0) + ... + #include "utarray.h" + +// vim: set nowrap syntax=asciidoc: diff --git a/doc/uthash/uthash-mini.png b/doc/uthash/uthash-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..9536b2a78675cb19ecd841db86808423ff805f75 GIT binary patch literal 3611 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 literal 0 HcmV?d00001 diff --git a/doc/uthash/uthash-mini.svg b/doc/uthash/uthash-mini.svg new file mode 100644 index 000000000..ea2d0749d --- /dev/null +++ b/doc/uthash/uthash-mini.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ut hash + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/uthash/uthash.png b/doc/uthash/uthash.png new file mode 100644 index 0000000000000000000000000000000000000000..20df5a7d3566fa1210102c6512956916d30d43a5 GIT binary patch literal 21518 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�L6@iTtUNOob*ju%^I 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 FV1mJ@2TK3| literal 0 HcmV?d00001 diff --git a/doc/uthash/utlist.txt b/doc/uthash/utlist.txt new file mode 100644 index 000000000..06b6b00dc --- /dev/null +++ b/doc/uthash/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 +v2.1.0, December 2018 + +Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. + +Introduction +------------ +The functions in `utringbuffer.h` are based on the general-purpose array macros +provided in `utarray.h`, so before reading this page you should read +link:utarray.html[that page] first. + +To use these macros in your own C program, copy both `utarray.h` and `utringbuffer.h` +into your source directory and use `utringbuffer.h` in your program. + + #include "utringbuffer.h" + +The provided <> are based loosely on the C++ STL vector methods. +The ring-buffer data type supports construction (with a specified capacity), +destruction, iteration, and push, but not pop; once the ring-buffer reaches full +capacity, pushing a new element automatically pops and destroys the oldest element. +The elements contained in the ring-buffer can be any simple datatype or structure. + +Internally the ring-buffer contains a pre-allocated memory region into which the +elements are copied, starting at position 0. When the ring-buffer reaches full +capacity, the next element to be pushed is pushed at position 0, overwriting the +oldest element, and the internal index representing the "start" of the ring-buffer +is incremented. A ring-buffer, once full, can never become un-full. + + +Download +~~~~~~~~ +To download the `utringbuffer.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 'utringbuffer' macros have been tested on: + + * Linux, + * Mac OS X, + * Windows, using Visual Studio 2008 and Visual Studio 2010 + +Usage +----- + +Declaration +~~~~~~~~~~~ + +The ring-buffer itself has the data type `UT_ringbuffer`, regardless of the type of +elements to be stored in it. It is declared like, + + UT_ringbuffer *history; + +New and free +~~~~~~~~~~~~ +The next step is to create the ring-buffer using `utringbuffer_new`. Later when you're +done with the ring-buffer, `utringbuffer_free` will free it and all its elements. + +Push, etc +~~~~~~~~~ +The central features of the ring-buffer involve putting elements into it +and iterating over them. There are several <> +that deal with either single elements or ranges of elements at a +time. In the examples below we will use only the push operation to insert +elements. + +Elements +-------- + +Support for dynamic arrays of integers or strings is especially easy. These are +best shown by example: + +Integers +~~~~~~~~ +This example makes a ring-buffer of integers, pushes 0-9 into it, then prints it +two different ways. Lastly it frees it. + +.Integer elements +------------------------------------------------------------------------------- +#include +#include "utringbuffer.h" + +int main() { + UT_ringbuffer *history; + int i, *p; + + utringbuffer_new(history, 7, &ut_int_icd); + for(i=0; i < 10; i++) utringbuffer_push_back(history, &i); + + for (p = (int*)utringbuffer_front(history); + p != NULL; + p = (int*)utringbuffer_next(history, p)) { + printf("%d\n", *p); /* prints "3 4 5 6 7 8 9" */ + } + + for (i=0; i < utringbuffer_len(history); i++) { + p = utringbuffer_eltptr(history, i); + printf("%d\n", *p); /* prints "3 4 5 6 7 8 9" */ + } + + utringbuffer_free(history); + + return 0; +} +------------------------------------------------------------------------------- + +The second argument to `utringbuffer_push_back` is always a 'pointer' to the type +(so a literal cannot be used). So for integers, it is an `int*`. + +Strings +~~~~~~~ +In this example we make a ring-buffer of strings, push two strings into it, print +it and free it. + +.String elements +------------------------------------------------------------------------------- +#include +#include "utringbuffer.h" + +int main() { + UT_ringbuffer *strs; + char *s, **p; + + utringbuffer_new(strs, 7, &ut_str_icd); + + s = "hello"; utringbuffer_push_back(strs, &s); + s = "world"; utringbuffer_push_back(strs, &s); + p = NULL; + while ( (p=(char**)utringbuffer_next(strs,p))) { + printf("%s\n",*p); + } + + utringbuffer_free(strs); + + return 0; +} +------------------------------------------------------------------------------- + +In this example, since the element is a `char*`, we pass a pointer to it +(`char**`) as the second argument to `utringbuffer_push_back`. Note that "push" makes +a copy of the source string and pushes that copy into the array. + +About UT_icd +~~~~~~~~~~~~ + +Arrays can be made of any type of element, not just integers and strings. The +elements can be basic types or structures. Unless you're dealing with integers +and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need +to define a `UT_icd` helper structure. This structure contains everything that +utringbuffer (or utarray) needs to initialize, copy or destruct elements. + + typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; + } UT_icd; + +The three function pointers `init`, `copy`, and `dtor` have these prototypes: + + typedef void (ctor_f)(void *dst, const void *src); + typedef void (dtor_f)(void *elt); + typedef void (init_f)(void *elt); + +The `sz` is just the size of the element being stored in the array. + +The `init` function is used by utarray but is never used by utringbuffer; +you may safely set it to any value you want. + +The `copy` function is used whenever an element is copied into the buffer. +It is invoked during `utringbuffer_push_back`. +If `copy` is `NULL`, it defaults to a bitwise copy using memcpy. + +The `dtor` function is used to clean up an element that is being removed from +the buffer. It may be invoked due to `utringbuffer_push_back` (on the oldest +element in the buffer), `utringbuffer_clear`, `utringbuffer_done`, or +`utringbuffer_free`. +If the elements need no cleanup upon destruction, `dtor` may be `NULL`. + +Scalar types +~~~~~~~~~~~~ + +The next example uses `UT_icd` with all its defaults to make a ring-buffer of +`long` elements. This example pushes two longs into a buffer of capacity 1, +prints the contents of the buffer (which is to say, the most recent value +pushed), and then frees the buffer. + +.long elements +------------------------------------------------------------------------------- +#include +#include "utringbuffer.h" + +UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; + +int main() { + UT_ringbuffer *nums; + long l, *p; + utringbuffer_new(nums, 1, &long_icd); + + l=1; utringbuffer_push_back(nums, &l); + l=2; utringbuffer_push_back(nums, &l); + + p=NULL; + while((p = (long*)utringbuffer_next(nums,p))) printf("%ld\n", *p); + + utringbuffer_free(nums); + return 0; +} +------------------------------------------------------------------------------- + +Structures +~~~~~~~~~~ + +Structures can be used as utringbuffer elements. If the structure requires no +special effort to initialize, copy or destruct, we can use `UT_icd` with all +its defaults. This example shows a structure that consists of two integers. Here +we push two values, print them and free the buffer. + +.Structure (simple) +------------------------------------------------------------------------------- +#include +#include "utringbuffer.h" + +typedef struct { + int a; + int b; +} intpair_t; + +UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; + +int main() { + + UT_ringbuffer *pairs; + intpair_t ip, *p; + utringbuffer_new(pairs, 7, &intpair_icd); + + ip.a=1; ip.b=2; utringbuffer_push_back(pairs, &ip); + ip.a=10; ip.b=20; utringbuffer_push_back(pairs, &ip); + + for(p=(intpair_t*)utringbuffer_front(pairs); + p!=NULL; + p=(intpair_t*)utringbuffer_next(pairs,p)) { + printf("%d %d\n", p->a, p->b); + } + + utringbuffer_free(pairs); + return 0; +} +------------------------------------------------------------------------------- + +The real utility of `UT_icd` is apparent when the elements stored in the +ring-buffer are structures that require special work to initialize, copy or +destruct. + +For example, when a structure contains pointers to related memory areas that +need to be copied when the structure is copied (and freed when the structure is +freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`. + +Here we take an example of a structure that contains an integer and a string. +When this element is copied (such as when an element is pushed), +we want to "deep copy" the `s` pointer (so the original element and the new +element point to their own copies of `s`). When an element is destructed, we +want to "deep free" its copy of `s`. Lastly, this example is written to work +even if `s` has the value `NULL`. + +.Structure (complex) +------------------------------------------------------------------------------- +#include +#include +#include "utringbuffer.h" + +typedef struct { + int a; + char *s; +} intchar_t; + +void intchar_copy(void *_dst, const void *_src) { + intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src; + dst->a = src->a; + dst->s = src->s ? strdup(src->s) : NULL; +} + +void intchar_dtor(void *_elt) { + intchar_t *elt = (intchar_t*)_elt; + free(elt->s); +} + +UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; + +int main() { + UT_ringbuffer *intchars; + intchar_t ic, *p; + utringbuffer_new(intchars, 2, &intchar_icd); + + ic.a=1; ic.s="hello"; utringbuffer_push_back(intchars, &ic); + ic.a=2; ic.s="world"; utringbuffer_push_back(intchars, &ic); + ic.a=3; ic.s="peace"; utringbuffer_push_back(intchars, &ic); + + p=NULL; + while( (p=(intchar_t*)utringbuffer_next(intchars,p))) { + printf("%d %s\n", p->a, (p->s ? p->s : "null")); + /* prints "2 world 3 peace" */ + } + + utringbuffer_free(intchars); + return 0; +} + +------------------------------------------------------------------------------- + +[[operations]] +Reference +--------- +This table lists all the utringbuffer operations. These are loosely based on the C++ +vector class. + +Operations +~~~~~~~~~~ + +[width="100%",cols="50 +v2.1.0, December 2018 + +Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. + +Introduction +------------ +A set of very simple stack macros for C structures are included with +uthash in `utstack.h`. To use these macros in your own C program, just +copy `utstack.h` into your source directory and use it in your programs. + + #include "utstack.h" + +These macros support the basic operations of a stack, implemented as +an intrusive linked list. A stack supports the "push", "pop", and "count" +operations, as well as the trivial operation of getting the top element +of the stack. + +Download +~~~~~~~~ +To download the `utstack.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 'utstack' macros have been tested on: + + * Linux, + * Mac OS X, + * Windows, using Visual Studio 2008 and Visual Studio 2010 + +Usage +----- + +Stack (list) head +~~~~~~~~~~~~~~~~~ +The stack head is simply a pointer to your element structure. You can name it +anything. *It must be initialized to `NULL`*. It doubles as a pointer to the +top element of your stack. + + element *stack = NULL; + +Stack operations +~~~~~~~~~~~~~~~ +The only operations on a stack are O(1) pushing, O(1) popping, and +O(n) counting the number of elements on the stack. None of the provided +macros permit directly accessing stack elements other than the top element. + +To increase the readability of your code, you can use the macro +`STACK_EMPTY(head)` as a more readable alternative to `head == NULL`, +and `STACK_TOP(head)` as a more readable alternative to `head`. + +[width="100%",cols="50 +#include +#include +#include "utstack.h" + +#define BUFLEN 20 + +typedef struct el { + char bname[BUFLEN]; + struct el *next; +} el; + +el *head = NULL; /* important- initialize to NULL! */ + +int main(int argc, char *argv[]) { + el *elt, *tmp; + + char linebuf[sizeof el->bname]; + int count; + FILE *file = fopen("test11.dat", "r"); + if (file == NULL) { + perror("can't open: "); + exit(-1); + } + + while (fgets(linebuf, sizeof linebuf, file) != NULL) { + el *name = malloc(sizeof *name); + if (name == NULL) exit(-1); + strcpy(name->bname, linebuf); + STACK_PUSH(head, name); + } + fclose(file); + + STACK_COUNT(head, elt, count); + printf("%d elements were read into the stack\n", count); + + /* now pop, print, and delete each element */ + while (!STACK_EMPTY(head)) { + printf("%s\n", STACK_TOP(head)->bname); + STACK_POP(head, elt); + free(elt); + } + + return 0; +} +-------------------------------------------------------------------------------- + +[[flex_names]] +Other names for next +~~~~~~~~~~~~~~~~~~~~ +If the element structure's `next` field is named something else, a separate group +of macros must be used. These work the same as the regular macros, but take the +field name as an extra parameter. + +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 `next` field as a trailing argument. + +[width="100%",cols="50 +v2.1.0, December 2018 + +Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. + +Introduction +------------ +A set of basic dynamic string macros for C programs are included with +uthash in `utstring.h`. To use these in your own C program, just copy +`utstring.h` into your source directory and use it in your programs. + + #include "utstring.h" + +The dynamic string supports operations such as inserting data, concatenation, +getting the length and content, substring search, and clear. It's ok to put +binary data into a utstring too. The string <> are +listed below. + +Some utstring operations are implemented as functions rather than macros. + +Download +~~~~~~~~ +To download the `utstring.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 'utstring' macros have been tested on: + + * Linux, + * Windows, using Visual Studio 2008 and Visual Studio 2010 + +Usage +----- + +Declaration +~~~~~~~~~~~ + +The dynamic string itself has the data type `UT_string`. It is declared like, + + UT_string *str; + +New and free +~~~~~~~~~~~~ +The next step is to create the string using `utstring_new`. Later when you're +done with it, `utstring_free` will free it and all its content. + +Manipulation +~~~~~~~~~~~~ +The `utstring_printf` or `utstring_bincpy` operations insert (copy) data into +the string. To concatenate one utstring to another, use `utstring_concat`. To +clear the content of the string, use `utstring_clear`. The length of the string +is available from `utstring_len`, and its content from `utstring_body`. This +evaluates to a `char*`. The buffer it points to is always null-terminated. +So, it can be used directly with external functions that expect a string. +This automatic null terminator is not counted in the length of the string. + +Samples +~~~~~~~ + +These examples show how to use utstring. + +.Sample 1 +------------------------------------------------------------------------------- +#include +#include "utstring.h" + +int main() { + UT_string *s; + + utstring_new(s); + utstring_printf(s, "hello world!" ); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + return 0; +} +------------------------------------------------------------------------------- + +The next example demonstrates that `utstring_printf` 'appends' to the string. +It also shows concatenation. + +.Sample 2 +------------------------------------------------------------------------------- +#include +#include "utstring.h" + +int main() { + UT_string *s, *t; + + utstring_new(s); + utstring_new(t); + + utstring_printf(s, "hello " ); + utstring_printf(s, "world " ); + + utstring_printf(t, "hi " ); + utstring_printf(t, "there " ); + + utstring_concat(s, t); + printf("length: %u\n", utstring_len(s)); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + utstring_free(t); + return 0; +} +------------------------------------------------------------------------------- + +The next example shows how binary data can be inserted into the string. It also +clears the string and prints new data into it. + +.Sample 3 +------------------------------------------------------------------------------- +#include +#include "utstring.h" + +int main() { + UT_string *s; + char binary[] = "\xff\xff"; + + utstring_new(s); + utstring_bincpy(s, binary, sizeof(binary)); + printf("length is %u\n", utstring_len(s)); + + utstring_clear(s); + utstring_printf(s,"number %d", 10); + printf("%s\n", utstring_body(s)); + + utstring_free(s); + return 0; +} +------------------------------------------------------------------------------- + +[[operations]] +Reference +--------- +These are the utstring operations. + +Operations +~~~~~~~~~~ + +[width="100%",cols="50