aboutsummaryrefslogtreecommitdiff
path: root/apps/systemlib/uthash
diff options
context:
space:
mode:
authorLorenz Meier <lm@inf.ethz.ch>2013-04-28 09:54:11 +0200
committerLorenz Meier <lm@inf.ethz.ch>2013-04-28 09:54:11 +0200
commit13fc6703862862f4263d8d5d085b7a16b87190e1 (patch)
tree47f3a17cb6f38b1aafe22e1cdef085cd73cd3a1d /apps/systemlib/uthash
parentf57439b90e23de260259dec051d3e2ead2d61c8c (diff)
downloadpx4-firmware-13fc6703862862f4263d8d5d085b7a16b87190e1.tar.gz
px4-firmware-13fc6703862862f4263d8d5d085b7a16b87190e1.tar.bz2
px4-firmware-13fc6703862862f4263d8d5d085b7a16b87190e1.zip
Moved last libs, drivers and headers, cleaned up IO build
Diffstat (limited to 'apps/systemlib/uthash')
-rw-r--r--apps/systemlib/uthash/doc/userguide.txt1682
-rw-r--r--apps/systemlib/uthash/doc/utarray.txt376
-rw-r--r--apps/systemlib/uthash/doc/utlist.txt219
-rw-r--r--apps/systemlib/uthash/doc/utstring.txt178
-rw-r--r--apps/systemlib/uthash/utarray.h233
-rw-r--r--apps/systemlib/uthash/uthash.h915
-rw-r--r--apps/systemlib/uthash/utlist.h522
-rw-r--r--apps/systemlib/uthash/utstring.h148
8 files changed, 0 insertions, 4273 deletions
diff --git a/apps/systemlib/uthash/doc/userguide.txt b/apps/systemlib/uthash/doc/userguide.txt
deleted file mode 100644
index 3e65a52fc..000000000
--- a/apps/systemlib/uthash/doc/userguide.txt
+++ /dev/null
@@ -1,1682 +0,0 @@
-uthash User Guide
-=================
-Troy D. Hanson <thanson@users.sourceforge.net>
-v1.9.6, April 2012
-
-include::sflogo.txt[]
-include::topnav.txt[]
-
-A hash in C
------------
-include::toc.txt[]
-
-This document is written for C programmers. Since you're reading this, chances
-are that you know a hash is used for looking up items using a key. In scripting
-languages like Perl, hashes are used all the time. In C, hashes don't exist in
-the language itself. This software provides a hash table for C structures.
-
-What can it do?
-~~~~~~~~~~~~~~~~~
-This software supports these operations on items in a hash table:
-
-1. add
-2. find
-3. delete
-4. count
-5. iterate
-6. sort
-7. select
-
-Is it fast?
-~~~~~~~~~~~
-Add, find and delete are normally constant-time operations. This is influenced
-by your key domain and the hash function.
-
-This hash aims to be minimalistic and efficient. It's around 900 lines of C.
-It inlines automatically because it's implemented as macros. It's fast as long
-as the hash function is suited to your keys. You can use the default hash
-function, or easily compare performance and choose from among several other
-<<hash_functions,built-in hash functions>>.
-
-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
- * Mac OS X
- * Windows using Visual Studio 2008 and 2010
- * Solaris
- * OpenBSD
- * FreeBSD
-
-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.
-
-Obtaining uthash
-~~~~~~~~~~~~~~~~
-Please follow the link to download on the
-http://uthash.sourceforge.net[uthash website] at http://uthash.sourceforge.net.
-
-A number of platforms include uthash in their package repositories. For example,
-Debian/Ubuntu users may simply `aptitude install uthash-dev`.
-
-Getting help
-~~~~~~~~~~~~
-Feel free to mailto:tdh@tkhanson.net[email the author] at
-tdh@tkhanson.net.
-
-Resources
-~~~~~~~~~
-Users of uthash may wish to follow the news feed for information about new
-releases. Also, there are some extra bonus headers included with uthash.
-
-News::
- The author has a news feed for http://troydhanson.wordpress.com/[software updates] image:img/rss.png[(RSS)].
-Extras included with uthash::
- uthash ships with these "extras"-- independent headers similar to uthash.
- First link:utlist.html[utlist.h] provides linked list macros for C structures.
- Second, link:utarray.html[utarray.h] implements dynamic arrays using macros.
- Third, link:utstring.html[utstring.h] implements a basic dynamic string.
-Other software::
- Other open-source software by the author is listed at http://tkhanson.net.
-
-Who's using it?
-~~~~~~~~~~~~~~~
-Since releasing uthash in 2006, it has been downloaded thousands of times,
-incorporated into commercial software, academic research, and into other
-open-source software.
-
-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
-~~~~~~~~~~~~~~~~~~~
-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 <<Macro_reference,Macro Reference>>.
-
-.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.
-
-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).
-
-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.
-
-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`.
-
-Sorted iteration
-^^^^^^^^^^^^^^^^
-The items in the hash are, by default, traversed in the order they were added
-("insertion order") when you follow the `hh.next` pointer. But you can sort
-the items into a new order using `HASH_SORT`. E.g.,
-
- HASH_SORT( users, name_sort );
-
-The second argument is a pointer to a comparison function. It must accept two
-arguments which are pointers to two items to compare. Its return value should
-be less than zero, zero, or greater than zero, if the first item sorts before,
-equal to, or after the second item, respectively. (Just like `strcmp`).
-
-.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 <stdio.h> /* gets */
-#include <stdlib.h> /* atoi, malloc */
-#include <string.h> /* 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;
-
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- s->id = user_id;
- strcpy(s->name, name);
- HASH_ADD_INT( users, id, s ); /* id: name of key field */
-}
-
-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. find user\n");
- printf("3. delete user\n");
- printf("4. delete all users\n");
- printf("5. sort items by name\n");
- printf("6. sort items by id\n");
- printf("7. print users\n");
- printf("8. count users\n");
- printf("9. quit\n");
- gets(in);
- switch(atoi(in)) {
- case 1:
- printf("name?\n");
- add_user(id++, gets(in));
- break;
- case 2:
- printf("id?\n");
- s = find_user(atoi(gets(in)));
- printf("user: %s\n", s ? s->name : "unknown");
- break;
- case 3:
- printf("id?\n");
- s = find_user(atoi(gets(in)));
- if (s) delete_user(s);
- else printf("id unknown\n");
- break;
- case 4:
- delete_all();
- break;
- case 5:
- sort_by_name();
- break;
- case 6:
- sort_by_id();
- break;
- case 7:
- print_users();
- break;
- case 8:
- num_users=HASH_COUNT(users);
- printf("there are %u users\n", num_users);
- break;
- case 9:
- 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 <<Macro_reference,Macro reference>>.
-================================================================================
-
-String 'within' structure
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.A string-keyed hash (string within structure)
-----------------------------------------------------------------------
-#include <string.h> /* strcpy */
-#include <stdlib.h> /* malloc */
-#include <stdio.h> /* 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 **n, *names[] = { "joe", "bob", "betty", NULL };
- struct my_struct *s, *tmp, *users = NULL;
- int i=0;
-
- for (n = names; *n != NULL; n++) {
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->name, *n,10);
- 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 <string.h> /* strcpy */
-#include <stdlib.h> /* malloc */
-#include <stdio.h> /* 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 **n, *names[] = { "joe", "bob", "betty", NULL };
- struct my_struct *s, *tmp, *users = NULL;
- int i=0;
-
- for (n = names; *n != NULL; n++) {
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- s->name = *n;
- 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 <stdio.h>
-#include <stdlib.h>
-#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(el_t));
- 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 <stdlib.h>
-#include <stdio.h>
-#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(record_t) );
- memset(r, 0, sizeof(record_t));
- 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 <<Macro_reference,Macro Reference>>.
-
-Advanced Topics
----------------
-
-Compound keys
-~~~~~~~~~~~~~
-Your key can even comprise multiple contiguous fields.
-
-.A multi-field key
-----------------------------------------------------------------------
-#include <stdlib.h> /* malloc */
-#include <stddef.h> /* offsetof */
-#include <stdio.h> /* printf */
-#include <string.h> /* 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).
-
-.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
-`<stddef.h>`. 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.
-
-[[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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#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 an alternative 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 alternative 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 alternative keys
-----------------------------------------------------------------------
-struct my_struct {
- int id; /* usual key */
- char username[10]; /* alternative 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);
-
- /* lookup 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);
-
- /* lookup 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);
-----------------------------------------------------------------------
-
-
-Several sort orders
-~~~~~~~~~~~~~~~~~~~
-It comes as no suprise 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 <<multihash,here>>, 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_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 Jenkin's.
-
-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
-|MUR | MurmurHash v3 (see note)
-|===============================================================================
-
-[NOTE]
-.MurmurHash
-================================================================================
-A special symbol must be defined if you intend to use MurmurHash. To use it, add
-`-DHASH_USING_NO_STRICT_ALIASING` to your `CFLAGS`. And, if you are using
-the gcc compiler with optimization, add `-fno-strict-aliasing` to your `CFLAGS`.
-================================================================================
-
-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 <<expansion,Expansion internals>>. 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 <<ideal>> 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.
-
-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 change how uthash allocates
-memory, and to run code in response to certain internal events.
-
-malloc/free
-^^^^^^^^^^^
-By default this hash implementation uses `malloc` and `free` to manage memory.
-If your application uses its own custom allocator, this hash can use them too.
-
-.Specifying alternate memory management functions
-----------------------------------------------------------------------------
-#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.
-
-Out of memory
-^^^^^^^^^^^^^
-If memory allocation fails (i.e., the malloc function returned `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. Uthash does not support "returning a failure" if memory cannot be
-allocated.
-
-Internal events
-^^^^^^^^^^^^^^^
-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.
-
-These two hooks are "notification" hooks which get executed if uthash is
-expanding buckets, or setting the 'bucket expansion inhibited' flag. Normally
-both of these hooks are undefined and thus compile away to nothing.
-
-Expansion
-+++++++++
-There is a hook for the bucket expansion event.
-
-.Bucket expansion hook
-----------------------------------------------------------------------------
-#include "uthash.h"
-
-#undef uthash_expand_fyi
-#define uthash_expand_fyi(tbl) printf("expanded to %d buckets\n", tbl->num_buckets)
-
-...
-----------------------------------------------------------------------------
-
-Expansion-inhibition
-++++++++++++++++++++
-This hook can be defined to code to execute in the event that uthash decides to
-set the 'bucket expansion inhibited' flag.
-
-.Bucket expansion inhibited hook
-----------------------------------------------------------------------------
-#include "uthash.h"
-
-#undef uthash_noexpand_fyi
-#define uthash_noexpand_fyi printf("warning: bucket expansion inhibited\n");
-
-...
-----------------------------------------------------------------------------
-
-
-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_FIND_INT | (head, key_ptr, item_ptr)
-|HASH_ADD_STR | (head, keyfield_name, item_ptr)
-|HASH_FIND_STR | (head, key_ptr, item_ptr)
-|HASH_ADD_PTR | (head, keyfield_name, 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_KEYPTR| (hh_name, head, key_ptr, key_len, item_ptr)
-|HASH_FIND | (hh_name, head, key_ptr, key_len, item_ptr)
-|HASH_DELETE | (hh_name, head, item_ptr)
-|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)
-|===============================================================================
-
-[NOTE]
-`HASH_ADD_KEYPTR` is used when the structure contains a pointer to the
-key, rather than the key itself.
-
-
-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
- <<validc,note>>.
-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 the notes in this guide on calculating key length).
-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.
-item_ptr::
- pointer to the structure being added, deleted, or looked up, or the current
- pointer during iteration. This is an input parameter for `HASH_ADD` and
- `HASH_DELETE` 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).
-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 return (or 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/apps/systemlib/uthash/doc/utarray.txt b/apps/systemlib/uthash/doc/utarray.txt
deleted file mode 100644
index 37830f124..000000000
--- a/apps/systemlib/uthash/doc/utarray.txt
+++ /dev/null
@@ -1,376 +0,0 @@
-utarray: dynamic array macros for C
-===================================
-Troy D. Hanson <thanson@users.sourceforge.net>
-v1.9.5, November 2011
-
-include::sflogo.txt[]
-include::topnav_utarray.txt[]
-
-Introduction
-------------
-include::toc.txt[]
-
-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 <<operations,operations>> 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
-accomodate all the data that is pushed into it.
-
-Download
-~~~~~~~~
-To download the `utarray.h` header file, follow the link on the
-http://uthash.sourceforge.net[uthash home page].
-
-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 <<operations,operations>>
-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 <stdio.h>
-#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 <stdio.h>
-#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 <stdio.h>
-#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 <stdio.h>
-#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 <stdio.h>
-#include <stdlib.h>
-#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<m,40<",grid="none",options="none"]
-|===============================================================================
-| utarray_new(UT_array *a, UT_icd *icd)| allocate a new array
-| utarray_free(UT_array *a) | free an allocated array
-| utarray_init(UT_array *a,UT_icd *icd)| init an array (non-alloc)
-| utarray_done(UT_array *a) | dispose of an array (non-allocd)
-| utarray_reserve(UT_array *a,int n) | ensure space available for 'n' more elements
-| utarray_push_back(UT_array *a,void *p) | push element p onto a
-| utarray_pop_back(UT_array *a) | pop last element from a
-| utarray_extend_back(UT_array *a) | push empty element onto a
-| utarray_len(UT_array *a) | get length of a
-| utarray_eltptr(UT_array *a,int j) | get pointer of element from index
-| utarray_eltidx(UT_array *a,void *e) | get index of element from pointer
-| utarray_insert(UT_array *a,void *p, int j) | insert element p to index j
-| utarray_inserta(UT_array *a,UT_array *w, int j) | insert array w into array a at index j
-| utarray_resize(UT_array *dst,int num) | extend or shrink array to num elements
-| utarray_concat(UT_array *dst,UT_array *src) | copy src to end of dst array
-| utarray_erase(UT_array *a,int pos,int len) | remove len elements from a[pos]..a[pos+len-1]
-| utarray_clear(UT_array *a) | clear all elements from a, setting its length to zero
-| utarray_sort(UT_array *a,cmpfcn *cmp) | sort elements of a using comparison function
-| utarray_find(UT_array *a,void *v, cmpfcn *cmp) | find element v in utarray (must be sorted)
-| utarray_front(UT_array *a) | get first element of a
-| utarray_next(UT_array *a,void *e) | get element of a following e (front if e is NULL)
-| utarray_prev(UT_array *a,void *e) | get element of a before e (back if e is NULL)
-| utarray_back(UT_array *a) | get last element of a
-|===============================================================================
-
-Notes
-~~~~~
-
-1. `utarray_new` and `utarray_free` are used to allocate a new array and free it,
- while `utarray_init` and `utarray_done` can be used if the UT_array is already
- allocated and just needs to be initialized or have its internal resources
- freed.
-2. `utarray_reserve` takes the "delta" of elements to reserve (not the total
- desired capacity of the array-- this differs from the C++ STL "reserve" notion)
-3. `utarray_sort` expects a comparison function having the usual `strcmp` -like
- convention where it accepts two elements (a and b) and returns a negative
- value if a precedes b, 0 if a and b sort equally, and positive if b precedes a.
- This is an example of a comparison function:
-
- int intsort(const void *a,const void*b) {
- int _a = *(int*)a;
- int _b = *(int*)b;
- return _a - _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.
-
-// vim: set nowrap syntax=asciidoc:
-
diff --git a/apps/systemlib/uthash/doc/utlist.txt b/apps/systemlib/uthash/doc/utlist.txt
deleted file mode 100644
index fbf961c27..000000000
--- a/apps/systemlib/uthash/doc/utlist.txt
+++ /dev/null
@@ -1,219 +0,0 @@
-utlist: linked list macros for C structures
-===========================================
-Troy D. Hanson <thanson@users.sourceforge.net>
-v1.9.5, November 2011
-
-include::sflogo.txt[]
-include::topnav_utlist.txt[]
-
-Introduction
-------------
-include::toc.txt[]
-
-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 link on the
-http://uthash.sourceforge.net[uthash home page].
-
-BSD licensed
-~~~~~~~~~~~~
-This software is made available under the
-link:license.html[revised BSD license].
-It is free and open source.
-
-Platforms
-~~~~~~~~~
-The 'utlist' macros have been tested on:
-
- * Linux,
- * Mac OS X, and
- * Windows, using Visual Studio 2008, Visual Studio 2010, or Cygwin/MinGW.
-
-Using utlist
-------------
-
-Types of lists
-~~~~~~~~~~~~~~
-Three types of linked lists are supported:
-
-- *singly-linked* lists,
-- *doubly-linked* lists, and
-- *circular, doubly-linked* lists
-
-Efficiency
-^^^^^^^^^^
-For all types of lists, prepending elements and deleting elements are
-constant-time operations. Appending to a singly-linked list is an 'O(n)'
-operation but appending to a doubly-linked list is constant time using these
-macros. (This is because, in the utlist implementation of the doubly-linked
-list, the head element's `prev` member points back to the list tail, even when
-the list is non-circular). Sorting is an 'O(n log(n))' operation. Iteration
-and searching are `O(n)` for all list types.
-
-List elements
-~~~~~~~~~~~~~
-You can use any structure with these macros, as long as the structure
-contains a `next` pointer. If you want to make a doubly-linked list,
-the element also needs to have a `prev` pointer.
-
- typedef struct element {
- char *name;
- struct element *prev; /* needed for a doubly-linked list only */
- struct element *next; /* needed for singly- or doubly-linked lists */
- } element;
-
-You can name your structure anything. In the example above it is called `element`.
-Within a particular list, all elements must be of the same type.
-
-List head
-~~~~~~~~~
-The list head is simply a pointer to your element structure. You can name it
-anything. *It must be initialized to `NULL`*.
-
- element *head = NULL;
-
-List operations
-~~~~~~~~~~~~~~~
-The lists support inserting or deleting elements, sorting the elements and
-iterating over them.
-
-[width="100%",cols="10<m,10<m,10<m",grid="cols",options="header"]
-|===============================================================================
-|Singly-linked | Doubly-linked | Circular, doubly-linked
-|LL_PREPEND(head,add); | DL_PREPEND(head,add); | CDL_PREPEND(head,add;
-|LL_APPEND(head,add); | DL_APPEND(head,add); |
-|LL_CONCAT(head1,head2); | DL_CONCAT(head1,head2); |
-|LL_DELETE(head,del); | DL_DELETE(head,del); | CDL_DELETE(head,del);
-|LL_SORT(head,cmp); | DL_SORT(head,cmp); | CDL_SORT(head,cmp);
-|LL_FOREACH(head,elt) {...}| DL_FOREACH(head,elt) {...} | CDL_FOREACH(head,elt) {...}
-|LL_FOREACH_SAFE(head,elt,tmp) {...}| DL_FOREACH_SAFE(head,elt,tmp) {...} | CDL_FOREACH_SAFE(head,elt,tmp1,tmp2) {...}
-|LL_SEARCH_SCALAR(head,elt,mbr,val);| DL_SEARCH_SCALAR(head,elt,mbr,val); | CDL_SEARCH_SCALAR(head,elt,mbr,val);
-|LL_SEARCH(head,elt,like,cmp);| DL_SEARCH(head,elt,like,cmp); | CDL_SEARCH(head,elt,like,cmp);
-|===============================================================================
-
-'Prepend' means to insert an element in front of the existing list head (if any),
-changing the list head to the new element. 'Append' means to add an element at the
-end of the list, so it becomes the new tail element. 'Concatenate' takes two
-properly constructed lists and appends the second list to the first. (Visual
-Studio 2008 does not support `LL_CONCAT` and `DL_CONCAT`, but VS2010 is ok.)
-
-The 'sort' operation never moves the elements in memory; rather it only adjusts
-the list order by altering the `prev` and `next` pointers in each element. Also
-the sort operation can change the list head to point to a new element.
-
-The 'foreach' operation is for easy iteration over the list from the head to the
-tail. A usage example is shown below. You can of course just use the `prev` and
-`next` pointers directly instead of using the 'foreach' macros.
-The 'foreach_safe' operation should be used if you plan to delete any of the list
-elements while iterating.
-
-The 'search' operation is a shortcut for iteration in search of a particular
-element. It is not any faster than manually iterating and testing each element.
-There are two forms: the "scalar" version searches for an element using a
-simple equality test on a given structure member, while the general version takes an
-element to which all others in the list will be compared using a `cmp` function.
-
-
-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 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; also, the output pointer from
- the search macros.
-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.
-
-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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "utlist.h"
-
-#define BUFLEN 20
-
-typedef struct el {
- char bname[BUFLEN];
- struct el *next, *prev;
-} el;
-
-int namecmp(el *a, el *b) {
- return strcmp(a->bname,b->bname);
-}
-
-el *head = NULL; /* important- initialize to NULL! */
-
-int main(int argc, char *argv[]) {
- el *name, *elt, *tmp, etmp;
-
- char linebuf[BUFLEN];
- FILE *file;
-
- if ( (file = fopen( "test11.dat", "r" )) == NULL ) {
- perror("can't open: ");
- exit(-1);
- }
-
- while (fgets(linebuf,BUFLEN,file) != NULL) {
- if ( (name = (el*)malloc(sizeof(el))) == NULL) exit(-1);
- strncpy(name->bname,linebuf,BUFLEN);
- DL_APPEND(head, name);
- }
- DL_SORT(head, namecmp);
- DL_FOREACH(head,elt) printf("%s", elt->bname);
-
- memcpy(&etmp.bname, "WES\n", 5);
- DL_SEARCH(head,elt,&etmp,namecmp);
- if (elt) printf("found %s\n", elt->bname);
-
- /* now delete each element, use the safe iterator */
- DL_FOREACH_SAFE(head,elt,tmp) {
- DL_DELETE(head,elt);
- }
-
- fclose(file);
-
- return 0;
-}
---------------------------------------------------------------------------------
-
-// vim: set nowrap syntax=asciidoc:
-
diff --git a/apps/systemlib/uthash/doc/utstring.txt b/apps/systemlib/uthash/doc/utstring.txt
deleted file mode 100644
index abfdcd107..000000000
--- a/apps/systemlib/uthash/doc/utstring.txt
+++ /dev/null
@@ -1,178 +0,0 @@
-utstring: dynamic string macros for C
-=====================================
-Troy D. Hanson <thanson@users.sourceforge.net>
-v1.9.5, November 2011
-
-include::sflogo.txt[]
-include::topnav_utstring.txt[]
-
-Introduction
-------------
-include::toc.txt[]
-
-A set of very basic dynamic string macros for C programs are included with
-uthash in `utstring.h`. To use these macros 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 basic operations such as inserting data (including
-binary data-- despite its name, utstring is not limited to string content),
-concatenation, getting the length and content, and clearing it. The string
-<<operations,operations>> are listed below.
-
-Download
-~~~~~~~~
-To download the `utstring.h` header file, follow the link on the
-http://uthash.sourceforge.net[uthash home page].
-
-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 <stdio.h>
-#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 is meant to demonstrate that printf 'appends' to the string.
-It also shows concatenation.
-
-.Sample 2
--------------------------------------------------------------------------------
-#include <stdio.h>
-#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 last 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 <stdio.h>
-#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<m,40<",grid="none",options="none"]
-|===============================================================================
-| utstring_new(s) | allocate a new utstring
-| utstring_renew(s) | allocate a new utstring (if s is `NULL`) otherwise clears it
-| utstring_free(s) | free an allocated utstring
-| utstring_init(s) | init a utstring (non-alloc)
-| utstring_done(s) | dispose of a utstring (non-allocd)
-| utstring_printf(s,fmt,...) | printf into a utstring (appends)
-| utstring_bincpy(s,bin,len) | insert binary data of length len (appends)
-| utstring_concat(dst,src) | concatenate src utstring to end of dst utstring
-| utstring_clear(s) | clear the content of s (setting its length to 0)
-| utstring_len(s) | obtain the length of s as an unsigned integer
-| utstring_body(s) | get `char*` to body of s (buffer is always null-terminated)
-|===============================================================================
-
-Notes
-~~~~~
-
-1. `utstring_new` and `utstring_free` are used to allocate a new string and free it,
- while `utstring_init` and `utstring_done` can be used if the UT_string is already
- allocated and just needs to be initialized or have its internal resources
- freed.
-2. `utstring_printf` is actually a function defined statically in `utstring.h`
- rather than a macro.
-
-// vim: set nowrap syntax=asciidoc:
-
diff --git a/apps/systemlib/uthash/utarray.h b/apps/systemlib/uthash/utarray.h
deleted file mode 100644
index 4ffb630bf..000000000
--- a/apps/systemlib/uthash/utarray.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
-Copyright (c) 2008-2012, Troy D. Hanson http://uthash.sourceforge.net
-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.
-*/
-
-/* a dynamic array implementation using macros
- * see http://uthash.sourceforge.net/utarray
- */
-#ifndef UTARRAY_H
-#define UTARRAY_H
-
-#define UTARRAY_VERSION 1.9.6
-
-#ifdef __GNUC__
-#define _UNUSED_ __attribute__ ((__unused__))
-#else
-#define _UNUSED_
-#endif
-
-#include <stddef.h> /* size_t */
-#include <string.h> /* memset, etc */
-#include <stdlib.h> /* exit */
-
-#define oom() exit(-1)
-
-typedef void (ctor_f)(void *dst, const void *src);
-typedef void (dtor_f)(void *elt);
-typedef void (init_f)(void *elt);
-typedef struct {
- size_t sz;
- init_f *init;
- ctor_f *copy;
- dtor_f *dtor;
-} UT_icd;
-
-typedef struct {
- unsigned i,n;/* i: index of next available slot, n: num slots */
- UT_icd icd; /* initializer, copy and destructor functions */
- char *d; /* n slots of size icd->sz*/
-} UT_array;
-
-#define utarray_init(a,_icd) do { \
- memset(a,0,sizeof(UT_array)); \
- (a)->icd=*_icd; \
-} while(0)
-
-#define utarray_done(a) do { \
- if ((a)->n) { \
- if ((a)->icd.dtor) { \
- size_t _ut_i; \
- for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
- (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
- } \
- } \
- free((a)->d); \
- } \
- (a)->n=0; \
-} while(0)
-
-#define utarray_new(a,_icd) do { \
- a=(UT_array*)malloc(sizeof(UT_array)); \
- utarray_init(a,_icd); \
-} while(0)
-
-#define utarray_free(a) do { \
- utarray_done(a); \
- free(a); \
-} while(0)
-
-#define utarray_reserve(a,by) do { \
- if (((a)->i+by) > ((a)->n)) { \
- while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \
- if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \
- } \
-} while(0)
-
-#define utarray_push_back(a,p) do { \
- utarray_reserve(a,1); \
- if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \
- else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \
-} while(0)
-
-#define utarray_pop_back(a) do { \
- if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \
- else { (a)->i--; } \
-} while(0)
-
-#define utarray_extend_back(a) do { \
- utarray_reserve(a,1); \
- if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \
- else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \
- (a)->i++; \
-} while(0)
-
-#define utarray_len(a) ((a)->i)
-
-#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
-#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) )))
-
-#define utarray_insert(a,p,j) do { \
- utarray_reserve(a,1); \
- if (j > (a)->i) break; \
- if ((j) < (a)->i) { \
- memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \
- ((a)->i - (j))*((a)->icd.sz)); \
- } \
- if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \
- else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \
- (a)->i++; \
-} while(0)
-
-#define utarray_inserta(a,w,j) do { \
- if (utarray_len(w) == 0) break; \
- if (j > (a)->i) break; \
- utarray_reserve(a,utarray_len(w)); \
- if ((j) < (a)->i) { \
- memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \
- _utarray_eltptr(a,j), \
- ((a)->i - (j))*((a)->icd.sz)); \
- } \
- if ((a)->icd.copy) { \
- size_t _ut_i; \
- for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \
- (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \
- } \
- } else { \
- memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \
- utarray_len(w)*((a)->icd.sz)); \
- } \
- (a)->i += utarray_len(w); \
-} while(0)
-
-#define utarray_resize(dst,num) do { \
- size_t _ut_i; \
- if (dst->i > (size_t)(num)) { \
- if ((dst)->icd.dtor) { \
- for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \
- (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \
- } \
- } \
- } else if (dst->i < (size_t)(num)) { \
- utarray_reserve(dst,num-dst->i); \
- if ((dst)->icd.init) { \
- for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \
- (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \
- } \
- } else { \
- memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \
- } \
- } \
- dst->i = num; \
-} while(0)
-
-#define utarray_concat(dst,src) do { \
- utarray_inserta((dst),(src),utarray_len(dst)); \
-} while(0)
-
-#define utarray_erase(a,pos,len) do { \
- if ((a)->icd.dtor) { \
- size_t _ut_i; \
- for(_ut_i=0; _ut_i < len; _ut_i++) { \
- (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \
- } \
- } \
- if ((a)->i > (pos+len)) { \
- memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \
- (((a)->i)-(pos+len))*((a)->icd.sz)); \
- } \
- (a)->i -= (len); \
-} while(0)
-
-#define utarray_renew(a,u) do { \
- if (a) utarray_clear(a); \
- else utarray_new((a),(u)); \
-} while(0)
-
-#define utarray_clear(a) do { \
- if ((a)->i > 0) { \
- if ((a)->icd.dtor) { \
- size_t _ut_i; \
- for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
- (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
- } \
- } \
- (a)->i = 0; \
- } \
-} while(0)
-
-#define utarray_sort(a,cmp) do { \
- qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \
-} while(0)
-
-#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
-
-#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
-#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL))
-#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
-#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
-#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(a)->icd.sz) : -1)
-
-/* last we pre-define a few icd for common utarrays of ints and strings */
-static void utarray_str_cpy(void *dst, const void *src) {
- char **_src = (char**)src, **_dst = (char**)dst;
- *_dst = (*_src == NULL) ? NULL : strdup(*_src);
-}
-static void utarray_str_dtor(void *elt) {
- char **eltc = (char**)elt;
- if (*eltc) free(*eltc);
-}
-static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
-static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL};
-static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL};
-
-
-#endif /* UTARRAY_H */
diff --git a/apps/systemlib/uthash/uthash.h b/apps/systemlib/uthash/uthash.h
deleted file mode 100644
index 9f83fc34f..000000000
--- a/apps/systemlib/uthash/uthash.h
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
-Copyright (c) 2003-2012, Troy D. Hanson http://uthash.sourceforge.net
-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.
-*/
-
-#ifndef UTHASH_H
-#define UTHASH_H
-
-#include <string.h> /* memcmp,strlen */
-#include <stddef.h> /* ptrdiff_t */
-#include <stdlib.h> /* exit() */
-
-/* These macros use decltype or the earlier __typeof GNU extension.
- As decltype is only available in newer compilers (VS2010 or gcc 4.3+
- when compiling c++ source) this code uses whatever method is needed
- or, for VS2008 where neither is available, uses casting workarounds. */
-#ifdef _MSC_VER /* MS compiler */
-#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
-#define DECLTYPE(x) (decltype(x))
-#else /* VS2008 or older (or VS2010 in C mode) */
-#define NO_DECLTYPE
-#define DECLTYPE(x)
-#endif
-#else /* GNU, Sun and other compilers */
-#define DECLTYPE(x) (__typeof(x))
-#endif
-
-#ifdef NO_DECLTYPE
-#define DECLTYPE_ASSIGN(dst,src) \
-do { \
- char **_da_dst = (char**)(&(dst)); \
- *_da_dst = (char*)(src); \
-} while(0)
-#else
-#define DECLTYPE_ASSIGN(dst,src) \
-do { \
- (dst) = DECLTYPE(dst)(src); \
-} while(0)
-#endif
-
-/* a number of the hash function use uint32_t which isn't defined on win32 */
-#ifdef _MSC_VER
-typedef unsigned int uint32_t;
-typedef unsigned char uint8_t;
-#else
-#include <inttypes.h> /* uint32_t */
-#endif
-
-#define UTHASH_VERSION 1.9.6
-
-#ifndef uthash_fatal
-#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
-#endif
-#ifndef uthash_malloc
-#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
-#endif
-#ifndef uthash_free
-#define uthash_free(ptr,sz) free(ptr) /* free fcn */
-#endif
-
-#ifndef uthash_noexpand_fyi
-#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
-#endif
-#ifndef uthash_expand_fyi
-#define uthash_expand_fyi(tbl) /* can be defined to log expands */
-#endif
-
-/* initial number of buckets */
-#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
-#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
-#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
-
-/* calculate the element whose hash handle address is hhe */
-#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
-
-#define HASH_FIND(hh,head,keyptr,keylen,out) \
-do { \
- unsigned _hf_bkt,_hf_hashv; \
- out=NULL; \
- if (head) { \
- HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
- if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
- HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
- keyptr,keylen,out); \
- } \
- } \
-} while (0)
-
-#ifdef HASH_BLOOM
-#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
-#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
-#define HASH_BLOOM_MAKE(tbl) \
-do { \
- (tbl)->bloom_nbits = HASH_BLOOM; \
- (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
- if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
- memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
- (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
-} while (0)
-
-#define HASH_BLOOM_FREE(tbl) \
-do { \
- uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
-} while (0)
-
-#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
-#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
-
-#define HASH_BLOOM_ADD(tbl,hashv) \
- HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
-
-#define HASH_BLOOM_TEST(tbl,hashv) \
- HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
-
-#else
-#define HASH_BLOOM_MAKE(tbl)
-#define HASH_BLOOM_FREE(tbl)
-#define HASH_BLOOM_ADD(tbl,hashv)
-#define HASH_BLOOM_TEST(tbl,hashv) (1)
-#endif
-
-#define HASH_MAKE_TABLE(hh,head) \
-do { \
- (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
- sizeof(UT_hash_table)); \
- if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
- memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
- (head)->hh.tbl->tail = &((head)->hh); \
- (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
- (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
- (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
- (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
- HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
- if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
- memset((head)->hh.tbl->buckets, 0, \
- HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
- HASH_BLOOM_MAKE((head)->hh.tbl); \
- (head)->hh.tbl->signature = HASH_SIGNATURE; \
-} while(0)
-
-#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
- HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
-
-#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
-do { \
- unsigned _ha_bkt; \
- (add)->hh.next = NULL; \
- (add)->hh.key = (char*)keyptr; \
- (add)->hh.keylen = (unsigned)keylen_in; \
- if (!(head)) { \
- head = (add); \
- (head)->hh.prev = NULL; \
- HASH_MAKE_TABLE(hh,head); \
- } else { \
- (head)->hh.tbl->tail->next = (add); \
- (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
- (head)->hh.tbl->tail = &((add)->hh); \
- } \
- (head)->hh.tbl->num_items++; \
- (add)->hh.tbl = (head)->hh.tbl; \
- HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
- (add)->hh.hashv, _ha_bkt); \
- HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
- HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
- HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
- HASH_FSCK(hh,head); \
-} while(0)
-
-#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
-do { \
- bkt = ((hashv) & ((num_bkts) - 1)); \
-} while(0)
-
-/* delete "delptr" from the hash table.
- * "the usual" patch-up process for the app-order doubly-linked-list.
- * The use of _hd_hh_del below deserves special explanation.
- * These used to be expressed using (delptr) but that led to a bug
- * if someone used the same symbol for the head and deletee, like
- * HASH_DELETE(hh,users,users);
- * We want that to work, but by changing the head (users) below
- * we were forfeiting our ability to further refer to the deletee (users)
- * in the patch-up process. Solution: use scratch space to
- * copy the deletee pointer, then the latter references are via that
- * scratch pointer rather than through the repointed (users) symbol.
- */
-#define HASH_DELETE(hh,head,delptr) \
-do { \
- unsigned _hd_bkt; \
- struct UT_hash_handle *_hd_hh_del; \
- if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
- uthash_free((head)->hh.tbl->buckets, \
- (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
- HASH_BLOOM_FREE((head)->hh.tbl); \
- uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
- head = NULL; \
- } else { \
- _hd_hh_del = &((delptr)->hh); \
- if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
- (head)->hh.tbl->tail = \
- (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
- (head)->hh.tbl->hho); \
- } \
- if ((delptr)->hh.prev) { \
- ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
- (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
- } else { \
- DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
- } \
- if (_hd_hh_del->next) { \
- ((UT_hash_handle*)((char*)_hd_hh_del->next + \
- (head)->hh.tbl->hho))->prev = \
- _hd_hh_del->prev; \
- } \
- HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
- HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
- (head)->hh.tbl->num_items--; \
- } \
- HASH_FSCK(hh,head); \
-} while (0)
-
-
-/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
-#define HASH_FIND_STR(head,findstr,out) \
- HASH_FIND(hh,head,findstr,strlen(findstr),out)
-#define HASH_ADD_STR(head,strfield,add) \
- HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
-#define HASH_FIND_INT(head,findint,out) \
- HASH_FIND(hh,head,findint,sizeof(int),out)
-#define HASH_ADD_INT(head,intfield,add) \
- HASH_ADD(hh,head,intfield,sizeof(int),add)
-#define HASH_FIND_PTR(head,findptr,out) \
- HASH_FIND(hh,head,findptr,sizeof(void *),out)
-#define HASH_ADD_PTR(head,ptrfield,add) \
- HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
-#define HASH_DEL(head,delptr) \
- HASH_DELETE(hh,head,delptr)
-
-/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
- * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
- */
-#ifdef HASH_DEBUG
-#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
-#define HASH_FSCK(hh,head) \
-do { \
- unsigned _bkt_i; \
- unsigned _count, _bkt_count; \
- char *_prev; \
- struct UT_hash_handle *_thh; \
- if (head) { \
- _count = 0; \
- for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
- _bkt_count = 0; \
- _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
- _prev = NULL; \
- while (_thh) { \
- if (_prev != (char*)(_thh->hh_prev)) { \
- HASH_OOPS("invalid hh_prev %p, actual %p\n", \
- _thh->hh_prev, _prev ); \
- } \
- _bkt_count++; \
- _prev = (char*)(_thh); \
- _thh = _thh->hh_next; \
- } \
- _count += _bkt_count; \
- if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
- HASH_OOPS("invalid bucket count %d, actual %d\n", \
- (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
- } \
- } \
- if (_count != (head)->hh.tbl->num_items) { \
- HASH_OOPS("invalid hh item count %d, actual %d\n", \
- (head)->hh.tbl->num_items, _count ); \
- } \
- /* traverse hh in app order; check next/prev integrity, count */ \
- _count = 0; \
- _prev = NULL; \
- _thh = &(head)->hh; \
- while (_thh) { \
- _count++; \
- if (_prev !=(char*)(_thh->prev)) { \
- HASH_OOPS("invalid prev %p, actual %p\n", \
- _thh->prev, _prev ); \
- } \
- _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
- _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
- (head)->hh.tbl->hho) : NULL ); \
- } \
- if (_count != (head)->hh.tbl->num_items) { \
- HASH_OOPS("invalid app item count %d, actual %d\n", \
- (head)->hh.tbl->num_items, _count ); \
- } \
- } \
-} while (0)
-#else
-#define HASH_FSCK(hh,head)
-#endif
-
-/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
- * the descriptor to which this macro is defined for tuning the hash function.
- * The app can #include <unistd.h> to get the prototype for write(2). */
-#ifdef HASH_EMIT_KEYS
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
-do { \
- unsigned _klen = fieldlen; \
- write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
- write(HASH_EMIT_KEYS, keyptr, fieldlen); \
-} while (0)
-#else
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
-#endif
-
-/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
-#ifdef HASH_FUNCTION
-#define HASH_FCN HASH_FUNCTION
-#else
-#define HASH_FCN HASH_JEN
-#endif
-
-/* The Bernstein hash function, used in Perl prior to v5.6 */
-#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _hb_keylen=keylen; \
- char *_hb_key=(char*)(key); \
- (hashv) = 0; \
- while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
- bkt = (hashv) & (num_bkts-1); \
-} while (0)
-
-
-/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
- * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
-#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _sx_i; \
- char *_hs_key=(char*)(key); \
- hashv = 0; \
- for(_sx_i=0; _sx_i < keylen; _sx_i++) \
- hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
- bkt = hashv & (num_bkts-1); \
-} while (0)
-
-#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _fn_i; \
- char *_hf_key=(char*)(key); \
- hashv = 2166136261UL; \
- for(_fn_i=0; _fn_i < keylen; _fn_i++) \
- hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _ho_i; \
- char *_ho_key=(char*)(key); \
- hashv = 0; \
- for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
- hashv += _ho_key[_ho_i]; \
- hashv += (hashv << 10); \
- hashv ^= (hashv >> 6); \
- } \
- hashv += (hashv << 3); \
- hashv ^= (hashv >> 11); \
- hashv += (hashv << 15); \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-#define HASH_JEN_MIX(a,b,c) \
-do { \
- a -= b; a -= c; a ^= ( c >> 13 ); \
- b -= c; b -= a; b ^= ( a << 8 ); \
- c -= a; c -= b; c ^= ( b >> 13 ); \
- a -= b; a -= c; a ^= ( c >> 12 ); \
- b -= c; b -= a; b ^= ( a << 16 ); \
- c -= a; c -= b; c ^= ( b >> 5 ); \
- a -= b; a -= c; a ^= ( c >> 3 ); \
- b -= c; b -= a; b ^= ( a << 10 ); \
- c -= a; c -= b; c ^= ( b >> 15 ); \
-} while (0)
-
-#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
-do { \
- unsigned _hj_i,_hj_j,_hj_k; \
- char *_hj_key=(char*)(key); \
- hashv = 0xfeedbeef; \
- _hj_i = _hj_j = 0x9e3779b9; \
- _hj_k = (unsigned)keylen; \
- while (_hj_k >= 12) { \
- _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
- + ( (unsigned)_hj_key[2] << 16 ) \
- + ( (unsigned)_hj_key[3] << 24 ) ); \
- _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
- + ( (unsigned)_hj_key[6] << 16 ) \
- + ( (unsigned)_hj_key[7] << 24 ) ); \
- hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
- + ( (unsigned)_hj_key[10] << 16 ) \
- + ( (unsigned)_hj_key[11] << 24 ) ); \
- \
- HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
- \
- _hj_key += 12; \
- _hj_k -= 12; \
- } \
- hashv += keylen; \
- switch ( _hj_k ) { \
- case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
- case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
- case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
- case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
- case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
- case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
- case 5: _hj_j += _hj_key[4]; \
- case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
- case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
- case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
- case 1: _hj_i += _hj_key[0]; \
- } \
- HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-/* The Paul Hsieh hash function */
-#undef get16bits
-#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
- || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
-#define get16bits(d) (*((const uint16_t *) (d)))
-#endif
-
-#if !defined (get16bits)
-#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
- +(uint32_t)(((const uint8_t *)(d))[0]) )
-#endif
-#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
-do { \
- char *_sfh_key=(char*)(key); \
- uint32_t _sfh_tmp, _sfh_len = keylen; \
- \
- int _sfh_rem = _sfh_len & 3; \
- _sfh_len >>= 2; \
- hashv = 0xcafebabe; \
- \
- /* Main loop */ \
- for (;_sfh_len > 0; _sfh_len--) { \
- hashv += get16bits (_sfh_key); \
- _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
- hashv = (hashv << 16) ^ _sfh_tmp; \
- _sfh_key += 2*sizeof (uint16_t); \
- hashv += hashv >> 11; \
- } \
- \
- /* Handle end cases */ \
- switch (_sfh_rem) { \
- case 3: hashv += get16bits (_sfh_key); \
- hashv ^= hashv << 16; \
- hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
- hashv += hashv >> 11; \
- break; \
- case 2: hashv += get16bits (_sfh_key); \
- hashv ^= hashv << 11; \
- hashv += hashv >> 17; \
- break; \
- case 1: hashv += *_sfh_key; \
- hashv ^= hashv << 10; \
- hashv += hashv >> 1; \
- } \
- \
- /* Force "avalanching" of final 127 bits */ \
- hashv ^= hashv << 3; \
- hashv += hashv >> 5; \
- hashv ^= hashv << 4; \
- hashv += hashv >> 17; \
- hashv ^= hashv << 25; \
- hashv += hashv >> 6; \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-
-#ifdef HASH_USING_NO_STRICT_ALIASING
-/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
- * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
- * MurmurHash uses the faster approach only on CPU's where we know it's safe.
- *
- * Note the preprocessor built-in defines can be emitted using:
- *
- * gcc -m64 -dM -E - < /dev/null (on gcc)
- * cc -## a.c (where a.c is a simple test file) (Sun Studio)
- */
-#if (defined(__i386__) || defined(__x86_64__))
-#define MUR_GETBLOCK(p,i) p[i]
-#else /* non intel */
-#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
-#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
-#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
-#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
-#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
-#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
-#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
-#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
-#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
-#else /* assume little endian non-intel */
-#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
-#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
-#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
-#endif
-#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
- (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
- (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
- MUR_ONE_THREE(p))))
-#endif
-#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
-#define MUR_FMIX(_h) \
-do { \
- _h ^= _h >> 16; \
- _h *= 0x85ebca6b; \
- _h ^= _h >> 13; \
- _h *= 0xc2b2ae35l; \
- _h ^= _h >> 16; \
-} while(0)
-
-#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
-do { \
- const uint8_t *_mur_data = (const uint8_t*)(key); \
- const int _mur_nblocks = (keylen) / 4; \
- uint32_t _mur_h1 = 0xf88D5353; \
- uint32_t _mur_c1 = 0xcc9e2d51; \
- uint32_t _mur_c2 = 0x1b873593; \
- const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
- int _mur_i; \
- for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
- uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
- _mur_k1 *= _mur_c1; \
- _mur_k1 = MUR_ROTL32(_mur_k1,15); \
- _mur_k1 *= _mur_c2; \
- \
- _mur_h1 ^= _mur_k1; \
- _mur_h1 = MUR_ROTL32(_mur_h1,13); \
- _mur_h1 = _mur_h1*5+0xe6546b64; \
- } \
- const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
- uint32_t _mur_k1=0; \
- switch((keylen) & 3) { \
- case 3: _mur_k1 ^= _mur_tail[2] << 16; \
- case 2: _mur_k1 ^= _mur_tail[1] << 8; \
- case 1: _mur_k1 ^= _mur_tail[0]; \
- _mur_k1 *= _mur_c1; \
- _mur_k1 = MUR_ROTL32(_mur_k1,15); \
- _mur_k1 *= _mur_c2; \
- _mur_h1 ^= _mur_k1; \
- } \
- _mur_h1 ^= (keylen); \
- MUR_FMIX(_mur_h1); \
- hashv = _mur_h1; \
- bkt = hashv & (num_bkts-1); \
-} while(0)
-#endif /* HASH_USING_NO_STRICT_ALIASING */
-
-/* key comparison function; return 0 if keys equal */
-#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
-
-/* iterate over items in a known bucket to find desired item */
-#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
-do { \
- if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
- else out=NULL; \
- while (out) { \
- if ((out)->hh.keylen == keylen_in) { \
- if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \
- } \
- if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
- else out = NULL; \
- } \
-} while(0)
-
-/* add an item to a bucket */
-#define HASH_ADD_TO_BKT(head,addhh) \
-do { \
- head.count++; \
- (addhh)->hh_next = head.hh_head; \
- (addhh)->hh_prev = NULL; \
- if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
- (head).hh_head=addhh; \
- if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
- && (addhh)->tbl->noexpand != 1) { \
- HASH_EXPAND_BUCKETS((addhh)->tbl); \
- } \
-} while(0)
-
-/* remove an item from a given bucket */
-#define HASH_DEL_IN_BKT(hh,head,hh_del) \
- (head).count--; \
- if ((head).hh_head == hh_del) { \
- (head).hh_head = hh_del->hh_next; \
- } \
- if (hh_del->hh_prev) { \
- hh_del->hh_prev->hh_next = hh_del->hh_next; \
- } \
- if (hh_del->hh_next) { \
- hh_del->hh_next->hh_prev = hh_del->hh_prev; \
- }
-
-/* Bucket expansion has the effect of doubling the number of buckets
- * and redistributing the items into the new buckets. Ideally the
- * items will distribute more or less evenly into the new buckets
- * (the extent to which this is true is a measure of the quality of
- * the hash function as it applies to the key domain).
- *
- * With the items distributed into more buckets, the chain length
- * (item count) in each bucket is reduced. Thus by expanding buckets
- * the hash keeps a bound on the chain length. This bounded chain
- * length is the essence of how a hash provides constant time lookup.
- *
- * The calculation of tbl->ideal_chain_maxlen below deserves some
- * explanation. First, keep in mind that we're calculating the ideal
- * maximum chain length based on the *new* (doubled) bucket count.
- * In fractions this is just n/b (n=number of items,b=new num buckets).
- * Since the ideal chain length is an integer, we want to calculate
- * ceil(n/b). We don't depend on floating point arithmetic in this
- * hash, so to calculate ceil(n/b) with integers we could write
- *
- * ceil(n/b) = (n/b) + ((n%b)?1:0)
- *
- * and in fact a previous version of this hash did just that.
- * But now we have improved things a bit by recognizing that b is
- * always a power of two. We keep its base 2 log handy (call it lb),
- * so now we can write this with a bit shift and logical AND:
- *
- * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
- *
- */
-#define HASH_EXPAND_BUCKETS(tbl) \
-do { \
- unsigned _he_bkt; \
- unsigned _he_bkt_i; \
- struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
- UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
- _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
- 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
- if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
- memset(_he_new_buckets, 0, \
- 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
- tbl->ideal_chain_maxlen = \
- (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
- ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
- tbl->nonideal_items = 0; \
- for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
- { \
- _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
- while (_he_thh) { \
- _he_hh_nxt = _he_thh->hh_next; \
- HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
- _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
- if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
- tbl->nonideal_items++; \
- _he_newbkt->expand_mult = _he_newbkt->count / \
- tbl->ideal_chain_maxlen; \
- } \
- _he_thh->hh_prev = NULL; \
- _he_thh->hh_next = _he_newbkt->hh_head; \
- if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
- _he_thh; \
- _he_newbkt->hh_head = _he_thh; \
- _he_thh = _he_hh_nxt; \
- } \
- } \
- uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
- tbl->num_buckets *= 2; \
- tbl->log2_num_buckets++; \
- tbl->buckets = _he_new_buckets; \
- tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
- (tbl->ineff_expands+1) : 0; \
- if (tbl->ineff_expands > 1) { \
- tbl->noexpand=1; \
- uthash_noexpand_fyi(tbl); \
- } \
- uthash_expand_fyi(tbl); \
-} while(0)
-
-
-/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
-/* Note that HASH_SORT assumes the hash handle name to be hh.
- * HASH_SRT was added to allow the hash handle name to be passed in. */
-#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
-#define HASH_SRT(hh,head,cmpfcn) \
-do { \
- unsigned _hs_i; \
- unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
- struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
- if (head) { \
- _hs_insize = 1; \
- _hs_looping = 1; \
- _hs_list = &((head)->hh); \
- while (_hs_looping) { \
- _hs_p = _hs_list; \
- _hs_list = NULL; \
- _hs_tail = NULL; \
- _hs_nmerges = 0; \
- while (_hs_p) { \
- _hs_nmerges++; \
- _hs_q = _hs_p; \
- _hs_psize = 0; \
- for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
- _hs_psize++; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- if (! (_hs_q) ) break; \
- } \
- _hs_qsize = _hs_insize; \
- while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
- if (_hs_psize == 0) { \
- _hs_e = _hs_q; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_qsize--; \
- } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
- _hs_e = _hs_p; \
- _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
- ((void*)((char*)(_hs_p->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_psize--; \
- } else if (( \
- cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
- DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
- ) <= 0) { \
- _hs_e = _hs_p; \
- _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
- ((void*)((char*)(_hs_p->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_psize--; \
- } else { \
- _hs_e = _hs_q; \
- _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
- ((void*)((char*)(_hs_q->next) + \
- (head)->hh.tbl->hho)) : NULL); \
- _hs_qsize--; \
- } \
- if ( _hs_tail ) { \
- _hs_tail->next = ((_hs_e) ? \
- ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
- } else { \
- _hs_list = _hs_e; \
- } \
- _hs_e->prev = ((_hs_tail) ? \
- ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
- _hs_tail = _hs_e; \
- } \
- _hs_p = _hs_q; \
- } \
- _hs_tail->next = NULL; \
- if ( _hs_nmerges <= 1 ) { \
- _hs_looping=0; \
- (head)->hh.tbl->tail = _hs_tail; \
- DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
- } \
- _hs_insize *= 2; \
- } \
- HASH_FSCK(hh,head); \
- } \
-} while (0)
-
-/* This function selects items from one hash into another hash.
- * The end result is that the selected items have dual presence
- * in both hashes. There is no copy of the items made; rather
- * they are added into the new hash through a secondary hash
- * hash handle that must be present in the structure. */
-#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
-do { \
- unsigned _src_bkt, _dst_bkt; \
- void *_last_elt=NULL, *_elt; \
- UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
- ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
- if (src) { \
- for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
- for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
- _src_hh; \
- _src_hh = _src_hh->hh_next) { \
- _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
- if (cond(_elt)) { \
- _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
- _dst_hh->key = _src_hh->key; \
- _dst_hh->keylen = _src_hh->keylen; \
- _dst_hh->hashv = _src_hh->hashv; \
- _dst_hh->prev = _last_elt; \
- _dst_hh->next = NULL; \
- if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
- if (!dst) { \
- DECLTYPE_ASSIGN(dst,_elt); \
- HASH_MAKE_TABLE(hh_dst,dst); \
- } else { \
- _dst_hh->tbl = (dst)->hh_dst.tbl; \
- } \
- HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
- HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
- (dst)->hh_dst.tbl->num_items++; \
- _last_elt = _elt; \
- _last_elt_hh = _dst_hh; \
- } \
- } \
- } \
- } \
- HASH_FSCK(hh_dst,dst); \
-} while (0)
-
-#define HASH_CLEAR(hh,head) \
-do { \
- if (head) { \
- uthash_free((head)->hh.tbl->buckets, \
- (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
- HASH_BLOOM_FREE((head)->hh.tbl); \
- uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
- (head)=NULL; \
- } \
-} while(0)
-
-#ifdef NO_DECLTYPE
-#define HASH_ITER(hh,head,el,tmp) \
-for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
- el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
-#else
-#define HASH_ITER(hh,head,el,tmp) \
-for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
- el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
-#endif
-
-/* obtain a count of items in the hash */
-#define HASH_COUNT(head) HASH_CNT(hh,head)
-#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
-
-typedef struct UT_hash_bucket {
- struct UT_hash_handle *hh_head;
- unsigned count;
-
- /* expand_mult is normally set to 0. In this situation, the max chain length
- * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
- * the bucket's chain exceeds this length, bucket expansion is triggered).
- * However, setting expand_mult to a non-zero value delays bucket expansion
- * (that would be triggered by additions to this particular bucket)
- * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
- * (The multiplier is simply expand_mult+1). The whole idea of this
- * multiplier is to reduce bucket expansions, since they are expensive, in
- * situations where we know that a particular bucket tends to be overused.
- * It is better to let its chain length grow to a longer yet-still-bounded
- * value, than to do an O(n) bucket expansion too often.
- */
- unsigned expand_mult;
-
-} UT_hash_bucket;
-
-/* random signature used only to find hash tables in external analysis */
-#define HASH_SIGNATURE 0xa0111fe1
-#define HASH_BLOOM_SIGNATURE 0xb12220f2
-
-typedef struct UT_hash_table {
- UT_hash_bucket *buckets;
- unsigned num_buckets, log2_num_buckets;
- unsigned num_items;
- struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
- ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
-
- /* in an ideal situation (all buckets used equally), no bucket would have
- * more than ceil(#items/#buckets) items. that's the ideal chain length. */
- unsigned ideal_chain_maxlen;
-
- /* nonideal_items is the number of items in the hash whose chain position
- * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
- * hash distribution; reaching them in a chain traversal takes >ideal steps */
- unsigned nonideal_items;
-
- /* ineffective expands occur when a bucket doubling was performed, but
- * afterward, more than half the items in the hash had nonideal chain
- * positions. If this happens on two consecutive expansions we inhibit any
- * further expansion, as it's not helping; this happens when the hash
- * function isn't a good fit for the key domain. When expansion is inhibited
- * the hash will still work, albeit no longer in constant time. */
- unsigned ineff_expands, noexpand;
-
- uint32_t signature; /* used only to find hash tables in external analysis */
-#ifdef HASH_BLOOM
- uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
- uint8_t *bloom_bv;
- char bloom_nbits;
-#endif
-
-} UT_hash_table;
-
-typedef struct UT_hash_handle {
- struct UT_hash_table *tbl;
- void *prev; /* prev element in app order */
- void *next; /* next element in app order */
- struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
- struct UT_hash_handle *hh_next; /* next hh in bucket order */
- void *key; /* ptr to enclosing struct's key */
- unsigned keylen; /* enclosing struct's key len */
- unsigned hashv; /* result of hash-fcn(key) */
-} UT_hash_handle;
-
-#endif /* UTHASH_H */
diff --git a/apps/systemlib/uthash/utlist.h b/apps/systemlib/uthash/utlist.h
deleted file mode 100644
index 1578acad2..000000000
--- a/apps/systemlib/uthash/utlist.h
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
-Copyright (c) 2007-2012, Troy D. Hanson http://uthash.sourceforge.net
-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.
-*/
-
-#ifndef UTLIST_H
-#define UTLIST_H
-
-#define UTLIST_VERSION 1.9.6
-
-#include <assert.h>
-
-/*
- * This file contains macros to manipulate singly and doubly-linked lists.
- *
- * 1. LL_ macros: singly-linked lists.
- * 2. DL_ macros: doubly-linked lists.
- * 3. CDL_ macros: circular doubly-linked lists.
- *
- * To use singly-linked lists, your structure must have a "next" pointer.
- * To use doubly-linked lists, your structure must "prev" and "next" pointers.
- * Either way, the pointer to the head of the list must be initialized to NULL.
- *
- * ----------------.EXAMPLE -------------------------
- * struct item {
- * int id;
- * struct item *prev, *next;
- * }
- *
- * struct item *list = NULL:
- *
- * int main() {
- * struct item *item;
- * ... allocate and populate item ...
- * DL_APPEND(list, item);
- * }
- * --------------------------------------------------
- *
- * For doubly-linked lists, the append and delete macros are O(1)
- * For singly-linked lists, append and delete are O(n) but prepend is O(1)
- * The sort macro is O(n log(n)) for all types of single/double/circular lists.
- */
-
-/* These macros use decltype or the earlier __typeof GNU extension.
- As decltype is only available in newer compilers (VS2010 or gcc 4.3+
- when compiling c++ code), this code uses whatever method is needed
- or, for VS2008 where neither is available, uses casting workarounds. */
-#ifdef _MSC_VER /* MS compiler */
-#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
-#define LDECLTYPE(x) decltype(x)
-#else /* VS2008 or older (or VS2010 in C mode) */
-#define NO_DECLTYPE
-#define LDECLTYPE(x) char*
-#endif
-#else /* GNU, Sun and other compilers */
-#define LDECLTYPE(x) __typeof(x)
-#endif
-
-/* for VS2008 we use some workarounds to get around the lack of decltype,
- * namely, we always reassign our tmp variable to the list head if we need
- * to dereference its prev/next pointers, and save/restore the real head.*/
-#ifdef NO_DECLTYPE
-#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
-#define _NEXT(elt,list) ((char*)((list)->next))
-#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
-#define _PREV(elt,list) ((char*)((list)->prev))
-#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
-#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
-#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-#else
-#define _SV(elt,list)
-#define _NEXT(elt,list) ((elt)->next)
-#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
-#define _PREV(elt,list) ((elt)->prev)
-#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
-#define _RS(list)
-#define _CASTASGN(a,b) (a)=(b)
-#endif
-
-/******************************************************************************
- * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
- * Unwieldy variable names used here to avoid shadowing passed-in variables. *
- *****************************************************************************/
-#define LL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-#define DL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _CASTASGN(list->prev, _ls_tail); \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-#define CDL_SORT(list, cmp) \
-do { \
- LDECLTYPE(list) _ls_p; \
- LDECLTYPE(list) _ls_q; \
- LDECLTYPE(list) _ls_e; \
- LDECLTYPE(list) _ls_tail; \
- LDECLTYPE(list) _ls_oldhead; \
- LDECLTYPE(list) _tmp; \
- LDECLTYPE(list) _tmp2; \
- int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
- if (list) { \
- _ls_insize = 1; \
- _ls_looping = 1; \
- while (_ls_looping) { \
- _CASTASGN(_ls_p,list); \
- _CASTASGN(_ls_oldhead,list); \
- list = NULL; \
- _ls_tail = NULL; \
- _ls_nmerges = 0; \
- while (_ls_p) { \
- _ls_nmerges++; \
- _ls_q = _ls_p; \
- _ls_psize = 0; \
- for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
- _ls_psize++; \
- _SV(_ls_q,list); \
- if (_NEXT(_ls_q,list) == _ls_oldhead) { \
- _ls_q = NULL; \
- } else { \
- _ls_q = _NEXT(_ls_q,list); \
- } \
- _RS(list); \
- if (!_ls_q) break; \
- } \
- _ls_qsize = _ls_insize; \
- while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
- if (_ls_psize == 0) { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
- } else if (_ls_qsize == 0 || !_ls_q) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
- } else if (cmp(_ls_p,_ls_q) <= 0) { \
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
- if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
- } else { \
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
- if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
- } \
- if (_ls_tail) { \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
- } else { \
- _CASTASGN(list,_ls_e); \
- } \
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
- _ls_tail = _ls_e; \
- } \
- _ls_p = _ls_q; \
- } \
- _CASTASGN(list->prev,_ls_tail); \
- _CASTASGN(_tmp2,list); \
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
- if (_ls_nmerges <= 1) { \
- _ls_looping=0; \
- } \
- _ls_insize *= 2; \
- } \
- } else _tmp=NULL; /* quiet gcc unused variable warning */ \
-} while (0)
-
-/******************************************************************************
- * singly linked list macros (non-circular) *
- *****************************************************************************/
-#define LL_PREPEND(head,add) \
-do { \
- (add)->next = head; \
- head = add; \
-} while (0)
-
-#define LL_CONCAT(head1,head2) \
-do { \
- LDECLTYPE(head1) _tmp; \
- if (head1) { \
- _tmp = head1; \
- while (_tmp->next) { _tmp = _tmp->next; } \
- _tmp->next=(head2); \
- } else { \
- (head1)=(head2); \
- } \
-} while (0)
-
-#define LL_APPEND(head,add) \
-do { \
- LDECLTYPE(head) _tmp; \
- (add)->next=NULL; \
- if (head) { \
- _tmp = head; \
- while (_tmp->next) { _tmp = _tmp->next; } \
- _tmp->next=(add); \
- } else { \
- (head)=(add); \
- } \
-} while (0)
-
-#define LL_DELETE(head,del) \
-do { \
- LDECLTYPE(head) _tmp; \
- if ((head) == (del)) { \
- (head)=(head)->next; \
- } else { \
- _tmp = head; \
- while (_tmp->next && (_tmp->next != (del))) { \
- _tmp = _tmp->next; \
- } \
- if (_tmp->next) { \
- _tmp->next = ((del)->next); \
- } \
- } \
-} while (0)
-
-/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
-#define LL_APPEND_VS2008(head,add) \
-do { \
- if (head) { \
- (add)->next = head; /* use add->next as a temp variable */ \
- while ((add)->next->next) { (add)->next = (add)->next->next; } \
- (add)->next->next=(add); \
- } else { \
- (head)=(add); \
- } \
- (add)->next=NULL; \
-} while (0)
-
-#define LL_DELETE_VS2008(head,del) \
-do { \
- if ((head) == (del)) { \
- (head)=(head)->next; \
- } else { \
- char *_tmp = (char*)(head); \
- while ((head)->next && ((head)->next != (del))) { \
- head = (head)->next; \
- } \
- if ((head)->next) { \
- (head)->next = ((del)->next); \
- } \
- { \
- char **_head_alias = (char**)&(head); \
- *_head_alias = _tmp; \
- } \
- } \
-} while (0)
-#ifdef NO_DECLTYPE
-#undef LL_APPEND
-#define LL_APPEND LL_APPEND_VS2008
-#undef LL_DELETE
-#define LL_DELETE LL_DELETE_VS2008
-#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
-#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
-#endif
-/* end VS2008 replacements */
-
-#define LL_FOREACH(head,el) \
- for(el=head;el;el=(el)->next)
-
-#define LL_FOREACH_SAFE(head,el,tmp) \
- for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
-
-#define LL_SEARCH_SCALAR(head,out,field,val) \
-do { \
- LL_FOREACH(head,out) { \
- if ((out)->field == (val)) break; \
- } \
-} while(0)
-
-#define LL_SEARCH(head,out,elt,cmp) \
-do { \
- LL_FOREACH(head,out) { \
- if ((cmp(out,elt))==0) break; \
- } \
-} while(0)
-
-/******************************************************************************
- * doubly linked list macros (non-circular) *
- *****************************************************************************/
-#define DL_PREPEND(head,add) \
-do { \
- (add)->next = head; \
- if (head) { \
- (add)->prev = (head)->prev; \
- (head)->prev = (add); \
- } else { \
- (add)->prev = (add); \
- } \
- (head) = (add); \
-} while (0)
-
-#define DL_APPEND(head,add) \
-do { \
- if (head) { \
- (add)->prev = (head)->prev; \
- (head)->prev->next = (add); \
- (head)->prev = (add); \
- (add)->next = NULL; \
- } else { \
- (head)=(add); \
- (head)->prev = (head); \
- (head)->next = NULL; \
- } \
-} while (0)
-
-#define DL_CONCAT(head1,head2) \
-do { \
- LDECLTYPE(head1) _tmp; \
- if (head2) { \
- if (head1) { \
- _tmp = (head2)->prev; \
- (head2)->prev = (head1)->prev; \
- (head1)->prev->next = (head2); \
- (head1)->prev = _tmp; \
- } else { \
- (head1)=(head2); \
- } \
- } \
-} while (0)
-
-#define DL_DELETE(head,del) \
-do { \
- assert((del)->prev != NULL); \
- if ((del)->prev == (del)) { \
- (head)=NULL; \
- } else if ((del)==(head)) { \
- (del)->next->prev = (del)->prev; \
- (head) = (del)->next; \
- } else { \
- (del)->prev->next = (del)->next; \
- if ((del)->next) { \
- (del)->next->prev = (del)->prev; \
- } else { \
- (head)->prev = (del)->prev; \
- } \
- } \
-} while (0)
-
-
-#define DL_FOREACH(head,el) \
- for(el=head;el;el=(el)->next)
-
-/* this version is safe for deleting the elements during iteration */
-#define DL_FOREACH_SAFE(head,el,tmp) \
- for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
-
-/* these are identical to their singly-linked list counterparts */
-#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
-#define DL_SEARCH LL_SEARCH
-
-/******************************************************************************
- * circular doubly linked list macros *
- *****************************************************************************/
-#define CDL_PREPEND(head,add) \
-do { \
- if (head) { \
- (add)->prev = (head)->prev; \
- (add)->next = (head); \
- (head)->prev = (add); \
- (add)->prev->next = (add); \
- } else { \
- (add)->prev = (add); \
- (add)->next = (add); \
- } \
-(head)=(add); \
-} while (0)
-
-#define CDL_DELETE(head,del) \
-do { \
- if ( ((head)==(del)) && ((head)->next == (head))) { \
- (head) = 0L; \
- } else { \
- (del)->next->prev = (del)->prev; \
- (del)->prev->next = (del)->next; \
- if ((del) == (head)) (head)=(del)->next; \
- } \
-} while (0)
-
-#define CDL_FOREACH(head,el) \
- for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
-
-#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
- for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
- (el) && ((tmp2)=(el)->next, 1); \
- ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
-
-#define CDL_SEARCH_SCALAR(head,out,field,val) \
-do { \
- CDL_FOREACH(head,out) { \
- if ((out)->field == (val)) break; \
- } \
-} while(0)
-
-#define CDL_SEARCH(head,out,elt,cmp) \
-do { \
- CDL_FOREACH(head,out) { \
- if ((cmp(out,elt))==0) break; \
- } \
-} while(0)
-
-#endif /* UTLIST_H */
-
diff --git a/apps/systemlib/uthash/utstring.h b/apps/systemlib/uthash/utstring.h
deleted file mode 100644
index a181ad778..000000000
--- a/apps/systemlib/uthash/utstring.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-Copyright (c) 2008-2012, Troy D. Hanson http://uthash.sourceforge.net
-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.
-*/
-
-/* a dynamic string implementation using macros
- * see http://uthash.sourceforge.net/utstring
- */
-#ifndef UTSTRING_H
-#define UTSTRING_H
-
-#define UTSTRING_VERSION 1.9.6
-
-#ifdef __GNUC__
-#define _UNUSED_ __attribute__ ((__unused__))
-#else
-#define _UNUSED_
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#define oom() exit(-1)
-
-typedef struct {
- char *d;
- size_t n; /* allocd size */
- size_t i; /* index of first unused byte */
-} UT_string;
-
-#define utstring_reserve(s,amt) \
-do { \
- if (((s)->n - (s)->i) < (size_t)(amt)) { \
- (s)->d = (char*)realloc((s)->d, (s)->n + amt); \
- if ((s)->d == NULL) oom(); \
- (s)->n += amt; \
- } \
-} while(0)
-
-#define utstring_init(s) \
-do { \
- (s)->n = 0; (s)->i = 0; (s)->d = NULL; \
- utstring_reserve(s,100); \
- (s)->d[0] = '\0'; \
-} while(0)
-
-#define utstring_done(s) \
-do { \
- if ((s)->d != NULL) free((s)->d); \
- (s)->n = 0; \
-} while(0)
-
-#define utstring_free(s) \
-do { \
- utstring_done(s); \
- free(s); \
-} while(0)
-
-#define utstring_new(s) \
-do { \
- s = (UT_string*)calloc(sizeof(UT_string),1); \
- if (!s) oom(); \
- utstring_init(s); \
-} while(0)
-
-#define utstring_renew(s) \
-do { \
- if (s) { \
- utstring_clear(s); \
- } else { \
- utstring_new(s); \
- } \
-} while(0)
-
-#define utstring_clear(s) \
-do { \
- (s)->i = 0; \
- (s)->d[0] = '\0'; \
-} while(0)
-
-#define utstring_bincpy(s,b,l) \
-do { \
- utstring_reserve((s),(l)+1); \
- if (l) memcpy(&(s)->d[(s)->i], b, l); \
- (s)->i += l; \
- (s)->d[(s)->i]='\0'; \
-} while(0)
-
-#define utstring_concat(dst,src) \
-do { \
- utstring_reserve((dst),((src)->i)+1); \
- if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
- (dst)->i += (src)->i; \
- (dst)->d[(dst)->i]='\0'; \
-} while(0)
-
-#define utstring_len(s) ((unsigned)((s)->i))
-
-#define utstring_body(s) ((s)->d)
-
-_UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) {
- int n;
- va_list cp;
- while (1) {
-#ifdef _WIN32
- cp = ap;
-#else
- va_copy(cp, ap);
-#endif
- n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
- va_end(cp);
-
- if ((n > -1) && (n < (int)(s->n-s->i))) {
- s->i += n;
- return;
- }
-
- /* Else try again with more space. */
- if (n > -1) utstring_reserve(s,n+1); /* exact */
- else utstring_reserve(s,(s->n)*2); /* 2x */
- }
-}
-_UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) {
- va_list ap;
- va_start(ap,fmt);
- utstring_printf_va(s,fmt,ap);
- va_end(ap);
-}
-
-#endif /* UTSTRING_H */