diff --git a/Build/Docs/Notepad3.txt b/Build/Docs/Notepad3.txt index 87ff371e3..fa47348fe 100644 --- a/Build/Docs/Notepad3.txt +++ b/Build/Docs/Notepad3.txt @@ -435,7 +435,7 @@ read the files without being told the new key. Technical Details: -(http://www.andromeda.com/people/ddyer/notepad/NotepadCrypt-technotes.html) +(https://www.real-me.net/ddyer/notepad/NotepadCrypt-technotes.html) Passphrase Management: 256 bit encryption keys are geneated from ascii passphrases by diff --git a/Build/Docs/Oniguruma_RE.txt b/Build/Docs/Oniguruma_RE.txt index 9c27e6a4d..7ffd25345 100644 --- a/Build/Docs/Oniguruma_RE.txt +++ b/Build/Docs/Oniguruma_RE.txt @@ -1,6 +1,6 @@ -Oniguruma Regular Expressions Version 6.9.5 2020/01/28 +Oniguruma Regular Expressions Version 6.9.6 2020/07/31 -syntax: ONIG_SYNTAX_ONIGURUMA (default) +syntax: ONIG_SYNTAX_ONIGURUMA (default syntax) 1. Syntax elements @@ -21,19 +21,28 @@ syntax: ONIG_SYNTAX_ONIGURUMA (default) \f form feed (0x0C) \a bell (0x07) \e escape (0x1B) - \nnn octal char (encoded byte value) - \o{17777777777} wide octal char (character code point value) - \uHHHH wide hexadecimal char (character code point value) - \xHH hexadecimal char (encoded byte value) - \x{7HHHHHHH} wide hexadecimal char (character code point value) - \cx control char (character code point value) - \C-x control char (character code point value) - \M-x meta (x|0x80) (character code point value) - \M-\C-x meta control char (character code point value) + \nnn octal char (encoded byte value) + \xHH hexadecimal char (encoded byte value) + \x{7HHHHHHH} (1-8 digits) hexadecimal char (code point value) + \o{17777777777} (1-11 digits) octal char (code point value) + \uHHHH hexadecimal char (code point value) + \cx control char (code point value) + \C-x control char (code point value) + \M-x meta (x|0x80) (code point value) + \M-\C-x meta control char (code point value) (* \b as backspace is effective in character class only) +2.1 Code point sequences + + Hexadecimal code point (1-8 digits) + \x{7HHHHHHH 7HHHHHHH ... 7HHHHHHH} + + Octal code point (1-11 digits) + \o{17777777777 17777777777 ... 17777777777} + + 3. Character types . any character (except newline) @@ -91,13 +100,13 @@ syntax: ONIG_SYNTAX_ONIGURUMA (default) [Extended Grapheme Cluster mode] (default) Unicode case: - See [Unicode Standard Annex #29: https://unicode.org/reports/tr29] + See [Unicode Standard Annex #29: https://unicode.org/reports/tr29/] Not Unicode case: \X === (?>\r\n|\O) [Word mode] Currently, this mode is supported in Unicode only. - See [Unicode Standard Annex #29: https://unicode.org/reports/tr29] + See [Unicode Standard Annex #29: https://unicode.org/reports/tr29/] Character Property @@ -182,14 +191,14 @@ syntax: ONIG_SYNTAX_ONIGURUMA (default) [Extended Grapheme Cluster mode] (default) Unicode case: - See [Unicode Standard Annex #29: https://unicode.org/reports/tr29] + See [Unicode Standard Annex #29: https://unicode.org/reports/tr29/] Not Unicode: All positions except between \r and \n. [Word mode] Currently, this mode is supported in Unicode only. - See [Unicode Standard Annex #29: https://unicode.org/reports/tr29] + See [Unicode Standard Annex #29: https://unicode.org/reports/tr29/] @@ -357,7 +366,7 @@ syntax: ONIG_SYNTAX_ONIGURUMA (default) (?~|absent) Absent stopper (* original) After passed this operator, string right range is limited - at the point that does not include the string match whth + at the point that does not include the string match with . (?~|) Range clear diff --git a/Build/Docs/uthash/.gitignore b/Build/Docs/uthash/.gitignore deleted file mode 100644 index a9f7c8c0d..000000000 --- a/Build/Docs/uthash/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -ChangeLog.html -userguide.html -utarray.html -utlist.html -utringbuffer.html -utstring.html diff --git a/Build/Docs/uthash/ChangeLog.txt b/Build/Docs/uthash/ChangeLog.txt index 6ace1dac3..81c20de4e 100644 --- a/Build/Docs/uthash/ChangeLog.txt +++ b/Build/Docs/uthash/ChangeLog.txt @@ -5,6 +5,18 @@ Click to return to the link:index.html[uthash home page]. NOTE: This ChangeLog may be incomplete and/or incorrect. See the git commit log. +Version 2.1.0 (2018-12-20) +-------------------------- +* silence some Clang static analysis warnings +* add LL_INSERT_INORDER and LL_LOWER_BOUND etc (thanks, Jeffrey Lovitz and Mattias Eriksson!) +* add uthash_bzero for platforms without +* fix a missing HASH_BLOOM_ADD in HASH_SELECT (thanks, Pawel Veselov!) +* permit malloc failure to be recoverable via HASH_NONFATAL_OOM (thanks, Pawel Veselov!) +* avoid repeated calls to uthash_strlen in HASH_FIND_STR +* rename uthash_memcmp to HASH_KEYCMP, leaving the old name for compatibility +* add utstack.h +* remove libut + Version 2.0.2 (2017-03-02) -------------------------- * fix segfault in HASH_ADD_INORDER etc (thanks, Yana Kireyonok!) @@ -17,6 +29,7 @@ Version 2.0.1 (2016-07-05) * in-order insertion macros HASH_ADD_INORDER etc (thanks, Thilo Schulz!) * by-hashvalue insertion macros HASH_ADD_BYHASHVALUE etc * during key comparison, check hashvalue before doing a full memcmp +* add utringbuffer.h Version 1.9.9.1 (2014-11-18) ---------------------------- @@ -43,7 +56,7 @@ Version 1.9.8 (2013-03-10) * `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!) * fixed clang warnings (thanks wynnw!) * fixed `utarray_insert` when inserting past array end (thanks Rob Willett!) -* you can now find https://troydhanson.github.com/uthash[uthash on GitHub] +* you can now find https://troydhanson.github.com/uthash/[uthash on GitHub] * there's a https://groups.google.com/d/forum/uthash[uthash Google Group] * uthash has been downloaded 29,000+ times since 2006 on SourceForge @@ -183,7 +196,7 @@ Version 1.5 (2009-02-19) This change made HASH_FIND about 13% faster and enabled reader concurrency. * made link:license.html[BSD license] terms even more permissive * added link:userguide.pdf[PDF version] of User Guide -* added https://troydhanson.wordpress.com/feed[update news] image:rss.png[(RSS)] +* added https://troydhanson.wordpress.com/feed/[update news] image:rss.png[(RSS)] Version 1.4 (2008-09-23) -------------------------- diff --git a/src/uthash/License_BSD_revised.txt b/Build/Docs/uthash/License.txt similarity index 92% rename from src/uthash/License_BSD_revised.txt rename to Build/Docs/uthash/License.txt index bf7276e15..fec1494e1 100644 --- a/src/uthash/License_BSD_revised.txt +++ b/Build/Docs/uthash/License.txt @@ -1,4 +1,4 @@ -Copyright (c) 2005-2016, Troy D. Hanson https://troydhanson.github.com/uthash +Copyright (c) 2005-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without @@ -18,3 +18,4 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/Build/Docs/uthash/banner.png b/Build/Docs/uthash/banner.png deleted file mode 100644 index de4f310b9..000000000 Binary files a/Build/Docs/uthash/banner.png and /dev/null differ diff --git a/Build/Docs/uthash/banner.svg b/Build/Docs/uthash/banner.svg deleted file mode 100644 index f3143f171..000000000 --- a/Build/Docs/uthash/banner.svg +++ /dev/null @@ -1,451 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - ut hash - - - - - - - - - - - - - - - - - - - - - - - a hash tablefor C structures - - - diff --git a/Build/Docs/uthash/index.html b/Build/Docs/uthash/index.html deleted file mode 100644 index e3d8504bb..000000000 --- a/Build/Docs/uthash/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - uthash: a hash table for C structures - - - - - -
- GitHub page > - uthash home - - - -
- -
-
- - - -
- Any C structure can be stored in a hash table using uthash. Just add a - UT_hash_handle to the structure and choose one or more fields - in your structure to act as the key. Then use these macros to store, - retrieve or delete items from the hash table. - -
-Example 1. Adding an item to a hash. -
-
-#include "uthash.h"
-
-struct my_struct {
-    int id;            /* we'll use this field as the key */
-    char name[10];             
-    UT_hash_handle hh; /* makes this structure hashable */
-};
-
-struct my_struct *users = NULL;
-
-void add_user(struct my_struct *s) {
-    HASH_ADD_INT( users, id, s );    
-}
-
-
-
-
- -
-Example 2. Looking up an item in a hash. -
-
-struct my_struct *find_user(int user_id) {
-    struct my_struct *s;
-
-    HASH_FIND_INT( users, &user_id, s );  
-    return s;
-}
-
-
-
-
- -
-Example 3. Deleting an item from a hash. -
- -
-void delete_user(struct my_struct *user) {
-    HASH_DEL( users, user);  
-}
-
-
-
-
- - For more information and examples, please see the User Guide. - -
-
- -
- - - - - - diff --git a/Build/Docs/uthash/rss.png b/Build/Docs/uthash/rss.png deleted file mode 100644 index b3c949d22..000000000 Binary files a/Build/Docs/uthash/rss.png and /dev/null differ diff --git a/Build/Docs/uthash/styles.css b/Build/Docs/uthash/styles.css deleted file mode 100644 index 061172232..000000000 --- a/Build/Docs/uthash/styles.css +++ /dev/null @@ -1,141 +0,0 @@ -#banner { - /* font-size: x-large; */ - /* background: #ff00ff; */ - /* height: 100px; */ -} - -#topnav { - /* background-image: url(img/grad_topnav.png); */ - /* background-repeat: repeat-y; */ - /* background-color: #af00af; */ - /* height: 25px; */ - margin-top: 5px; - margin-bottom: 10px; - padding: 3px; - font-size: 9pt; - font-family: sans-serif; - /* border-style: solid; */ - /* border-width: 1px; */ -} - -#topnav a { - padding: 8px; -} - -h1,p { margin: 0; } /* non-0 margin on firefox */ - -#mid { - /* background-image: url(img/grad_blue.png); */ - background-repeat: repeat-y; - /* background-color: #ffddaa; */ - padding-top: 20px; - padding-top: 20px; - margin-bottom: 10px; -} - -#mid img { - padding-left: 10px; - vertical-align: middle; -} - -a img { - border: 0 -} - -.twitter-share-button { - float: right; -} - -.twitter-follow-button { - padding: 5px; -} - -#nav { - background-color: #fff8f1; - margin-left: 10px; - margin-top: 20px; - margin-right: 20px; - float: left; - padding: 10px; - border-style: solid; - border-width: 2px; - font-family: sans-serif; -} - - -#nav h2 { - font-weight: bold; - font-size: 10pt; -} - -#nav h3 { - /* font-weight: bold; */ - padding-left: 5px; - /* font-style: oblique; */ - font-family: sans-serif; - font-size: 7pt; -} - -#nav div { - font-size: 9pt; - padding-left: 15px; -} - -#main { - background: #ffffff; - margin-top: 20px; - margin-left: 170px; - padding-left: 20px; - height: 100%; -} - -#main h1 { - font-family: sans-serif; -} - -.listing { - margin: 20px; - font-family: sans-serif; - font-weight: bold; -} - -.code { - padding: 10px; - margin: 10px; - font-size: 8pt; - font-weight: normal; - background: #f3f3f3; - width: 100%; - border-style: solid; - border-width: 1px; -} - -#footer { - /* background: #00ffff; */ - margin-top: 5px; - font-size: small; - font-family: sans-serif; -} - -hr { - height: 0.04em; - background: black; - margin: 0 10% 0 0; -} - -#footer { - width: 90%; -} - -#footer img { - margin-right: 5px; - float: right; -} - -#footer #support { - float: right; -} - -body { - width: 80%; -} diff --git a/Build/Docs/uthash/userguide.txt b/Build/Docs/uthash/userguide.txt index 4d39abcd4..ae232d1d6 100644 --- a/Build/Docs/uthash/userguide.txt +++ b/Build/Docs/uthash/userguide.txt @@ -1,11 +1,11 @@ uthash User Guide ================= Troy D. Hanson, Arthur O'Dwyer -v2.0.2, March 2017 +v2.1.0, December 2018 To download uthash, follow this link back to the https://github.com/troydhanson/uthash[GitHub project page]. -Back to my https://troydhanson.github.io[other projects]. +Back to my https://troydhanson.github.io/[other projects]. A hash in C ----------- @@ -230,8 +230,8 @@ last parameter is a pointer to the structure being added. .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. +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 @@ -257,7 +257,7 @@ Otherwise we just modify the structure that already exists. HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ if (s==NULL) { - s = (struct my_struct*)malloc(sizeof(struct my_struct)); + s = (struct my_struct *)malloc(sizeof *s); s->id = user_id; HASH_ADD_INT( users, id, s ); /* id: name of key field */ } @@ -534,7 +534,7 @@ void add_user(int user_id, char *name) { HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ if (s==NULL) { - s = (struct my_struct*)malloc(sizeof(struct my_struct)); + s = (struct my_struct *)malloc(sizeof *s); s->id = user_id; HASH_ADD_INT( users, id, s ); /* id: name of key field */ } @@ -713,14 +713,13 @@ struct my_struct { int main(int argc, char *argv[]) { - const char **n, *names[] = { "joe", "bob", "betty", NULL }; + const char *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++; + for (int i = 0; names[i]; ++i) { + s = (struct my_struct *)malloc(sizeof *s); + strcpy(s->name, names[i]); + s->id = i; HASH_ADD_STR( users, name, s ); } @@ -760,14 +759,13 @@ struct my_struct { int main(int argc, char *argv[]) { - const char **n, *names[] = { "joe", "bob", "betty", NULL }; + const char *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++; + for (int i = 0; names[i]; ++i) { + s = (struct my_struct *)malloc(sizeof *s); + s->name = names[i]; + s->id = i; HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s ); } @@ -810,7 +808,7 @@ char *someaddr = NULL; int main() { el_t *d; - el_t *e = (el_t*)malloc(sizeof(el_t)); + el_t *e = (el_t *)malloc(sizeof *e); if (!e) return -1; e->key = (void*)someaddr; e->i = 1; @@ -861,8 +859,8 @@ typedef struct { 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 = (record_t *)malloc(sizeof *r); + memset(r, 0, sizeof *r); r->key.a = 'a'; r->key.b = 1; HASH_ADD(hh, records, key, sizeof(record_key_t), r); @@ -926,7 +924,7 @@ int main(int argc, char *argv[]) { int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ /* allocate and initialize our structure */ - msg = (msg_t*)malloc( sizeof(msg_t) + sizeof(beijing) ); + 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; @@ -943,7 +941,7 @@ int main(int argc, char *argv[]) { /* look it up to prove that it worked :-) */ msg=NULL; - lookup_key = (lookup_key_t*)malloc(sizeof(*lookup_key) + sizeof(beijing)); + 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)); @@ -968,6 +966,7 @@ by an `int` will normally have 3 "wasted" bytes of padding after the char, in order to make the `int` field start on a multiple-of-4 address (4 is the length of the int). +[[multifield_note]] .Calculating the length of a multi-field key: ******************************************************************************* To determine the key length when using a multi-field key, you must include any @@ -992,6 +991,10 @@ didn't zero-fill the structure, this padding would contain random values. The random values would lead to `HASH_FIND` failures; as two "identical" keys will appear to mismatch if there are any differences within their padding. +Alternatively, you can customize the global <> +and <> to ignore the padding in your key. +See <>. + [[multilevel]] Multi-level hash tables ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1072,7 +1075,7 @@ 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 use a different key; - each hash table may have its own sort order; - or you might simply use multiple hash tables for grouping purposes. E.g., you could have users in an `admin_users` and a `users` hash table. @@ -1082,19 +1085,19 @@ which it might be added. You can name them anything. E.g., UT_hash_handle hh1, hh2; -Items with alternative keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Items with multiple keys +~~~~~~~~~~~~~~~~~~~~~~~~ You might create a hash table keyed on an ID field, and another hash table keyed on username (if usernames are unique). You can add the same user structure to both hash tables (without duplication of the structure), allowing lookup of a user structure by their name or ID. The way to achieve this is to have a separate `UT_hash_handle` for each hash to which the structure may be added. -.A structure with two alternative keys +.A structure with two different keys ---------------------------------------------------------------------- struct my_struct { - int id; /* usual key */ - char username[10]; /* alternative key */ + int id; /* first key */ + char username[10]; /* second key */ UT_hash_handle hh1; /* handle for first hash table */ UT_hash_handle hh2; /* handle for second hash table */ }; @@ -1124,12 +1127,12 @@ always used with the `users_by_name` hash table). 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 */ + /* find user by ID in the "users_by_id" hash table */ i=1; HASH_FIND(hh1, users_by_id, &i, sizeof(int), s); if (s) printf("found id %d: %s\n", i, s->username); - /* lookup user by username in the "users_by_name" hash table */ + /* find user by username in the "users_by_name" hash table */ name = "thanson"; HASH_FIND(hh2, users_by_name, name, strlen(name), s); if (s) printf("found user %s: %d\n", name, s->id); @@ -1171,7 +1174,7 @@ 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). +(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) { @@ -1269,12 +1272,67 @@ items to the destination hash selectively. The two hash handles must differ. An example of using `HASH_SELECT` is included in `tests/test36.c`. +[[hash_keycompare]] +Specifying an alternate key comparison function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you call `HASH_FIND(hh, head, intfield, sizeof(int), out)`, uthash will +first call <>`(intfield, sizeof(int), hashvalue)` to +determine the bucket `b` in which to search, and then, for each element `elt` +of bucket `b`, uthash will evaluate +`elt->hh.hashv == hashvalue && elt.hh.keylen == sizeof(int) && HASH_KEYCMP(intfield, elt->hh.key, sizeof(int)) == 0`. +`HASH_KEYCMP` should return `0` to indicate that `elt` is a match and should be +returned, and any non-zero value to indicate that the search for a matching +element should continue. + +By default, uthash defines `HASH_KEYCMP` as an alias for `memcmp`. On platforms +that do not provide `memcmp`, you can substitute your own implementation. + +---------------------------------------------------------------------------- +#undef HASH_KEYCMP +#define HASH_KEYCMP(a,b,len) bcmp(a,b,len) +---------------------------------------------------------------------------- + +Another reason to substitute your own key comparison function is if your "key" is not +trivially comparable. In this case you will also need to substitute your own `HASH_FUNCTION`. + +---------------------------------------------------------------------------- +struct Key { + short s; + /* 2 bytes of padding */ + float f; +}; +/* do not compare the padding bytes; do not use memcmp on floats */ +unsigned key_hash(struct Key *s) { return s + (unsigned)f; } +bool key_equal(struct Key *a, struct Key *b) { return a.s == b.s && a.f == b.f; } + +#define HASH_FUNCTION(s,len,hashv) (hashv) = key_hash((struct Key *)s) +#define HASH_KEYCMP(a,b,len) (!key_equal((struct Key *)a, (struct Key *)b)) +---------------------------------------------------------------------------- + +Another reason to substitute your own key comparison function is to trade off +correctness for raw speed. During its linear search of a bucket, uthash always +compares the 32-bit `hashv` first, and calls `HASH_KEYCMP` only if the `hashv` +compares equal. This means that `HASH_KEYCMP` is called at least once per +successful find. Given a good hash function, we expect the `hashv` comparison to +produce a "false positive" equality only once in four billion times. Therefore, +we expect `HASH_KEYCMP` to produce `0` most of the time. If we expect many +successful finds, and our application doesn't mind the occasional false positive, +we might substitute a no-op comparison function: + +---------------------------------------------------------------------------- +#undef HASH_KEYCMP +#define HASH_KEYCMP(a,b,len) 0 /* occasionally wrong, but very fast */ +---------------------------------------------------------------------------- + +Note: The global equality-comparison function `HASH_KEYCMP` has no relationship +at all to the lessthan-comparison function passed as a parameter to `HASH_ADD_INORDER`. [[hash_functions]] Built-in hash functions ~~~~~~~~~~~~~~~~~~~~~~~ Internally, a hash function transforms a key into a bucket number. You don't -have to take any action to use the default hash function, currently Jenkin's. +have to take any action to use the default hash function, currently Jenkins. Some programs may benefit from using another of the built-in hash functions. There is a simple analysis utility included with uthash to help you determine @@ -1296,17 +1354,8 @@ below. E.g., |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, @@ -1531,6 +1580,31 @@ inhibited' flag remains in effect as long as the hash has items in it. Inhibited expansion may cause `HASH_FIND` to exhibit worse than constant-time performance. +Diagnostic hooks +^^^^^^^^^^^^^^^^ + +There are two "notification" hooks which get executed if uthash is +expanding buckets, or setting the 'bucket expansion inhibited' flag. +There is no need for the application to set these hooks or take action in +response to these events. They are mainly for diagnostic purposes. +Normally both of these hooks are undefined and thus compile away to nothing. + +The `uthash_expand_fyi` hook can be defined to execute code whenever +uthash performs a bucket expansion. + +---------------------------------------------------------------------------- +#undef uthash_expand_fyi +#define uthash_expand_fyi(tbl) printf("expanded to %u buckets\n", tbl->num_buckets) +---------------------------------------------------------------------------- + +The `uthash_noexpand_fyi` hook can be defined to execute code whenever +uthash sets the 'bucket expansion inhibited' flag. + +---------------------------------------------------------------------------- +#undef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) printf("warning: bucket expansion inhibited\n") +---------------------------------------------------------------------------- + Hooks ~~~~~ You don't need to use these hooks -- they are only here if you want to modify @@ -1545,8 +1619,8 @@ example, by passing `-Duthash_malloc=my_malloc` on the command line. Specifying alternate memory management functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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. +By default, uthash uses `malloc` and `free` to manage memory. +If your application uses its own custom allocator, uthash can use them too. ---------------------------------------------------------------------------- #include "uthash.h" @@ -1568,26 +1642,22 @@ convenience on embedded platforms that manage their own memory. Specifying alternate standard library functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uthash also uses `strlen` (in the `HASH_FIND_STR` convenience macro, for -example), `memcmp` (as the method of comparing keys for equality), and `memset` -(used only for zeroing memory). On platforms that do not provide these functions, -you can substitute your own implementations. +example) and `memset` (used only for zeroing memory). On platforms that do not +provide these functions, you can substitute your own implementations. ---------------------------------------------------------------------------- #undef uthash_bzero #define uthash_bzero(a,len) my_bzero(a,len) -#undef uthash_memcmp -#define uthash_memcmp(a,b,len) my_memcmp(a,b,len) - #undef uthash_strlen #define uthash_strlen(s) my_strlen(s) ---------------------------------------------------------------------------- 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. +If memory allocation fails (i.e., the `uthash_malloc` function returns `NULL`), +the default behavior is to terminate the process by calling `exit(-1)`. This +can be modified by re-defining the `uthash_fatal` macro. ---------------------------------------------------------------------------- #undef uthash_fatal @@ -1595,36 +1665,36 @@ be modified by re-defining the `uthash_fatal` macro. ---------------------------------------------------------------------------- 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. +place. Note that an allocation failure may leave allocated memory that cannot +be recovered. After `uthash_fatal`, the hash table object should be considered +unusable; it might not be safe even to run `HASH_CLEAR` on the hash table +when it is in this state. -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. +To enable "returning a failure" if memory cannot be allocated, define the +macro `HASH_NONFATAL_OOM` before including the `uthash.h` header file. In this +case, `uthash_fatal` is not used; instead, each allocation failure results in +a single call to `uthash_nonfatal_oom(elt)` where `elt` is the address of the +element whose insertion triggered the failure. The default behavior of +`uthash_nonfatal_oom` is a no-op. ---------------------------------------------------------------------------- -#undef uthash_expand_fyi -#define uthash_expand_fyi(tbl) printf("expanded to %d buckets\n", tbl->num_buckets) +#undef uthash_nonfatal_oom +#define uthash_nonfatal_oom(elt) perhaps_recover((element_t *) elt) ---------------------------------------------------------------------------- -Expansion-inhibition -++++++++++++++++++++ -This hook can be defined to code to execute in the event that uthash decides to -set the 'bucket expansion inhibited' flag. +Before the call to `uthash_nonfatal_oom`, the hash table is rolled back +to the state it was in prior to the problematic insertion; no memory is +leaked. It is safe to `throw` or `longjmp` out of the `uthash_nonfatal_oom` +handler. ----------------------------------------------------------------------------- -#undef uthash_noexpand_fyi -#define uthash_noexpand_fyi printf("warning: bucket expansion inhibited\n") ----------------------------------------------------------------------------- +The `elt` argument will be of the correct pointer-to-element type, unless +`uthash_nonfatal_oom` is invoked from `HASH_SELECT`, in which case it will +be of `void*` type and must be cast before using. In any case, `elt->hh.tbl` +will be `NULL`. + +Allocation failure is possible only when adding elements to the hash table +(including the `ADD`, `REPLACE`, and `SELECT` operations). +`uthash_free` is not allowed to fail. Debug mode ~~~~~~~~~~ @@ -1750,21 +1820,21 @@ than `hh`, or if your key's data type isn't `int` or `char[]`. |=============================================================================== |macro | arguments |HASH_ADD | (hh_name, head, keyfield_name, key_len, item_ptr) -|HASH_ADD_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, key_hash, item_ptr) +|HASH_ADD_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, hashv, item_ptr) |HASH_ADD_KEYPTR | (hh_name, head, key_ptr, key_len, item_ptr) -|HASH_ADD_KEYPTR_BYHASHVALUE | (hh_name, head, key_ptr, key_len, key_hash, item_ptr) +|HASH_ADD_KEYPTR_BYHASHVALUE | (hh_name, head, key_ptr, key_len, hashv, item_ptr) |HASH_ADD_INORDER | (hh_name, head, keyfield_name, key_len, item_ptr, cmp) -|HASH_ADD_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, key_hash, item_ptr, cmp) +|HASH_ADD_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, cmp) |HASH_ADD_KEYPTR_INORDER | (hh_name, head, key_ptr, key_len, item_ptr, cmp) -|HASH_ADD_KEYPTR_BYHASHVALUE_INORDER | (hh_name, head, key_ptr, key_len, key_hash, item_ptr, cmp) +|HASH_ADD_KEYPTR_BYHASHVALUE_INORDER | (hh_name, head, key_ptr, key_len, hashv, item_ptr, cmp) |HASH_REPLACE | (hh_name, head, keyfield_name, key_len, item_ptr, replaced_item_ptr) -|HASH_REPLACE_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, key_hash, item_ptr, replaced_item_ptr) +|HASH_REPLACE_BYHASHVALUE | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, replaced_item_ptr) |HASH_REPLACE_INORDER | (hh_name, head, keyfield_name, key_len, item_ptr, replaced_item_ptr, cmp) -|HASH_REPLACE_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, key_hash, item_ptr, replaced_item_ptr, cmp) +|HASH_REPLACE_BYHASHVALUE_INORDER | (hh_name, head, keyfield_name, key_len, hashv, item_ptr, replaced_item_ptr, cmp) |HASH_FIND | (hh_name, head, key_ptr, key_len, item_ptr) -|HASH_FIND_BYHASHVALUE | (hh_name, head, key_ptr, key_len, key_hash, item_ptr) +|HASH_FIND_BYHASHVALUE | (hh_name, head, key_ptr, key_len, hashv, item_ptr) |HASH_DELETE | (hh_name, head, item_ptr) -|HASH_VALUE | (key_ptr, key_len, key_hash) +|HASH_VALUE | (key_ptr, key_len, hashv) |HASH_SRT | (hh_name, head, cmp) |HASH_CNT | (hh_name, head) |HASH_CLEAR | (hh_name, head) @@ -1799,12 +1869,12 @@ keyfield_name:: 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). + multi-field key, see <>.) key_ptr:: for `HASH_FIND`, this is a pointer to the key to look up in the hash (since it's a pointer, you can't directly pass a literal value here). For `HASH_ADD_KEYPTR`, this is the address of the key of the item being added. -key_hash:: +hashv:: the hash value of the provided key. This is an input parameter for the `..._BYHASHVALUE` macros, and an output parameter for `HASH_VALUE`. Reusing a cached hash value can be a performance optimization if @@ -1823,9 +1893,9 @@ cmp:: 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 + a function or macro which accepts a single argument (a void pointer to a + structure, which needs to be cast to the appropriate structure type). The + function or macro should evaluate to a non-zero value if the structure should be "selected" for addition to the destination hash. // vim: set tw=80 wm=2 syntax=asciidoc: diff --git a/Build/Docs/uthash/utarray.txt b/Build/Docs/uthash/utarray.txt deleted file mode 100644 index 546f42420..000000000 --- a/Build/Docs/uthash/utarray.txt +++ /dev/null @@ -1,374 +0,0 @@ -utarray: dynamic array macros for C -=================================== -Troy D. Hanson -v2.0.2, March 2017 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -A set of general-purpose dynamic array macros for C structures are included with -uthash in `utarray.h`. To use these macros in your own C program, just -copy `utarray.h` into your source directory and use it in your programs. - - #include "utarray.h" - -The dynamic array supports basic operations such as push, pop, and erase on the -array elements. These array elements can be any simple datatype or structure. -The array <> are based loosely on the C++ STL vector methods. - -Internally the dynamic array contains a contiguous memory region into which -the elements are copied. This buffer is grown as needed using `realloc` to -accommodate all the data that is pushed into it. - -Download -~~~~~~~~ -To download the `utarray.h` header file, -follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file, -then look in the src/ sub-directory. - -BSD licensed -~~~~~~~~~~~~ -This software is made available under the -link:license.html[revised BSD license]. -It is free and open source. - -Platforms -~~~~~~~~~ -The 'utarray' macros have been tested on: - - * Linux, - * Mac OS X, - * Windows, using Visual Studio 2008 and Visual Studio 2010 - -Usage ------ - -Declaration -~~~~~~~~~~~ - -The array itself has the data type `UT_array`, regardless of the type of -elements to be stored in it. It is declared like, - - UT_array *nums; - -New and free -~~~~~~~~~~~~ -The next step is to create the array using `utarray_new`. Later when you're -done with the array, `utarray_free` will free it and all its elements. - -Push, pop, etc -~~~~~~~~~~~~~~ -The central features of the utarray involve putting elements into it, taking -them out, and iterating over them. There are several <> -to pick from that deal with either single elements or ranges of elements at a -time. In the examples below we will use only the push operation to insert -elements. - -Elements --------- - -Support for dynamic arrays of integers or strings is especially easy. These are -best shown by example: - -Integers -~~~~~~~~ -This example makes a utarray of integers, pushes 0-9 into it, then prints it. -Lastly it frees it. - -.Integer elements -------------------------------------------------------------------------------- -#include -#include "utarray.h" - -int main() { - UT_array *nums; - int i, *p; - - utarray_new(nums,&ut_int_icd); - for(i=0; i < 10; i++) utarray_push_back(nums,&i); - - for(p=(int*)utarray_front(nums); - p!=NULL; - p=(int*)utarray_next(nums,p)) { - printf("%d\n",*p); - } - - utarray_free(nums); - - return 0; -} -------------------------------------------------------------------------------- - -The second argument to `utarray_push_back` is always a 'pointer' to the type -(so a literal cannot be used). So for integers, it is an `int*`. - -Strings -~~~~~~~ -In this example we make a utarray of strings, push two strings into it, print -it and free it. - -.String elements -------------------------------------------------------------------------------- -#include -#include "utarray.h" - -int main() { - UT_array *strs; - char *s, **p; - - utarray_new(strs,&ut_str_icd); - - s = "hello"; utarray_push_back(strs, &s); - s = "world"; utarray_push_back(strs, &s); - p = NULL; - while ( (p=(char**)utarray_next(strs,p))) { - printf("%s\n",*p); - } - - utarray_free(strs); - - return 0; -} -------------------------------------------------------------------------------- - -In this example, since the element is a `char*`, we pass a pointer to it -(`char**`) as the second argument to `utarray_push_back`. Note that "push" makes -a copy of the source string and pushes that copy into the array. - -About UT_icd -~~~~~~~~~~~~ - -Arrays be made of any type of element, not just integers and strings. The -elements can be basic types or structures. Unless you're dealing with integers -and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need -to define a `UT_icd` helper structure. This structure contains everything that -utarray needs to initialize, copy or destruct elements. - - typedef struct { - size_t sz; - init_f *init; - ctor_f *copy; - dtor_f *dtor; - } UT_icd; - -The three function pointers `init`, `copy`, and `dtor` have these prototypes: - - typedef void (ctor_f)(void *dst, const void *src); - typedef void (dtor_f)(void *elt); - typedef void (init_f)(void *elt); - -The `sz` is just the size of the element being stored in the array. - -The `init` function will be invoked whenever utarray needs to initialize an -empty element. This only happens as a byproduct of `utarray_resize` or -`utarray_extend_back`. If `init` is `NULL`, it defaults to zero filling the -new element using memset. - -The `copy` function is used whenever an element is copied into the array. -It is invoked during `utarray_push_back`, `utarray_insert`, `utarray_inserta`, -or `utarray_concat`. If `copy` is `NULL`, it defaults to a bitwise copy using -memcpy. - -The `dtor` function is used to clean up an element that is being removed from -the array. It may be invoked due to `utarray_resize`, `utarray_pop_back`, -`utarray_erase`, `utarray_clear`, `utarray_done` or `utarray_free`. If the -elements need no cleanup upon destruction, `dtor` may be `NULL`. - -Scalar types -~~~~~~~~~~~~ - -The next example uses `UT_icd` with all its defaults to make a utarray of -`long` elements. This example pushes two longs, prints them, and frees the -array. - -.long elements -------------------------------------------------------------------------------- -#include -#include "utarray.h" - -UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; - -int main() { - UT_array *nums; - long l, *p; - utarray_new(nums, &long_icd); - - l=1; utarray_push_back(nums, &l); - l=2; utarray_push_back(nums, &l); - - p=NULL; - while( (p=(long*)utarray_next(nums,p))) printf("%ld\n", *p); - - utarray_free(nums); - return 0; -} -------------------------------------------------------------------------------- - -Structures -~~~~~~~~~~ - -Structures can be used as utarray elements. If the structure requires no -special effort to initialize, copy or destruct, we can use `UT_icd` with all -its defaults. This example shows a structure that consists of two integers. Here -we push two values, print them and free the array. - -.Structure (simple) -------------------------------------------------------------------------------- -#include -#include "utarray.h" - -typedef struct { - int a; - int b; -} intpair_t; - -UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; - -int main() { - - UT_array *pairs; - intpair_t ip, *p; - utarray_new(pairs,&intpair_icd); - - ip.a=1; ip.b=2; utarray_push_back(pairs, &ip); - ip.a=10; ip.b=20; utarray_push_back(pairs, &ip); - - for(p=(intpair_t*)utarray_front(pairs); - p!=NULL; - p=(intpair_t*)utarray_next(pairs,p)) { - printf("%d %d\n", p->a, p->b); - } - - utarray_free(pairs); - return 0; -} -------------------------------------------------------------------------------- - -The real utility of `UT_icd` is apparent when the elements of the utarray are -structures that require special work to initialize, copy or destruct. - -For example, when a structure contains pointers to related memory areas that -need to be copied when the structure is copied (and freed when the structure is -freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`. - -Here we take an example of a structure that contains an integer and a string. -When this element is copied (such as when an element is pushed into the array), -we want to "deep copy" the `s` pointer (so the original element and the new -element point to their own copies of `s`). When an element is destructed, we -want to "deep free" its copy of `s`. Lastly, this example is written to work -even if `s` has the value `NULL`. - -.Structure (complex) -------------------------------------------------------------------------------- -#include -#include -#include "utarray.h" - -typedef struct { - int a; - char *s; -} intchar_t; - -void intchar_copy(void *_dst, const void *_src) { - intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src; - dst->a = src->a; - dst->s = src->s ? strdup(src->s) : NULL; -} - -void intchar_dtor(void *_elt) { - intchar_t *elt = (intchar_t*)_elt; - if (elt->s) free(elt->s); -} - -UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; - -int main() { - UT_array *intchars; - intchar_t ic, *p; - utarray_new(intchars, &intchar_icd); - - ic.a=1; ic.s="hello"; utarray_push_back(intchars, &ic); - ic.a=2; ic.s="world"; utarray_push_back(intchars, &ic); - - p=NULL; - while( (p=(intchar_t*)utarray_next(intchars,p))) { - printf("%d %s\n", p->a, (p->s ? p->s : "null")); - } - - utarray_free(intchars); - return 0; -} - -------------------------------------------------------------------------------- - -[[operations]] -Reference ---------- -This table lists all the utarray operations. These are loosely based on the C++ -vector class. - -Operations -~~~~~~~~~~ - -[width="100%",cols="50 _b); - } - -4. `utarray_find` uses a binary search to locate an element having a certain value - according to the given comparison function. The utarray must be first sorted - using the same comparison function. An example of using `utarray_find` with - a utarray of strings is included in `tests/test61.c`. - -5. A 'pointer' to a particular element (obtained using `utarray_eltptr` or - `utarray_front`, `utarray_next`, `utarray_prev`, `utarray_back`) becomes invalid whenever - another element is inserted into the utarray. This is because the internal - memory management may need to `realloc` the element storage to a new address. - For this reason, it's usually better to refer to an element by its integer - 'index' in code whose duration may include element insertion. - -// vim: set nowrap syntax=asciidoc: - diff --git a/Build/Docs/uthash/uthash-mini.png b/Build/Docs/uthash/uthash-mini.png deleted file mode 100644 index 9536b2a78..000000000 Binary files a/Build/Docs/uthash/uthash-mini.png and /dev/null differ diff --git a/Build/Docs/uthash/uthash-mini.svg b/Build/Docs/uthash/uthash-mini.svg deleted file mode 100644 index ea2d0749d..000000000 --- a/Build/Docs/uthash/uthash-mini.svg +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - ut hash - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Build/Docs/uthash/uthash.png b/Build/Docs/uthash/uthash.png deleted file mode 100644 index 20df5a7d3..000000000 Binary files a/Build/Docs/uthash/uthash.png and /dev/null differ diff --git a/Build/Docs/uthash/utlist.txt b/Build/Docs/uthash/utlist.txt deleted file mode 100644 index 72765c47e..000000000 --- a/Build/Docs/uthash/utlist.txt +++ /dev/null @@ -1,317 +0,0 @@ -utlist: linked list macros for C structures -=========================================== -Troy D. Hanson -v2.0.2, March 2017 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -A set of general-purpose 'linked list' macros for C structures are included with -uthash in `utlist.h`. To use these macros in your own C program, just -copy `utlist.h` into your source directory and use it in your programs. - - #include "utlist.h" - -These macros support the basic linked list operations: adding and deleting -elements, sorting them and iterating over them. - -Download -~~~~~~~~ -To download the `utlist.h` header file, -follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file, -then look in the src/ sub-directory. - -BSD licensed -~~~~~~~~~~~~ -This software is made available under the -link:license.html[revised BSD license]. -It is free and open source. - -Platforms -~~~~~~~~~ -The 'utlist' macros have been tested on: - - * Linux, - * Mac OS X, and - * Windows, using Visual Studio 2008, Visual Studio 2010, or Cygwin/MinGW. - -Using utlist ------------- - -Types of lists -~~~~~~~~~~~~~~ -Three types of linked lists are supported: - -- *singly-linked* lists, -- *doubly-linked* lists, and -- *circular, doubly-linked* lists - -Efficiency -^^^^^^^^^^ -Prepending elements:: - Constant-time on all list types. -Appending:: - 'O(n)' on singly-linked lists; constant-time on doubly-linked list. - (The utlist implementation of the doubly-linked list keeps a tail pointer in - `head->prev` so that append can be done in constant time). -Deleting elements:: - 'O(n)' on singly-linked lists; constant-time on doubly-linked list. -Sorting:: - 'O(n log(n))' for all list types. -Insertion in order (for sorted lists):: - 'O(n)' for all list types. -Iteration, counting and searching:: - 'O(n)' for all list types. - -List elements -~~~~~~~~~~~~~ -You can use any structure with these macros, as long as the structure -contains a `next` pointer. If you want to make a doubly-linked list, -the element also needs to have a `prev` pointer. - - typedef struct element { - char *name; - struct element *prev; /* needed for a doubly-linked list only */ - struct element *next; /* needed for singly- or doubly-linked lists */ - } element; - -You can name your structure anything. In the example above it is called `element`. -Within a particular list, all elements must be of the same type. - -Flexible prev/next naming -^^^^^^^^^^^^^^^^^^^^^^^^^ -You can name your `prev` and `next` pointers something else. If you do, there is -a <> that work identically but take these names as -extra arguments. - -List head -~~~~~~~~~ -The list head is simply a pointer to your element structure. You can name it -anything. *It must be initialized to `NULL`*. - - element *head = NULL; - -List operations -~~~~~~~~~~~~~~~ -The lists support inserting or deleting elements, sorting the elements and -iterating over them. - -[width="100%",cols="10next`. - -The 'count' operation iterates over the list and increments a supplied counter. - -The parameters shown in the table above are explained here: - -head:: - The list head (a pointer to your list element structure). -add:: - A pointer to the list element structure you are adding to the list. -del:: - A pointer to the list element structure you are replacing or - deleting from the list. -elt:: - A pointer that will be assigned to each list element in succession (see - example) in the case of iteration macros; or, the output pointer from - the search macros. -ref:: - Reference element for prepend and append operations that will be - prepended before or appended after. - If `ref` is a pointer with value NULL, the new element will be appended to the - list for _PREPEND_ELEM() operations and prepended for _APPEND_ELEM() operations. - `ref` must be the name of a pointer variable and cannot be literally NULL, - use _PREPEND() and _APPEND() macro family instead. -like:: - An element pointer, having the same type as `elt`, for which the search macro - seeks a match (if found, the match is stored in `elt`). A match is determined - by the given `cmp` function. -cmp:: - pointer to comparison function which accepts two arguments-- these are - pointers to two element structures to be compared. The comparison function - must return an `int` that is negative, zero, or positive, which specifies - whether the first item should sort before, equal to, or after the second item, - respectively. (In other words, the same convention that is used by `strcmp`). - Note that under Visual Studio 2008 you may need to declare the two arguments - as `void *` and then cast them back to their actual types. -tmp:: - A pointer of the same type as `elt`. Used internally. Need not be initialized. -mbr:: - In the scalar search macro, the name of a member within the `elt` structure which - will be tested (using `==`) for equality with the value `val`. -val:: - In the scalar search macro, specifies the value of (of structure member - `field`) of the element being sought. -count:: - integer which will be set to the length of the list - -Example -~~~~~~~ -This example program reads names from a text file (one name per line), and -appends each name to a doubly-linked list. Then it sorts and prints them. - -.A doubly-linked list --------------------------------------------------------------------------------- -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(el *a, el *b) { - return strcmp(a->bname,b->bname); -} - -el *head = NULL; /* important- initialize to NULL! */ - -int main(int argc, char *argv[]) { - el *name, *elt, *tmp, etmp; - - char linebuf[BUFLEN]; - int count; - FILE *file; - - if ( (file = fopen( "test11.dat", "r" )) == NULL ) { - perror("can't open: "); - exit(-1); - } - - while (fgets(linebuf,BUFLEN,file) != NULL) { - if ( (name = (el*)malloc(sizeof(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); - DL_COUNT(head, elt, count); - printf("%d number of elements in list\n", count); - - memcpy(&etmp.bname, "WES\n", 5); - DL_SEARCH(head,elt,&etmp,namecmp); - if (elt) printf("found %s\n", elt->bname); - - /* now delete each element, use the safe iterator */ - DL_FOREACH_SAFE(head,elt,tmp) { - DL_DELETE(head,elt); - free(elt); - } - - fclose(file); - - return 0; -} --------------------------------------------------------------------------------- - -[[flex_names]] -Other names for prev and next -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If the `prev` and `next` fields are named something else, a separate group of -macros must be used. These work the same as the regular macros, but take the -field names as extra parameters. - -These "flexible field name" macros are shown below. They all end with "2". Each -operates the same as its counterpart without the 2, but they take the name of -the `prev` and `next` fields (as applicable) as trailing arguments. - -.Flexible field name macros - LL_SORT2(list, cmp, next); - DL_SORT2(list, cmp, prev, next); - CDL_SORT2(list, cmp, prev, next); - LL_PREPEND2(head, add, next); - LL_PREPEND_ELEM2(head, ref, add, next); - LL_APPEND_ELEM2(head, ref, add, next); - LL_REPLACE_ELEM(head, del, add, next); - LL_CONCAT2(head1, head2, next); - LL_APPEND2(head, add, next); - LL_DELETE2(head, del, next); - LL_FOREACH2(head, elt, next) {...} - LL_FOREACH_SAFE2(head, elt, tmp, next) {...} - LL_SEARCH_SCALAR2(head, elt, mbr, val, next); - LL_SEARCH2(head, elt, like, cmp, next); - LL_LOWER_BOUND2(head, elt, like, cmp, next); - LL_COUNT2(head, elt, count, next); - DL_PREPEND2(head, add, prev, next); - DL_PREPEND_ELEM2(head, ref, add, prev, next); - DL_APPEND_ELEM2(head, ref, add, prev, next); - DL_REPLACE_ELEM2(head, del, add, prev, next); - DL_CONCAT2(head1, head2, prev, next); - DL_APPEND2(head, add, prev, next); - DL_DELETE2(head, del, prev, next); - DL_FOREACH2(head, elt, next) {...} - DL_FOREACH_SAFE2(head, elt, tmp, next) {...} - DL_SEARCH_SCALAR2(head, elt, mbr, val, next); - DL_SEARCH2(head, elt, like, cmp, next); - DL_LOWER_BOUND2(head, elt, like, cmp, next); - DL_COUNT2(head, elt, count, next); - CDL_PREPEND2(head, add, prev, next); - CDL_PREPEND_ELEM2(head, ref, add, prev, next); - CDL_APPEND_ELEM2(head, ref, add, prev, next); - CDL_REPLACE_ELEM2(head, del, add, prev, next); - CDL_APPEND2(head, add, prev, next); - CDL_DELETE2(head, del, prev, next); - CDL_FOREACH2(head, elt, next) {...} - CDL_FOREACH_SAFE2(head, elt, tmp1, tmp2, prev, next) {...} - CDL_SEARCH_SCALAR2(head, elt, mbr, val, next); - CDL_SEARCH2(head, elt, like, cmp, next); - CDL_LOWER_BOUND2(head, elt, like, cmp, next); - CDL_COUNT2(head, elt, count, next); - -// vim: set tw=80 wm=2 syntax=asciidoc: - diff --git a/Build/Docs/uthash/utringbuffer.txt b/Build/Docs/uthash/utringbuffer.txt deleted file mode 100644 index eae99a748..000000000 --- a/Build/Docs/uthash/utringbuffer.txt +++ /dev/null @@ -1,374 +0,0 @@ -utringbuffer: dynamic ring-buffer macros for C -============================================== -Arthur O'Dwyer -v2.0.2, March 2017 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -The functions in `utringbuffer.h` are based on the general-purpose array macros -provided in `utarray.h`, so before reading this page you should read -link:utarray.html[that page] first. - -To use these macros in your own C program, copy both `utarray.h` and `utringbuffer.h` -into your source directory and use `utringbuffer.h` in your program. - - #include "utringbuffer.h" - -The provided <> are based loosely on the C++ STL vector methods. -The ring-buffer data type supports construction (with a specified capacity), -destruction, iteration, and push, but not pop; once the ring-buffer reaches full -capacity, pushing a new element automatically pops and destroys the oldest element. -The elements contained in the ring-buffer can be any simple datatype or structure. - -Internally the ring-buffer contains a pre-allocated memory region into which the -elements are copied, starting at position 0. When the ring-buffer reaches full -capacity, the next element to be pushed is pushed at position 0, overwriting the -oldest element, and the internal index representing the "start" of the ring-buffer -is incremented. A ring-buffer, once full, can never become un-full. - - -Download -~~~~~~~~ -To download the `utringbuffer.h` header file, -follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file, -then look in the src/ sub-directory. - -BSD licensed -~~~~~~~~~~~~ -This software is made available under the -link:license.html[revised BSD license]. -It is free and open source. - -Platforms -~~~~~~~~~ -The 'utringbuffer' macros have been tested on: - - * Linux, - * Mac OS X, - * Windows, using Visual Studio 2008 and Visual Studio 2010 - -Usage ------ - -Declaration -~~~~~~~~~~~ - -The ring-buffer itself has the data type `UT_ringbuffer`, regardless of the type of -elements to be stored in it. It is declared like, - - UT_ringbuffer *history; - -New and free -~~~~~~~~~~~~ -The next step is to create the ring-buffer using `utringbuffer_new`. Later when you're -done with the ring-buffer, `utringbuffer_free` will free it and all its elements. - -Push, etc -~~~~~~~~~ -The central features of the ring-buffer involve putting elements into it -and iterating over them. There are several <> -that deal with either single elements or ranges of elements at a -time. In the examples below we will use only the push operation to insert -elements. - -Elements --------- - -Support for dynamic arrays of integers or strings is especially easy. These are -best shown by example: - -Integers -~~~~~~~~ -This example makes a ring-buffer of integers, pushes 0-9 into it, then prints it -two different ways. Lastly it frees it. - -.Integer elements -------------------------------------------------------------------------------- -#include -#include "utringbuffer.h" - -int main() { - UT_ringbuffer *history; - int i, *p; - - utringbuffer_new(history, 7, &ut_int_icd); - for(i=0; i < 10; i++) utringbuffer_push_back(history, &i); - - for (p = (int*)utringbuffer_front(history); - p != NULL; - p = (int*)utringbuffer_next(history, p)) { - printf("%d\n", *p); /* prints "3 4 5 6 7 8 9" */ - } - - for (i=0; i < utringbuffer_len(history); i++) { - p = utringbuffer_eltptr(history, i); - printf("%d\n", *p); /* prints "3 4 5 6 7 8 9" */ - } - - utringbuffer_free(history); - - return 0; -} -------------------------------------------------------------------------------- - -The second argument to `utringbuffer_push_back` is always a 'pointer' to the type -(so a literal cannot be used). So for integers, it is an `int*`. - -Strings -~~~~~~~ -In this example we make a ring-buffer of strings, push two strings into it, print -it and free it. - -.String elements -------------------------------------------------------------------------------- -#include -#include "utringbuffer.h" - -int main() { - UT_ringbuffer *strs; - char *s, **p; - - utringbuffer_new(strs, 7, &ut_str_icd); - - s = "hello"; utringbuffer_push_back(strs, &s); - s = "world"; utringbuffer_push_back(strs, &s); - p = NULL; - while ( (p=(char**)utringbuffer_next(strs,p))) { - printf("%s\n",*p); - } - - utringbuffer_free(strs); - - return 0; -} -------------------------------------------------------------------------------- - -In this example, since the element is a `char*`, we pass a pointer to it -(`char**`) as the second argument to `utringbuffer_push_back`. Note that "push" makes -a copy of the source string and pushes that copy into the array. - -About UT_icd -~~~~~~~~~~~~ - -Arrays can be made of any type of element, not just integers and strings. The -elements can be basic types or structures. Unless you're dealing with integers -and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need -to define a `UT_icd` helper structure. This structure contains everything that -utringbuffer (or utarray) needs to initialize, copy or destruct elements. - - typedef struct { - size_t sz; - init_f *init; - ctor_f *copy; - dtor_f *dtor; - } UT_icd; - -The three function pointers `init`, `copy`, and `dtor` have these prototypes: - - typedef void (ctor_f)(void *dst, const void *src); - typedef void (dtor_f)(void *elt); - typedef void (init_f)(void *elt); - -The `sz` is just the size of the element being stored in the array. - -The `init` function is used by utarray but is never used by utringbuffer; -you may safely set it to any value you want. - -The `copy` function is used whenever an element is copied into the buffer. -It is invoked during `utringbuffer_push_back`. -If `copy` is `NULL`, it defaults to a bitwise copy using memcpy. - -The `dtor` function is used to clean up an element that is being removed from -the buffer. It may be invoked due to `utringbuffer_push_back` (on the oldest -element in the buffer), `utringbuffer_clear`, `utringbuffer_done`, or -`utringbuffer_free`. -If the elements need no cleanup upon destruction, `dtor` may be `NULL`. - -Scalar types -~~~~~~~~~~~~ - -The next example uses `UT_icd` with all its defaults to make a ring-buffer of -`long` elements. This example pushes two longs into a buffer of capacity 1, -prints the contents of the buffer (which is to say, the most recent value -pushed), and then frees the buffer. - -.long elements -------------------------------------------------------------------------------- -#include -#include "utringbuffer.h" - -UT_icd long_icd = {sizeof(long), NULL, NULL, NULL }; - -int main() { - UT_ringbuffer *nums; - long l, *p; - utringbuffer_new(nums, 1, &long_icd); - - l=1; utringbuffer_push_back(nums, &l); - l=2; utringbuffer_push_back(nums, &l); - - p=NULL; - while((p = (long*)utringbuffer_next(nums,p))) printf("%ld\n", *p); - - utringbuffer_free(nums); - return 0; -} -------------------------------------------------------------------------------- - -Structures -~~~~~~~~~~ - -Structures can be used as utringbuffer elements. If the structure requires no -special effort to initialize, copy or destruct, we can use `UT_icd` with all -its defaults. This example shows a structure that consists of two integers. Here -we push two values, print them and free the buffer. - -.Structure (simple) -------------------------------------------------------------------------------- -#include -#include "utringbuffer.h" - -typedef struct { - int a; - int b; -} intpair_t; - -UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL}; - -int main() { - - UT_ringbuffer *pairs; - intpair_t ip, *p; - utringbuffer_new(pairs, 7, &intpair_icd); - - ip.a=1; ip.b=2; utringbuffer_push_back(pairs, &ip); - ip.a=10; ip.b=20; utringbuffer_push_back(pairs, &ip); - - for(p=(intpair_t*)utringbuffer_front(pairs); - p!=NULL; - p=(intpair_t*)utringbuffer_next(pairs,p)) { - printf("%d %d\n", p->a, p->b); - } - - utringbuffer_free(pairs); - return 0; -} -------------------------------------------------------------------------------- - -The real utility of `UT_icd` is apparent when the elements stored in the -ring-buffer are structures that require special work to initialize, copy or -destruct. - -For example, when a structure contains pointers to related memory areas that -need to be copied when the structure is copied (and freed when the structure is -freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`. - -Here we take an example of a structure that contains an integer and a string. -When this element is copied (such as when an element is pushed), -we want to "deep copy" the `s` pointer (so the original element and the new -element point to their own copies of `s`). When an element is destructed, we -want to "deep free" its copy of `s`. Lastly, this example is written to work -even if `s` has the value `NULL`. - -.Structure (complex) -------------------------------------------------------------------------------- -#include -#include -#include "utringbuffer.h" - -typedef struct { - int a; - char *s; -} intchar_t; - -void intchar_copy(void *_dst, const void *_src) { - intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src; - dst->a = src->a; - dst->s = src->s ? strdup(src->s) : NULL; -} - -void intchar_dtor(void *_elt) { - intchar_t *elt = (intchar_t*)_elt; - free(elt->s); -} - -UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor}; - -int main() { - UT_ringbuffer *intchars; - intchar_t ic, *p; - utringbuffer_new(intchars, 2, &intchar_icd); - - ic.a=1; ic.s="hello"; utringbuffer_push_back(intchars, &ic); - ic.a=2; ic.s="world"; utringbuffer_push_back(intchars, &ic); - ic.a=3; ic.s="peace"; utringbuffer_push_back(intchars, &ic); - - p=NULL; - while( (p=(intchar_t*)utringbuffer_next(intchars,p))) { - printf("%d %s\n", p->a, (p->s ? p->s : "null")); - /* prints "2 world 3 peace" */ - } - - utringbuffer_free(intchars); - return 0; -} - -------------------------------------------------------------------------------- - -[[operations]] -Reference ---------- -This table lists all the utringbuffer operations. These are loosely based on the C++ -vector class. - -Operations -~~~~~~~~~~ - -[width="100%",cols="50 -v2.0.2, March 2017 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -A set of basic dynamic string macros for C programs are included with -uthash in `utstring.h`. To use these in your own C program, just copy -`utstring.h` into your source directory and use it in your programs. - - #include "utstring.h" - -The dynamic string supports operations such as inserting data, concatenation, -getting the length and content, substring search, and clear. It's ok to put -binary data into a utstring too. The string <> are -listed below. - -Some utstring operations are implemented as functions rather than macros. - -Download -~~~~~~~~ -To download the `utstring.h` header file, -follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file, -then look in the src/ sub-directory. - -BSD licensed -~~~~~~~~~~~~ -This software is made available under the -link:license.html[revised BSD license]. -It is free and open source. - -Platforms -~~~~~~~~~ -The 'utstring' macros have been tested on: - - * Linux, - * Windows, using Visual Studio 2008 and Visual Studio 2010 - -Usage ------ - -Declaration -~~~~~~~~~~~ - -The dynamic string itself has the data type `UT_string`. It is declared like, - - UT_string *str; - -New and free -~~~~~~~~~~~~ -The next step is to create the string using `utstring_new`. Later when you're -done with it, `utstring_free` will free it and all its content. - -Manipulation -~~~~~~~~~~~~ -The `utstring_printf` or `utstring_bincpy` operations insert (copy) data into -the string. To concatenate one utstring to another, use `utstring_concat`. To -clear the content of the string, use `utstring_clear`. The length of the string -is available from `utstring_len`, and its content from `utstring_body`. This -evaluates to a `char*`. The buffer it points to is always null-terminated. -So, it can be used directly with external functions that expect a string. -This automatic null terminator is not counted in the length of the string. - -Samples -~~~~~~~ - -These examples show how to use utstring. - -.Sample 1 -------------------------------------------------------------------------------- -#include -#include "utstring.h" - -int main() { - UT_string *s; - - utstring_new(s); - utstring_printf(s, "hello world!" ); - printf("%s\n", utstring_body(s)); - - utstring_free(s); - return 0; -} -------------------------------------------------------------------------------- - -The next example demonstrates that `utstring_printf` 'appends' to the string. -It also shows concatenation. - -.Sample 2 -------------------------------------------------------------------------------- -#include -#include "utstring.h" - -int main() { - UT_string *s, *t; - - utstring_new(s); - utstring_new(t); - - utstring_printf(s, "hello " ); - utstring_printf(s, "world " ); - - utstring_printf(t, "hi " ); - utstring_printf(t, "there " ); - - utstring_concat(s, t); - printf("length: %u\n", utstring_len(s)); - printf("%s\n", utstring_body(s)); - - utstring_free(s); - utstring_free(t); - return 0; -} -------------------------------------------------------------------------------- - -The next example shows how binary data can be inserted into the string. It also -clears the string and prints new data into it. - -.Sample 3 -------------------------------------------------------------------------------- -#include -#include "utstring.h" - -int main() { - UT_string *s; - char binary[] = "\xff\xff"; - - utstring_new(s); - utstring_bincpy(s, binary, sizeof(binary)); - printf("length is %u\n", utstring_len(s)); - - utstring_clear(s); - utstring_printf(s,"number %d", 10); - printf("%s\n", utstring_body(s)); - - utstring_free(s); - return 0; -} -------------------------------------------------------------------------------- - -[[operations]] -Reference ---------- -These are the utstring operations. - -Operations -~~~~~~~~~~ - -[width="100%",cols="50 - - - - uthash: a hash table for C structures - - - - - -
- uthash home > - BSD license -
- -
-
-
-
-Copyright (c) 2005-2017, Troy D. Hanson  http://troydhanson.github.com/uthash/
+Copyright (c) 2005-2018, Troy D. Hanson   https://troydhanson.github.com/uthash/
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -41,15 +18,4 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
- -
- - - - - diff --git a/src/uthash/utarray.h b/src/uthash/utarray.h index 7a253b200..dd8191f33 100644 --- a/src/uthash/utarray.h +++ b/src/uthash/utarray.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2008-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/uthash/uthash.h b/src/uthash/uthash.h index ba1079607..f568e1ce3 100644 --- a/src/uthash/uthash.h +++ b/src/uthash/uthash.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2003-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/uthash/uthash.url b/src/uthash/uthash.url index 9044eb2c7..2ee7d1985 100644 --- a/src/uthash/uthash.url +++ b/src/uthash/uthash.url @@ -1,2 +1,4 @@ [InternetShortcut] URL=https://troydhanson.github.io/uthash/index.html +IDList= +HotKey=0 diff --git a/src/uthash/utlist.h b/src/uthash/utlist.h index 5d8af6a3c..a03f9bab0 100644 --- a/src/uthash/utlist.h +++ b/src/uthash/utlist.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2007-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/uthash/utringbuffer.h b/src/uthash/utringbuffer.h index 5a1dc8154..ff537d964 100644 --- a/src/uthash/utringbuffer.h +++ b/src/uthash/utringbuffer.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2015-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/uthash/utstack.h b/src/uthash/utstack.h index 3b0c1a0df..2b74ecbdc 100644 --- a/src/uthash/utstack.h +++ b/src/uthash/utstack.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2018-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/uthash/utstring.h b/src/uthash/utstring.h index 14151b8e3..6f17e36eb 100644 --- a/src/uthash/utstring.h +++ b/src/uthash/utstring.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2008-2018, Troy D. Hanson https://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without