diff --git a/src/util/uthash/LICENSE b/src/util/uthash/LICENSE index ad8e16a..e75a243 100644 --- a/src/util/uthash/LICENSE +++ b/src/util/uthash/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2005-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2005-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/util/uthash/README.md b/src/util/uthash/README.md index 3adebca..a85c10d 100644 --- a/src/util/uthash/README.md +++ b/src/util/uthash/README.md @@ -1,6 +1,8 @@ +[![Build status](https://api.travis-ci.org/troydhanson/uthash.svg?branch=master)](https://travis-ci.org/troydhanson/uthash) + Documentation for uthash is available at: -http://troydhanson.github.com/uthash/ +https://troydhanson.github.com/uthash/ diff --git a/src/util/uthash/doc/ChangeLog.html b/src/util/uthash/doc/ChangeLog.html deleted file mode 100644 index b59128d..0000000 --- a/src/util/uthash/doc/ChangeLog.html +++ /dev/null @@ -1,1504 +0,0 @@ - - - - - -uthash ChangeLog - - - - - -
-
-
-

Click to return to the uthash home page.

-
-
-
-

Version 1.9.8.p2

-
-
    -
  • -

    -added LRU cache example in tests/lru_cache (thanks, Oliver Lorenz!) -

    -
  • -
  • -

    -fix LL_DELETE2 for VS2008 (thanks, Greg Davydouski!) -

    -
  • -
-
-
-
-

Version 1.9.8.p1

-
-
    -
  • -

    -fix missing argument in HASH_REPLACE_STR (thanks, Alex!) -

    -
  • -
  • -

    -bump version number in source files to match docs (thanks, John Crow!) -

    -
  • -
  • -

    -add HASH_OVERHEAD macro to get overhead size for hash table -

    -
  • -
-
-
-
-

Version 1.9.8 (2013-03-10)

-
-
    -
  • -

    -HASH_REPLACE now in uthash (thanks, Nick Vatamaniuc!) -

    -
  • -
  • -

    -fixed clang warnings (thanks wynnw!) -

    -
  • -
  • -

    -fixed utarray_insert when inserting past array end (thanks Rob Willett!) -

    -
  • -
  • -

    -you can now find uthash on GitHub -

    -
  • -
  • -

    -there’s a uthash Google Group -

    -
  • -
  • -

    -uthash has been downloaded 29,000+ times since 2006 on SourceForge -

    -
  • -
-
-
-
-

Version 1.9.7 (2012-10-09)

-
-
    -
  • -

    -utstring now supports substring search using utstring_find (thanks, Joe Wei!) -

    -
  • -
  • -

    -utlist now supports element prepend and replace (thanks, Zoltán Lajos Kis!) -

    -
  • -
  • -

    -utlist element prev/next fields can now have any names (thanks, Pawel S. Veselov!) -

    -
  • -
  • -

    -uthash cast quiets a clang warning (thanks, Roman Divacky and Baptiste Daroussin!) -

    -
  • -
  • -

    -uthash userguide example shows how to check key uniqueness (thanks, Richard Cook!) -

    -
  • -
  • -

    -uthash HASH_MUR compiles under MSVC++ 10 in C mode (thanks, Arun Kirthi Cherian!) -

    -
  • -
  • -

    -utstring_printf now supports format checking (thanks, Donald Carr!) -

    -
  • -
-
-
-
-

Version 1.9.6 (2012-04-28)

-
-
    -
  • -

    -add utarray_prev (thanks, Ben Hiett!) -

    -
  • -
  • -

    -add parens/casts for greater compatibility (thanks, Atis, Debasis Ganguly, and Steve McClellan!) -

    -
  • -
  • -

    -added ifndef to uthash_malloc and related hooks (thanks, Holger Machens!) -

    -
  • -
  • -

    -edit examples so they do not leak memory (thanks, 任晶磊!) -

    -
  • -
-
-
-
-

Version 1.9.5 (2011-11-16)

-
-
    -
  • -

    -added utarray_renew -

    -
  • -
  • -

    -fixed memory leak in uthash_clear when using Bloom filter (thanks, Jan Hättig!) -

    -
  • -
  • -

    -utarray now copies the UT_icd on array creation rather than storing a pointer -

    -
  • -
  • -

    -add parentheses to HASH_ADD to fix preprocessing of certain arguments (thanks, Aaron Rosen!) -

    -
  • -
  • -

    -more parenthesizations for greater macro argument flexibility -

    -
  • -
-
-
-
-

Version 1.9.4 (2011-06-05)

-
-
    -
  • -

    -uthash now supports MurmurHash v3 -

    -
  • -
  • -

    -utlist now includes concatenation macros (LL_CONCAT and DL_CONCAT) -

    -
  • -
  • -

    -utarray now supports binary search (utarray_find) -

    -
  • -
  • -

    -utstring now supports a new-or-clear-existing macro (utstring_renew) -

    -
  • -
  • -

    -documented technique for a multi-level hash table -

    -
  • -
  • -

    -clarified scope requirements for UT_icd in the utarray documentation -

    -
  • -
  • -

    -fixed termination when utstring_clear is followed by utstring_body -

    -
  • -
  • -

    -fixed utarray_inserta macro when used with complex arguments -

    -
  • -
  • -

    -on Visual Studio define missing type uint8_t -

    -
  • -
  • -

    -Debian/Ubuntu include uthash in the package uthash-dev. -

    -
  • -
  • -

    -uthash has been downloaded 16,211 times. -

    -
  • -
-

Thanks to Yu Feng, Richard Cook, Dino Ciuffetti, Chris Groer, and Arun Cherian -for feedback and fixes in this release!

-
-
-
-

Version 1.9.3 (2010-10-31)

-
-
    -
  • -

    -fix an ifdef for compatibility with Intel compiler (thanks, degski!) -

    -
  • -
  • -

    -fix HASH_ITER macro to satisfy C++ casting rules (thanks, Erik Bai!) -

    -
  • -
-
-
-
-

Version 1.9.2 (2010-10-04)

-
-
    -
  • -

    -new HASH_ITER macro for more convenient deletion-safe iteration -

    -
  • -
  • -

    -hashscan can now run on FreeBSD 8.1 and later (thanks, Markus Gebert!) -

    -
  • -
  • -

    -More parens to evaluate complex macro arguments properly (thanks, ngg!) -

    -
  • -
  • -

    -Add sz parameter to the uthash_free hook for platforms that do their own memory management. Hopefully this minor API change doesn’t cause too much breakage for people. (thanks, Niall Douglas!) -

    -
  • -
  • -

    -uthash has been downloaded 12,294 times -

    -
  • -
-
-
-
-

Version 1.9.1 (2010-05-15)

-
-
    -
  • -

    -Fix a redefinition warning when using uthash.h and utstring.h together -

    -
  • -
  • -

    -Fix a bug in utstring_init -

    -
  • -
  • -

    -Added HASH_FIND_PTR and HASH_ADD_PTR (thanks, Niall Douglas!) -

    -
  • -
-
-
-
-

Version 1.9 (2010-03-31)

-
-
    -
  • -

    -uthash now supports Visual Studio 2008 and 2010 in C or C++ code! -

    -
  • -
  • -

    -new headers utarray.h and utstring.h - are now included. These implement dynamic arrays and strings using macros -

    -
  • -
  • -

    -utlist.h now has deletion-safe iterators and search macros -

    -
  • -
  • -

    -the test suite now runs under Visual Studio (thanks again degski!) -

    -
  • -
  • -

    -special thanks for suggesting utarray and utlist features to Charalampos P.! -

    -
  • -
  • -

    -uthash has been downloaded 9,616 times -

    -
  • -
-
-
-
-

Version 1.8 (2009-09-08)

-
-
    -
  • -

    -Added the hashscan utility that can report on the size and quality of - hash tables in a running process (Linux-only) -

    -
  • -
  • -

    -Added Bloom filter support. This has the potential to speed up certain - types of programs that look up non-existant keys in sufficient numbers. -

    -
  • -
  • -

    -Restored the MurmurHash, which can once again be used, if an additional - symbol is defined. This is a "safety" by which the user declares they - understand that -fno-strict-aliasing flag must be used if they are - using MurmurHash under gcc with optimization. -

    -
  • -
  • -

    -Unified the bucket/table malloc hooks; now there is only one malloc hook -

    -
  • -
  • -

    -Re-organized the manual into a main section and advanced topics section -

    -
  • -
  • -

    -Fixed a bug in utlist.h where sorting a singly-linked list threw a - compile-time error. -

    -
  • -
  • -

    -Fixed a bug in utlist.h where a doubly-linked list that is sorted - did not maintain the special head->prev pointer back to the list tail. -

    -
  • -
-
-
-
-

Version 1.7 (2009-06-11)

-
-
    -
  • -

    -The MurmurHash has been removed, and Jenkin’s hash is once again the default. - While MurmurHash performed well, it’s unsafe with regard to the strict - aliasing rule. This results in incorrect code when compiled with optimization. - It’s not possible to enable -fno-strict-aliasing from within a header file. -

    -
  • -
  • -

    -The linked list macros in utlist.h now comply with the strict-aliasing - rule so they generate correct code under high optimization levels (O2 or O3). - The use of the __typeof__ extension, which was originally a GNU extension, - may reduce portability to other compilers that do not support this extension. - This extension is used in the singly-linked list macros and the sort macros. -

    -
  • -
-
-
-
-

Version 1.6 (2009-05-08)

-
-

Special thanks to Alfred Heisner for contributing several enhancements:

-
    -
  • -

    -Support for two new hash functions: -

    -
      -
    • -

      -the Paul Hsieh hash function (HASH_SFH) -

      -
    • -
    • -

      -Austin Appleby’s MurmurHash function (HASH_MUR) -

      -
    • -
    -
  • -
  • -

    -Because of its excellent performance, MurmurHash is now the default hash function. -

    -
  • -
  • -

    -keystats now has much better elapsed time accuracy under Cygwin and MinGW -

    -
  • -
  • -

    -fixed casting in HASH_FNV, HASH_SAX and HASH_OAT for non-char keys -

    -
  • -
-

This release also includes:

-
    -
  • -

    -a new HASH_CLEAR operation clears a hash table in one step. -

    -
  • -
  • -

    -a new HASH_SELECT operation inserts those elements from one hash that - satisfy a given condition into another hash. The selected items have - dual presence in both hash tables. For example a game could select the - visible polygons from a hash of all polygons. -

    -
  • -
  • -

    -fixed a compile-time error which occurred if the final argument to - HASH_ADD_KEYPTR was a pointer to an array member like &a[i] -

    -
  • -
  • -

    -added another test script tests/all_funcs which executes the test suite - using every supported hash function -

    -
  • -
-

And lastly,

-
    -
  • -

    -a new, separate header called utlist.h is included which - provides linked list macros for C structures, similar in style to the - uthash macros -

    -
  • -
-
-
-
-

Version 1.5 (2009-02-19)

-
-
    -
  • -

    -now thread-safe for concurrent readers -

    -
  • -
  • -

    -use scratch variables on stack rather than in table (thanks, Petter Arvidsson!). - This change made HASH_FIND about 13% faster and enabled reader concurrency. -

    -
  • -
  • -

    -made BSD license terms even more permissive -

    -
  • -
  • -

    -added PDF version of User Guide -

    -
  • -
  • -

    -added update news -(RSS) - -

    -
  • -
-
-
-
-

Version 1.4 (2008-09-23)

-
-
    -
  • -

    -Add HASH_COUNT for counting items in the hash -

    -
  • -
  • -

    -Compatibility with C++. Satisfy additional casting requirements. - Also in the tests/ directory, running make cplusplus now compiles - all the test programs with the C++ compiler. -

    -
  • -
  • -

    -Eliminate elmt pointer from the UT_hash_handle. Calculate elmt - from hash handle address by subtracting hho (hash handle offset). -

    -
  • -
  • -

    -Contributed by L.S.Chin: - Cast void* to char* before pointer arithmetic to suppress compiler - warnings. We assume compilers abide to C standards which impose - requirement that sizeof(void*) == sizeof(char*). -

    -
  • -
  • -

    -Return meaningful exit status from do_tests per Tiago Cunha, - so that package manager-based install can verify tests are successful -

    -
  • -
-
-
-
-

Version 1.3 (2008-07-27)

-
-
    -
  • -

    -use integer-only math-- no floating point! Support FPU-less CPU’s. -

    -
  • -
  • -

    -eliminate hash_q metric, which measured the fraction of items with - non-ideal chain positions. We only need to know if this fraction - is below 0.5. This is now determined using fast bitwise tests. -

    -
  • -
  • -

    -when an item is added to the hash, calculate the key’s hash value - upfront and store it, instead of recomputing it as needed. This hashv - is stored in the hash handle. Potentially major speed benefit for - bucket expansion algorithm. Deleting is marginally improved too. -

    -
  • -
  • -

    -fixed a minor bug in the calculation of the max ideal chain length; - line 446 in v1.2 erroneously calculated a/b*2 instead of a/(b*2). - The effect of this bug was that bucket expansion could occur more - readily because the per-bucket max chain length multiplier factor - (which delays bucket expansion when certain buckets are overused) - was set to a lower, expansion-favoring value than intended. -

    -
  • -
  • -

    -improved source commenting and improved variable names in structures -

    -
  • -
  • -

    -remove HASH_JSW. Lengthy random number array made code less readable -

    -
  • -
  • -

    -add HASH_SRT(hh,hash,cmp) as a generalized HASH_SORT(hash,cmp). - It was an omission in uthash 1.2 that there was no sort macro for - hash handles with names other than hh. -

    -
  • -
  • -

    -Corrected HASH_FSCK so it works with any name for the hash handle. -

    -
  • -
  • -

    -behave properly in pathological HASH_DEL(a,a) case where the same - variable references the head and the deletee (advancing the head - then loses the correct reference to the deletee); fix by using - scratch area in the hash table to store deletee hash handle. -

    -
  • -
  • -

    -made tests runnable on MinGW -

    -
  • -
  • -

    -3000+ downloads since uthash-1.0 -

    -
  • -
-
-
-
-

Version 1.2 (2006-11-22)

-
-
    -
  • -

    -new HASH_SORT macro -

    -
  • -
  • -

    -Cygwin support -

    -
  • -
  • -

    -User Guide now features a clickable Table of Contents. - (The technique for generating the TOC on the browser was contributed - back to the AsciiDoc project and incorporated into AsciiDoc v8.1.0). -

    -
  • -
-
-
-
-

Version 1.1 (2006-06-28)

-
-
    -
  • -

    -uthash-1.1 released -

    -
  • -
  • -

    -supports several built-in user-selectable hash functions -

    -
  • -
  • -

    -new keystats utility quantifies performance of hash functions -

    -
  • -
-
-
-
-

Version 1.0 (2006-06-02)

-
-
    -
  • -

    -Initial release -

    -
  • -
-
-
-
-

- - - diff --git a/src/util/uthash/doc/ChangeLog.txt b/src/util/uthash/doc/ChangeLog.txt deleted file mode 100644 index 0807da8..0000000 --- a/src/util/uthash/doc/ChangeLog.txt +++ /dev/null @@ -1,230 +0,0 @@ -uthash ChangeLog -================ - -Click to return to the link:index.html[uthash home page]. - -Version 1.9.8.p2 ----------------- -* added LRU cache example in `tests/lru_cache` (thanks, Oliver Lorenz!) -* fix LL_DELETE2 for VS2008 (thanks, Greg Davydouski!) - -Version 1.9.8.p1 ----------------- -* fix missing argument in `HASH_REPLACE_STR` (thanks, Alex!) -* bump version number in source files to match docs (thanks, John Crow!) -* add `HASH_OVERHEAD` macro to get overhead size for hash table - -Version 1.9.8 (2013-03-10) --------------------------- -* `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!) -* fixed clang warnings (thanks wynnw!) -* fixed `utarray_insert` when inserting past array end (thanks Rob Willett!) -* you can now find http://troydhanson.github.com/uthash/[uthash on GitHub] -* there's a https://groups.google.com/d/forum/uthash[uthash Google Group] -* uthash has been downloaded 29,000+ times since 2006 on SourceForge - -Version 1.9.7 (2012-10-09) --------------------------- -* utstring now supports substring search using `utstring_find` (thanks, Joe Wei!) -* utlist now supports element 'prepend' and 'replace' (thanks, Zoltán Lajos Kis!) -* utlist element prev/next fields can now have any names (thanks, Pawel S. Veselov!) -* uthash cast quiets a clang warning (thanks, Roman Divacky and Baptiste Daroussin!) -* uthash userguide example shows how to check key uniqueness (thanks, Richard Cook!) -* uthash HASH_MUR compiles under MSVC++ 10 in C mode (thanks, Arun Kirthi Cherian!) -* `utstring_printf` now supports format checking (thanks, Donald Carr!) - -Version 1.9.6 (2012-04-28) --------------------------- -* add utarray_prev (thanks, Ben Hiett!) -* add parens/casts for greater compatibility (thanks, Atis, Debasis Ganguly, and Steve McClellan!) -* added ifndef to uthash_malloc and related hooks (thanks, Holger Machens!) -* edit examples so they do not leak memory (thanks, 任晶磊!) - -Version 1.9.5 (2011-11-16) --------------------------- -* added `utarray_renew` -* fixed memory leak in `uthash_clear` when using Bloom filter (thanks, Jan Hättig!) -* utarray now copies the UT_icd on array creation rather than storing a pointer -* add parentheses to `HASH_ADD` to fix preprocessing of certain arguments (thanks, Aaron Rosen!) -* more parenthesizations for greater macro argument flexibility - -Version 1.9.4 (2011-06-05) --------------------------- -* uthash now supports MurmurHash v3 -* utlist now includes concatenation macros (`LL_CONCAT` and `DL_CONCAT`) -* utarray now supports binary search (`utarray_find`) -* utstring now supports a new-or-clear-existing macro (`utstring_renew`) -* documented technique for a multi-level hash table -* clarified scope requirements for `UT_icd` in the utarray documentation -* fixed termination when `utstring_clear` is followed by `utstring_body` -* fixed utarray_inserta macro when used with complex arguments -* on Visual Studio define missing type `uint8_t` -* Debian/Ubuntu include uthash in the package `uthash-dev`. -* uthash has been downloaded 16,211 times. - -Thanks to Yu Feng, Richard Cook, Dino Ciuffetti, Chris Groer, and Arun Cherian -for feedback and fixes in this release! - -Version 1.9.3 (2010-10-31) --------------------------- -* fix an `ifdef` for compatibility with Intel compiler (thanks, degski!) -* fix `HASH_ITER` macro to satisfy C++ casting rules (thanks, Erik Bai!) - -Version 1.9.2 (2010-10-04) --------------------------- -* new `HASH_ITER` macro for more convenient deletion-safe iteration -* `hashscan` can now run on FreeBSD 8.1 and later (thanks, Markus Gebert!) -* More parens to evaluate complex macro arguments properly (thanks, ngg!) -* Add sz parameter to the `uthash_free` hook for platforms that do their own memory management. Hopefully this minor API change doesn't cause too much breakage for people. (thanks, Niall Douglas!) -* uthash has been downloaded 12,294 times - -Version 1.9.1 (2010-05-15) --------------------------- -* Fix a redefinition warning when using `uthash.h` and `utstring.h` together -* Fix a bug in `utstring_init` -* Added `HASH_FIND_PTR` and `HASH_ADD_PTR` (thanks, Niall Douglas!) - -Version 1.9 (2010-03-31) --------------------------- -* uthash now supports Visual Studio 2008 and 2010 in C or C++ code! -* new headers link:utarray.html[utarray.h] and link:utstring.html[utstring.h] - are now included. These implement dynamic arrays and strings using macros -* link:utlist.html[utlist.h] now has deletion-safe iterators and search macros -* the test suite now runs under Visual Studio (thanks again degski!) -* special thanks for suggesting utarray and utlist features to Charalampos P.! -* uthash has been downloaded 9,616 times - -Version 1.8 (2009-09-08) --------------------------- -* Added the `hashscan` utility that can report on the size and quality of - hash tables in a running process (Linux-only) -* Added Bloom filter support. This has the potential to speed up certain - types of programs that look up non-existant keys in sufficient numbers. -* Restored the MurmurHash, which can once again be used, if an additional - symbol is defined. This is a "safety" by which the user declares they - understand that `-fno-strict-aliasing` flag must be used if they are - using MurmurHash under gcc with optimization. -* Unified the bucket/table malloc hooks; now there is only one malloc hook -* Re-organized the manual into a main section and advanced topics section -* Fixed a bug in `utlist.h` where sorting a singly-linked list threw a - compile-time error. -* Fixed a bug in `utlist.h` where a doubly-linked list that is sorted - did not maintain the special `head->prev` pointer back to the list tail. - -Version 1.7 (2009-06-11) --------------------------- -* The MurmurHash has been removed, and Jenkin's hash is once again the default. - While MurmurHash performed well, it's unsafe with regard to the strict - aliasing rule. This results in incorrect code when compiled with optimization. - It's not possible to enable `-fno-strict-aliasing` from within a header file. -* The linked list macros in `utlist.h` now comply with the strict-aliasing - rule so they generate correct code under high optimization levels (O2 or O3). - The use of the `__typeof__` extension, which was originally a GNU extension, - may reduce portability to other compilers that do not support this extension. - This extension is used in the singly-linked list macros and the sort macros. - -Version 1.6 (2009-05-08) --------------------------- -Special thanks to Alfred Heisner for contributing several enhancements: - -* Support for two new hash functions: - - the Paul Hsieh hash function (`HASH_SFH`) - - Austin Appleby's MurmurHash function (`HASH_MUR`) -* Because of its excellent performance, MurmurHash is now the default hash function. -* `keystats` now has much better elapsed time accuracy under Cygwin and MinGW -* fixed casting in `HASH_FNV`, `HASH_SAX` and `HASH_OAT` for non-char keys - -This release also includes: - -* a new `HASH_CLEAR` operation clears a hash table in one step. -* a new `HASH_SELECT` operation inserts those elements from one hash that - satisfy a given condition into another hash. The selected items have - dual presence in both hash tables. For example a game could select the - visible polygons from a hash of all polygons. -* fixed a compile-time error which occurred if the final argument to - `HASH_ADD_KEYPTR` was a pointer to an array member like `&a[i]` -* added another test script `tests/all_funcs` which executes the test suite - using every supported hash function - -And lastly, - -* a new, separate header called link:utlist.html[utlist.h] is included which - provides 'linked list macros' for C structures, similar in style to the - uthash macros - -Version 1.5 (2009-02-19) --------------------------- -* now thread-safe for concurrent readers -* use scratch variables on stack rather than in table (thanks, Petter Arvidsson!). - This change made HASH_FIND about 13% faster and enabled reader concurrency. -* made link:license.html[BSD license] terms even more permissive -* added link:userguide.pdf[PDF version] of User Guide -* added http://troydhanson.wordpress.com/feed/[update news] image:rss.png[(RSS)] - -Version 1.4 (2008-09-23) --------------------------- -* Add `HASH_COUNT` for counting items in the hash -* Compatibility with C\+\+. Satisfy additional casting requirements. - Also in the `tests/` directory, running `make cplusplus` now compiles - all the test programs with the C++ compiler. -* Eliminate `elmt` pointer from the UT_hash_handle. Calculate elmt - from hash handle address by subtracting `hho` (hash handle offset). -* Contributed by L.S.Chin: - Cast `void*` to char* before pointer arithmetic to suppress compiler - warnings. We assume compilers abide to C standards which impose - requirement that `sizeof(void*) == sizeof(char*)`. -* Return meaningful exit status from do_tests per Tiago Cunha, - so that package manager-based install can verify tests are successful - - -Version 1.3 (2008-07-27) ------------------------- -* use integer-only math-- no floating point! Support FPU-less CPU's. -* eliminate `hash_q` metric, which measured the fraction of items with - non-ideal chain positions. We only need to know if this fraction - is below 0.5. This is now determined using fast bitwise tests. -* when an item is added to the hash, calculate the key's hash value - upfront and store it, instead of recomputing it as needed. This hashv - is stored in the hash handle. Potentially major speed benefit for - bucket expansion algorithm. Deleting is marginally improved too. -* fixed a minor bug in the calculation of the max ideal chain length; - line 446 in v1.2 erroneously calculated a/b*2 instead of a/(b*2). - The effect of this bug was that bucket expansion could occur more - readily because the per-bucket 'max chain length multiplier factor' - (which delays bucket expansion when certain buckets are overused) - was set to a lower, expansion-favoring value than intended. -* improved source commenting and improved variable names in structures -* remove `HASH_JSW`. Lengthy random number array made code less readable -* add `HASH_SRT(hh,hash,cmp)` as a generalized `HASH_SORT(hash,cmp)`. - It was an omission in uthash 1.2 that there was no sort macro for - hash handles with names other than hh. -* Corrected `HASH_FSCK` so it works with any name for the hash handle. -* behave properly in pathological `HASH_DEL(a,a)` case where the same - variable references the head and the deletee (advancing the head - then loses the correct reference to the deletee); fix by using - scratch area in the hash table to store deletee hash handle. -* made tests runnable on MinGW -* 3000+ downloads since uthash-1.0 - - -Version 1.2 (2006-11-22) ------------------------- -* new `HASH_SORT` macro -* Cygwin support -* User Guide now features a clickable Table of Contents. - (The technique for generating the TOC on the browser was contributed - back to the AsciiDoc project and incorporated into AsciiDoc v8.1.0). - - -Version 1.1 (2006-06-28) ------------------------- -* uthash-1.1 released -* supports several built-in user-selectable hash functions -* new keystats utility quantifies performance of hash functions - - -Version 1.0 (2006-06-02) ------------------------- -* Initial release - -// vim: set syntax=asciidoc: diff --git a/src/util/uthash/doc/banner.png b/src/util/uthash/doc/banner.png deleted file mode 100644 index de4f310..0000000 Binary files a/src/util/uthash/doc/banner.png and /dev/null differ diff --git a/src/util/uthash/doc/banner.svg b/src/util/uthash/doc/banner.svg deleted file mode 100644 index f3143f1..0000000 --- a/src/util/uthash/doc/banner.svg +++ /dev/null @@ -1,451 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - ut hash - - - - - - - - - - - - - - - - - - - - - - - a hash tablefor C structures - - - diff --git a/src/util/uthash/doc/google315d692c9c632ed0.html b/src/util/uthash/doc/google315d692c9c632ed0.html deleted file mode 100644 index c79038e..0000000 --- a/src/util/uthash/doc/google315d692c9c632ed0.html +++ /dev/null @@ -1 +0,0 @@ -google-site-verification: google315d692c9c632ed0.html \ No newline at end of file diff --git a/src/util/uthash/doc/index.html b/src/util/uthash/doc/index.html deleted file mode 100644 index fca79bf..0000000 --- a/src/util/uthash/doc/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - uthash: a hash table for C structures - - - - - -
- GitHub page > - uthash home - -Tweet - -
- -
-
- - - -
- 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/src/util/uthash/doc/license.html b/src/util/uthash/doc/license.html deleted file mode 100644 index c8b63c8..0000000 --- a/src/util/uthash/doc/license.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - uthash: a hash table for C structures - - - - - -
- uthash home > - BSD license -
- -
-
-
-
-Copyright (c) 2005-2013, Troy D. Hanson  http://troydhanson.github.com/uthash/
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
- -
- - - - - - diff --git a/src/util/uthash/doc/rss.png b/src/util/uthash/doc/rss.png deleted file mode 100644 index b3c949d..0000000 Binary files a/src/util/uthash/doc/rss.png and /dev/null differ diff --git a/src/util/uthash/doc/styles.css b/src/util/uthash/doc/styles.css deleted file mode 100644 index 0611722..0000000 --- a/src/util/uthash/doc/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/src/util/uthash/doc/todo.txt b/src/util/uthash/doc/todo.txt deleted file mode 100644 index 73c9f4f..0000000 --- a/src/util/uthash/doc/todo.txt +++ /dev/null @@ -1,4 +0,0 @@ -1. to minimize TLB churn, store hashv locally in chain -2. to reduce memory, make the insertion-order pointers optional -3. to improve optimization use function generators rather than void* -4. to reduce memory, eliminate hash handle, bookkeep in head object diff --git a/src/util/uthash/doc/userguide.html b/src/util/uthash/doc/userguide.html deleted file mode 100644 index 5eb823d..0000000 --- a/src/util/uthash/doc/userguide.html +++ /dev/null @@ -1,3034 +0,0 @@ - - - - - -uthash User Guide - - - - - -
-
-
-

To download uthash, follow this link back to the -GitHub project page.

-
-
-
-

A hash in C

-
-

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, hashes or "dictionaries" 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/replace -

    -
  2. -
  3. -

    -find -

    -
  4. -
  5. -

    -delete -

    -
  6. -
  7. -

    -count -

    -
  8. -
  9. -

    -iterate -

    -
  10. -
  11. -

    -sort -

    -
  12. -
  13. -

    -select -

    -
  14. -
-
-
-

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 -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 -

    -
  • -
-

Windows users: as of 2013 it’s been a while since I had the environment to test -uthash under Visual Studio. If someone wants to run the unit tests under the latest -Visual Studio and confirm that its still clean, that’d be appreciated.

-
-

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 -revised BSD license. -It is free and open source.

-
-
-

Download uthash

-

Follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file.

-
-
-

Getting help

-

I encourage people to use the public Google Group to ask questions: uthash@googlegroups.com

- -

If you are experienced with uthash and like to answer questions, please join the -group and chime in when someone asks a question. That would be a great help!

-
-

Contacting the author

-

You can email me at tdh@tkhanson.net or message @troydhanson on Twitter. I -can’t always answer my email, and when I do, it’s sometimes weeks later. Sorry!

-
-
-
-

Contributing

-

If you add a new feature or fix something in uthash or in the extras, please -make a pull request on Github. For anything other than a trivial change, include -a unit test and documentation if you possibly can. (And don’t be discouraged if -it takes weeks or even months for me to merge it. Sorry, my life is busy!) Thanks!

-
-
-

Extras included

-

Three "extras" come with uthash. These provide lists, dynamic arrays and -strings:

-
    -
  • -

    -utlist.h provides linked list macros for C structures. -

    -
  • -
  • -

    -utarray.h implements dynamic arrays using macros. -

    -
  • -
  • -

    -utstring.h implements a basic dynamic string. -

    -
  • -
-

There’s also a small LRU cache API, based on uthash, in tests/lru_cache.

-
-

Other software

-

Other open-source software by the author is listed at http://tkhanson.net.

-
-
-
-

News

-

The author has a blog for software updates - -(RSS) -. You can also follow @troydhanson on Twitter for updates.

-
-
-

Who’s using it?

-

Uthash was downloaded around 30,000 times between 2006-2013 then transitioned to -GitHub. It’s been incorporated into commercial software, academic research, and -into other open-source software. It has also been added to the native package -repositories for a number of Unix-y distros.

-

When uthash was written, there were fewer options for doing generic hash tables -in C than exist today. There are faster hash tables, more memory-efficient hash -tables, with very different API’s today. But, like driving a minivan, uthash is -convenient, and gets the job done without drawing a lot of attention to itself.

-
-
-
-
-

Your structure

-
-

In uthash, a hash table is comprised of structures. Each structure represents a -key-value association. One or more of the structure fields constitute the key. -The structure pointer itself is the value.

-
-
Defining a structure that can be hashed
-
-
#include "uthash.h"
-
-struct my_struct {
-    int id;                    /* key */
-    char name[10];
-    UT_hash_handle hh;         /* makes this structure hashable */
-};
-
-

Note that, in uthash, your structure will never be moved or copied into another -location when you add it into a hash table. This means that you can keep other -data structures that safely point to your structure-- regardless of whether you -add or delete it from a hash table during your program’s lifetime.

-
-

The key

-

There are no restrictions on the data type or name of the key field. The key -can also comprise multiple contiguous fields, having any names and data types.

-
-
-
Any data type… really?
-

Yes, your key and structure can have any data type. Unlike function calls with -fixed prototypes, uthash consists of macros-- whose arguments are untyped-- and -thus able to work with any type of structure or key.

-
-
-

Unique keys

-

As with any hash, every item must have a unique key. Your application must -enforce key uniqueness. Before you add an item to the hash table, you must -first know (if in doubt, check!) that the key is not already in use. You -can check whether a key already exists in the hash table using HASH_FIND.

-
-
-
-

The hash handle

-

The UT_hash_handle field must be present in your structure. It is used for -the internal bookkeeping that makes the hash work. It does not require -initialization. It can be named anything, but you can simplify matters by -naming it hh. This allows you to use the easier "convenience" macros to add, -find and delete items.

-
-
-

A word about memory

-
-

Overhead

-

The hash handle consumes about 32 bytes per item on a 32-bit system, or 56 bytes -per item on a 64-bit system. The other overhead costs-- the buckets and the -table-- are negligible in comparison. You can use HASH_OVERHEAD to get the -overhead size, in bytes, for a hash table. See Macro Reference.

-
-
-

How clean up occurs

-

Some have asked how uthash cleans up its internal memory. The answer is simple: -when you delete the final item from a hash table, uthash releases all the -internal memory associated with that hash table, and sets its pointer to NULL.

-
-
-
-
-
-

Hash operations

-
-

This section introduces the uthash macros by example. For a more succinct -listing, see 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.

-
-
-
Wait.. the field name is a parameter?
-

If you find it strange that id, which is the name of a field in the -structure, can be passed as a parameter, welcome to the world of macros. Don’t -worry- the C preprocessor expands this to valid C code.

-
-
-

Key must not be modified while in-use

-

Once a structure has been added to the hash, do not change the value of its key. -Instead, delete the item from the hash, change the key, and then re-add it.

-
-
-

Checking uniquness

-

In the example above, we didn’t check to see if user_id was already a key -of some existing item in the hash. If there’s any chance that duplicate keys -could be generated by your program, you must explicitly check the uniqueness -before adding the key to the hash. If the key is already in the hash, you can -simply modify the existing structure in the hash rather than adding the item. -It is an error to add two items with the same key to the hash table.

-

Let’s rewrite the add_user function to check whether the id is in the hash. -Only if the id is not present in the hash, do we create the item and add it. -Otherwise we just modify the structure that already exists.

-
-
-
void add_user(int user_id, char *name) {
-    struct my_struct *s;
-
-
-
-
    HASH_FIND_INT(users, &user_id, s);  /* id already in the hash? */
-    if (s==NULL) {
-      s = (struct my_struct*)malloc(sizeof(struct my_struct));
-      s->id = user_id;
-      HASH_ADD_INT( users, id, s );  /* id: name of key field */
-    }
-    strcpy(s->name, name);
-}
-
-

Why doesn’t uthash check key uniqueness for you? It saves the cost of a hash -lookup for those programs which don’t need it- for example, programs whose keys -are generated by an incrementing, non-repeating counter.

-

However, if replacement is a common operation, it is possible to use the -HASH_REPLACE macro. This macro, before adding the item, will try to find an -item with the same key and delete it first. It also returns a pointer to the -replaced item, so the user has a chance to de-allocate its memory.

-
-
-

Passing the hash pointer into functions

-

In the example above users is a global variable, but what if the caller wanted -to pass the hash pointer into the add_user function? At first glance it would -appear that you could simply pass users as an argument, but that won’t work -right.

-
-
-
/* bad */
-void add_user(struct my_struct *users, int user_id, char *name) {
-  ...
-  HASH_ADD_INT( users, id, s );
-}
-
-

You really need to pass a pointer to the hash pointer:

-
-
-
/* good */
-void add_user(struct my_struct **users, int user_id, char *name) { ...
-  ...
-  HASH_ADD_INT( *users, id, s );
-}
-
-

Note that we dereferenced the pointer in the HASH_ADD also.

-

The reason it’s necessary to deal with a pointer to the hash pointer is simple: -the hash macros modify it (in other words, they modify the pointer itself not -just what it points to).

-
-
-
-

Replace item

-

HASH_REPLACE macros are equivalent to HASH_ADD macros except they attempt -to find and delete the item first. If it find and deletes and item, it will -also return that items pointer as an output parameter.

-
-
-

Find item

-

To look up a structure in a hash, you need its key. Then call HASH_FIND. -(Here we use the convenience macro HASH_FIND_INT for keys of type int).

-
-
Find a structure using its key
-
-
struct my_struct *find_user(int user_id) {
-    struct my_struct *s;
-
-    HASH_FIND_INT( users, &user_id, s );  /* s: output pointer */
-    return s;
-}
-
-

Here, the hash table is users, and &user_id points to the key (an integer -in this case). Last, s is the output variable of HASH_FIND_INT. The -final result is that s points to the structure with the given key, or -is NULL if the key wasn’t found in the hash.

-
- - - -
-
Note
-
The middle argument is a pointer to the key. You can’t pass a literal key -value to HASH_FIND. Instead assign the literal value to a variable, and pass -a pointer to the variable.
-
-
-
-

Delete item

-

To delete a structure from a hash, you must have a pointer to it. (If you only -have the key, first do a HASH_FIND to get the structure pointer).

-
-
Delete an item from a hash
-
-
void delete_user(struct my_struct *user) {
-    HASH_DEL( users, user);  /* user: pointer to deletee */
-    free(user);              /* optional; it's up to you! */
-}
-
-

Here again, users is the hash table, and user is a pointer to the -structure we want to remove from the hash.

-
-

uthash never frees your structure

-

Deleting a structure just removes it from the hash table-- it doesn’t free -it. The choice of when to free your structure is entirely up to you; uthash -will never free your structure. For example when using HASH_REPLACE macros, -a replaced output argument is returned back, in order to make it possible for -the user to de-allocate it.

-
-
-

Delete can change the pointer

-

The hash table pointer (which initially points to the first item added to the -hash) can change in response to HASH_DEL (i.e. if you delete the first item -in the hash table).

-
-
-

Iterative deletion

-

The HASH_ITER macro is a deletion-safe iteration construct which expands -to a simple for loop.

-
-
Delete all items from a hash
-
-
void delete_all() {
-  struct my_struct *current_user, *tmp;
-
-  HASH_ITER(hh, users, current_user, tmp) {
-    HASH_DEL(users,current_user);  /* delete; users advances to next */
-    free(current_user);            /* optional- if you want to free  */
-  }
-}
-
-
-
-

All-at-once deletion

-

If you only want to delete all the items, but not free them or do any -per-element clean up, you can do this more efficiently in a single operation:

-
-
-
HASH_CLEAR(hh,users);
-
-

Afterward, the list head (here, users) will be set to NULL.

-
-
-
-

Count items

-

The number of items in the hash table can be obtained using HASH_COUNT:

-
-
Count of items in the hash table
-
-
unsigned int num_users;
-num_users = HASH_COUNT(users);
-printf("there are %u users\n", num_users);
-
-

Incidentally, this works even the list (users, here) is NULL, in -which case the count is 0.

-
-
-

Iterating and sorting

-

You can loop over the items in the hash by starting from the beginning and -following the hh.next pointer.

-
-
Iterating over all the items in a hash
-
-
void print_users() {
-    struct my_struct *s;
-
-    for(s=users; s != NULL; s=s->hh.next) {
-        printf("user id %d: name %s\n", s->id, s->name);
-    }
-}
-
-

There is also an hh.prev pointer you could use to iterate backwards through -the hash, starting from any known item.

-
-

Deletion-safe iteration

-

In the example above, it would not be safe to delete and free s in the body -of the for loop, (because s is derefenced each time the loop iterates). -This is easy to rewrite correctly (by copying the s->hh.next pointer to a -temporary variable before freeing s), but it comes up often enough that a -deletion-safe iteration macro, HASH_ITER, is included. It expands to a -for-loop header. Here is how it could be used to rewrite the last example:

-
-
-
struct my_struct *s, *tmp;
-
-
-
-
HASH_ITER(hh, users, s, tmp) {
-    printf("user id %d: name %s\n", s->id, s->name);
-    /* ... it is safe to delete and free s here */
-}
-
-
-
-
A hash is also a doubly-linked list.
-

Iterating backward and forward through the items in the hash is possible -because of the hh.prev and hh.next fields. All the items in the hash can -be reached by repeatedly following these pointers, thus the hash is also a -doubly-linked list.

-
-

If you’re using uthash in a C++ program, you need an extra cast on the for -iterator, e.g., s=(struct my_struct*)s->hh.next.

-
-
-

Sorting

-

The items in the hash are visited in "insertion order" when you follow the -hh.next pointer. You can sort the items into a new order using HASH_SORT.

-
-
-
HASH_SORT( users, name_sort );
-
-

The second argument is a pointer to a comparison function. It must accept two -pointer arguments (the items to compare), and must return an int which is -less than zero, zero, or greater than zero, if the first item sorts before, -equal to, or after the second item, respectively. (This is the same convention -used by strcmp or qsort in the standard C library).

-
-
-
int sort_function(void *a, void *b) {
-  /* compare a to b (cast a and b appropriately)
-   * return (int) -1 if (a < b)
-   * return (int)  0 if (a == b)
-   * return (int)  1 if (a > b)
-   */
-}
-
-

Below, name_sort and id_sort are two examples of sort functions.

-
-
Sorting the items in the hash
-
-
int name_sort(struct my_struct *a, struct my_struct *b) {
-    return strcmp(a->name,b->name);
-}
-
-int id_sort(struct my_struct *a, struct my_struct *b) {
-    return (a->id - b->id);
-}
-
-void sort_by_name() {
-    HASH_SORT(users, name_sort);
-}
-
-void sort_by_id() {
-    HASH_SORT(users, id_sort);
-}
-
-

When the items in the hash are sorted, the first item may change position. In -the example above, users may point to a different structure after calling -HASH_SORT.

-
-
-
-

A complete example

-

We’ll repeat all the code and embellish it with a main() function to form a -working example.

-

If this code was placed in a file called example.c in the same directory as -uthash.h, it could be compiled and run like this:

-
-
-
cc -o example example.c
-./example
-
-

Follow the prompts to try the program.

-
-
A complete program
-
-
#include <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;
-
-    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->id = user_id;
-      HASH_ADD_INT( users, id, s );  /* id: name of key field */
-    }
-    strcpy(s->name, name);
-}
-
-struct my_struct *find_user(int user_id) {
-    struct my_struct *s;
-
-    HASH_FIND_INT( users, &user_id, s );  /* s: output pointer */
-    return s;
-}
-
-void delete_user(struct my_struct *user) {
-    HASH_DEL( users, user);  /* user: pointer to deletee */
-    free(user);
-}
-
-void delete_all() {
-  struct my_struct *current_user, *tmp;
-
-  HASH_ITER(hh, users, current_user, tmp) {
-    HASH_DEL(users,current_user);  /* delete it (users advances to next) */
-    free(current_user);            /* free it */
-  }
-}
-
-void print_users() {
-    struct my_struct *s;
-
-    for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {
-        printf("user id %d: name %s\n", s->id, s->name);
-    }
-}
-
-int name_sort(struct my_struct *a, struct my_struct *b) {
-    return strcmp(a->name,b->name);
-}
-
-int id_sort(struct my_struct *a, struct my_struct *b) {
-    return (a->id - b->id);
-}
-
-void sort_by_name() {
-    HASH_SORT(users, name_sort);
-}
-
-void sort_by_id() {
-    HASH_SORT(users, id_sort);
-}
-
-int main(int argc, char *argv[]) {
-    char in[10];
-    int id=1, running=1;
-    struct my_struct *s;
-    unsigned num_users;
-
-    while (running) {
-        printf(" 1. add user\n");
-        printf(" 2. add/rename user by id\n");
-        printf(" 3. find user\n");
-        printf(" 4. delete user\n");
-        printf(" 5. delete all users\n");
-        printf(" 6. sort items by name\n");
-        printf(" 7. sort items by id\n");
-        printf(" 8. print users\n");
-        printf(" 9. count users\n");
-        printf("10. quit\n");
-        gets(in);
-        switch(atoi(in)) {
-            case 1:
-                printf("name?\n");
-                add_user(id++, gets(in));
-                break;
-            case 2:
-                printf("id?\n");
-                gets(in); id = atoi(in);
-                printf("name?\n");
-                add_user(id, gets(in));
-                break;
-            case 3:
-                printf("id?\n");
-                s = find_user(atoi(gets(in)));
-                printf("user: %s\n", s ? s->name : "unknown");
-                break;
-            case 4:
-                printf("id?\n");
-                s = find_user(atoi(gets(in)));
-                if (s) delete_user(s);
-                else printf("id unknown\n");
-                break;
-            case 5:
-                delete_all();
-                break;
-            case 6:
-                sort_by_name();
-                break;
-            case 7:
-                sort_by_id();
-                break;
-            case 8:
-                print_users();
-                break;
-            case 9:
-                num_users=HASH_COUNT(users);
-                printf("there are %u users\n", num_users);
-                break;
-            case 10:
-                running=0;
-                break;
-        }
-    }
-
-    delete_all();  /* free any structures */
-    return 0;
-}
-
-

This program is included in the distribution in tests/example.c. You can run -make example in that directory to compile it easily.

-
-
-
-
-

Standard key types

-
-

This section goes into specifics of how to work with different kinds of keys. -You can use nearly any type of key-- integers, strings, pointers, structures, etc.

-
- - - -
-
Note
-
-
A note about float
-

You can use floating point keys. This comes with the same caveats as with any -program that tests floating point equality. In other words, even the tiniest -difference in two floating point numbers makes them distinct keys.

-
-
-
-

Integer keys

-

The preceding examples demonstrated use of integer keys. To recap, use the -convenience macros HASH_ADD_INT and HASH_FIND_INT for structures with -integer keys. (The other operations such as HASH_DELETE and HASH_SORT are -the same for all types of keys).

-
-
-

String keys

-

If your structure has a string key, the operations to use depend on whether your -structure points to the key (char *) or the string resides within the -structure (char a[10]). This distinction is important. As we’ll see below, -you need to use HASH_ADD_KEYPTR when your structure points to a key (that is, -the key itself is outside of the structure); in contrast, use HASH_ADD_STR -for a string key that is contained within your structure.

-
- - - -
-
Note
-
-
char[ ] vs. char*
-

The string is within the structure in the first example below-- name is a -char[10] field. In the second example, the key is outside of the -structure-- name is a char *. So the first example uses HASH_ADD_STR but -the second example uses HASH_ADD_KEYPTR. For information on this macro, see -the 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.

-
-
-
-
-

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.

-
-
-

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.

-
-
-

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.

-
- - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 1. Bloom filter sizes for selected values of n
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 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.

-
-
-

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
-
-
- - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 2. Built-in hash functions
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 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%

-
-
-
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

-
- - - -
-
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 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

-
-
-

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. -
  3. -

    -for add or find, the key field must be of type int or char[] or pointer -

    -
  4. -
-
- - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 3. Convenience macros
macro arguments

HASH_ADD_INT

(head, keyfield_name, item_ptr)

HASH_REPLACE_INT

(head, keyfiled_name, item_ptr,replaced_item_ptr)

HASH_FIND_INT

(head, key_ptr, item_ptr)

HASH_ADD_STR

(head, keyfield_name, item_ptr)

HASH_REPLACE_STR

(head,keyfield_name, item_ptr, replaced_item_ptr)

HASH_FIND_STR

(head, key_ptr, item_ptr)

HASH_ADD_PTR

(head, keyfield_name, item_ptr)

HASH_REPLACE_PTR

(head, keyfield_name, item_ptr, replaced_item_ptr)

HASH_FIND_PTR

(head, key_ptr, item_ptr)

HASH_DEL

(head, item_ptr)

HASH_SORT

(head, cmp)

HASH_COUNT

(head)

-
-
-
-

General macros

-

These macros add, find, delete and sort the items in a hash. You need to -use the general macros if your UT_hash_handle is named something other -than hh, or if your key’s data type isn’t int or char[].

-
- - --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Table 4. General macros
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_REPLACE

(hh_name, head, keyfield_name, key_len, item_ptr, replaced_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)

HASH_OVERHEAD

(hh_name, head)

-
-
- - - -
-
Note
-
HASH_ADD_KEYPTR is used when the structure contains a pointer to the -key, rather than the key itself.
-
-
-

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 - 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). -

-
-
-replaced_item_ptr -
-
-

- used in HASH_REPLACE macros. This is an output parameter that is set to point - to the replaced item (if no item is replaced it is set to NULL). -

-
-
-cmp -
-
-

- pointer to comparison function which accepts two arguments (pointers to - items to compare) and returns an int specifying whether the first item - should sort before, equal to, or after the second item (like strcmp). -

-
-
-condition -
-
-

- a function or macro which accepts a single argument-- a void pointer to a - structure, which needs to be cast to the appropriate structure type. The - function or macro should return (or evaluate to) a non-zero value if the - structure should be "selected" for addition to the destination hash. -

-
-
-
-
-
-
-
-

- - - diff --git a/src/util/uthash/doc/userguide.txt b/src/util/uthash/doc/userguide.txt deleted file mode 100644 index 9d74f2a..0000000 --- a/src/util/uthash/doc/userguide.txt +++ /dev/null @@ -1,1793 +0,0 @@ -uthash User Guide -================= -Troy D. Hanson -v1.9.8, March 2013 - -To download uthash, follow this link back to the -https://github.com/troydhanson/uthash[GitHub project page]. - -A hash in C ------------ -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, hashes or "dictionaries" 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/replace -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 -<>. - -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 - -Windows users: as of 2013 it's been a while since I had the environment to test -uthash under Visual Studio. If someone wants to run the unit tests under the latest -Visual Studio and confirm that its still clean, that'd be appreciated. - -Test suite -^^^^^^^^^^ -To run the test suite, enter the `tests` directory. Then, - - * on Unix platforms, run `make` - * on Windows, run the "do_tests_win32.cmd" batch file. (You may edit the - batch file if your Visual Studio is installed in a non-standard location). - -BSD licensed -~~~~~~~~~~~~ -This software is made available under the -link:license.html[revised BSD license]. -It is free and open source. - -Download uthash -~~~~~~~~~~~~~~~ -Follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file. - -Getting help -~~~~~~~~~~~~ -I encourage people to use the public Google Group to ask questions: mailto:uthash@googlegroups.com[] - -You can browse it at: https://groups.google.com/d/forum/uthash[] - -If you are experienced with uthash and like to answer questions, please join the -group and chime in when someone asks a question. That would be a great help! - -Contacting the author -^^^^^^^^^^^^^^^^^^^^^ -You can email me at tdh@tkhanson.net or message @troydhanson on Twitter. I -can't always answer my email, and when I do, it's sometimes weeks later. Sorry! - -Contributing -~~~~~~~~~~~~ -If you add a new feature or fix something in uthash or in the extras, please -make a pull request on Github. For anything other than a trivial change, include -a unit test and documentation if you possibly can. (And don't be discouraged if -it takes weeks or even months for me to merge it. Sorry, my life is busy!) Thanks! - -Extras included -~~~~~~~~~~~~~~~ -Three "extras" come with uthash. These provide lists, dynamic arrays and -strings: - - * link:utlist.html[utlist.h] provides linked list macros for C structures. - * link:utarray.html[utarray.h] implements dynamic arrays using macros. - * link:utstring.html[utstring.h] implements a basic dynamic string. - -There's also a small LRU cache API, based on uthash, in `tests/lru_cache`. - -Other software -^^^^^^^^^^^^^^ -Other open-source software by the author is listed at http://tkhanson.net. - -News -~~~~ -The author has a blog for http://troydhanson.wordpress.com/[software updates] -image:rss.png[(RSS)]. You can also follow @troydhanson on Twitter for updates. - -Who's using it? -~~~~~~~~~~~~~~~ -Uthash was downloaded around 30,000 times between 2006-2013 then transitioned to -GitHub. It's been incorporated into commercial software, academic research, and -into other open-source software. It has also been added to the native package -repositories for a number of Unix-y distros. - -When uthash was written, there were fewer options for doing generic hash tables -in C than exist today. There are faster hash tables, more memory-efficient hash -tables, with very different API's today. But, like driving a minivan, uthash is -convenient, and gets the job done without drawing a lot of attention to itself. - -Your structure --------------- - -In uthash, a hash table is comprised of structures. Each structure represents a -key-value association. One or more of the structure fields constitute the key. -The structure pointer itself is the value. - -.Defining a structure that can be hashed ----------------------------------------------------------------------- -#include "uthash.h" - -struct my_struct { - int id; /* key */ - char name[10]; - UT_hash_handle hh; /* makes this structure hashable */ -}; ----------------------------------------------------------------------- - -Note that, in uthash, your structure will never be moved or copied into another -location when you add it into a hash table. This means that you can keep other -data structures that safely point to your structure-- regardless of whether you -add or delete it from a hash table during your program's lifetime. - -The key -~~~~~~~ -There are no restrictions on the data type or name of the key field. The key -can also comprise multiple contiguous fields, having any names and data types. - -.Any data type... really? -***************************************************************************** -Yes, your key and structure can have any data type. Unlike function calls with -fixed prototypes, uthash consists of macros-- whose arguments are untyped-- and -thus able to work with any type of structure or key. -***************************************************************************** - -Unique keys -^^^^^^^^^^^ -As with any hash, every item must have a unique key. Your application must -enforce key uniqueness. Before you add an item to the hash table, you must -first know (if in doubt, check!) that the key is not already in use. You -can check whether a key already exists in the hash table using `HASH_FIND`. - -The hash handle -~~~~~~~~~~~~~~~ -The `UT_hash_handle` field must be present in your structure. It is used for -the internal bookkeeping that makes the hash work. It does not require -initialization. It can be named anything, but you can simplify matters by -naming it `hh`. This allows you to use the easier "convenience" macros to add, -find and delete items. - -A word about memory -~~~~~~~~~~~~~~~~~~~ - -Overhead -^^^^^^^^ -The hash handle consumes about 32 bytes per item on a 32-bit system, or 56 bytes -per item on a 64-bit system. The other overhead costs-- the buckets and the -table-- are negligible in comparison. You can use `HASH_OVERHEAD` to get the -overhead size, in bytes, for a hash table. See <>. - -How clean up occurs -^^^^^^^^^^^^^^^^^^^ -Some have asked how uthash cleans up its internal memory. The answer is simple: -'when you delete the final item' from a hash table, uthash releases all the -internal memory associated with that hash table, and sets its pointer to NULL. - - -Hash operations ---------------- - -This section introduces the uthash macros by example. For a more succinct -listing, see <>. - -.Convenience vs. general macros: -***************************************************************************** -The uthash macros fall into two categories. The 'convenience' macros can be used -with integer, pointer or string keys (and require that you chose the conventional -name `hh` for the `UT_hash_handle` field). The convenience macros take fewer -arguments than the general macros, making their usage a bit simpler for these -common types of keys. - -The 'general' macros can be used for any types of keys, or for multi-field keys, -or when the `UT_hash_handle` has been named something other than `hh`. These -macros take more arguments and offer greater flexibility in return. But if the -convenience macros suit your needs, use them-- your code will be more readable. -***************************************************************************** - -Declare the hash -~~~~~~~~~~~~~~~~ -Your hash must be declared as a `NULL`-initialized pointer to your structure. - - struct my_struct *users = NULL; /* important! initialize to NULL */ - -Add item -~~~~~~~~ -Allocate and initialize your structure as you see fit. The only aspect -of this that matters to uthash is that your key must be initialized to -a unique value. Then call `HASH_ADD`. (Here we use the convenience macro -`HASH_ADD_INT`, which offers simplified usage for keys of type `int`). - -.Add an item to a hash ----------------------------------------------------------------------- -void add_user(int user_id, char *name) { - struct my_struct *s; - - s = malloc(sizeof(struct my_struct)); - s->id = user_id; - strcpy(s->name, name); - HASH_ADD_INT( users, id, s ); /* id: name of key field */ -} ----------------------------------------------------------------------- - -The first parameter to `HASH_ADD_INT` is the hash table, and the -second parameter is the 'name' of the key field. Here, this is `id`. The -last parameter is a pointer to the structure being added. - -[[validc]] -.Wait.. the field name is a parameter? -******************************************************************************* -If you find it strange that `id`, which is the 'name of a field' in the -structure, can be passed as a parameter, welcome to the world of macros. Don't -worry- the C preprocessor expands this to valid C code. -******************************************************************************* - -Key must not be modified while in-use -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Once a structure has been added to the hash, do not change the value of its key. -Instead, delete the item from the hash, change the key, and then re-add it. - -Checking uniquness -^^^^^^^^^^^^^^^^^^ -In the example above, we didn't check to see if `user_id` was already a key -of some existing item in the hash. *If there's any chance that duplicate keys -could be generated by your program, you must explicitly check the uniqueness* -before adding the key to the hash. If the key is already in the hash, you can -simply modify the existing structure in the hash rather than adding the item. -'It is an error to add two items with the same key to the hash table'. - -Let's rewrite the `add_user` function to check whether the id is in the hash. -Only if the id is not present in the hash, do we create the item and add it. -Otherwise we just modify the structure that already exists. - - void add_user(int user_id, char *name) { - struct my_struct *s; - - HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ - if (s==NULL) { - s = (struct my_struct*)malloc(sizeof(struct my_struct)); - s->id = user_id; - HASH_ADD_INT( users, id, s ); /* id: name of key field */ - } - strcpy(s->name, name); - } - - -Why doesn't uthash check key uniqueness for you? It saves the cost of a hash -lookup for those programs which don't need it- for example, programs whose keys -are generated by an incrementing, non-repeating counter. - -However, if replacement is a common operation, it is possible to use the -`HASH_REPLACE` macro. This macro, before adding the item, will try to find an -item with the same key and delete it first. It also returns a pointer to the -replaced item, so the user has a chance to de-allocate its memory. - -Passing the hash pointer into functions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In the example above `users` is a global variable, but what if the caller wanted -to pass the hash pointer 'into' the `add_user` function? At first glance it would -appear that you could simply pass `users` as an argument, but that won't work -right. - - /* bad */ - void add_user(struct my_struct *users, int user_id, char *name) { - ... - HASH_ADD_INT( users, id, s ); - } - -You really need to pass 'a pointer' to the hash pointer: - - /* good */ - void add_user(struct my_struct **users, int user_id, char *name) { ... - ... - HASH_ADD_INT( *users, id, s ); - } - -Note that we dereferenced the pointer in the `HASH_ADD` also. - -The reason it's necessary to deal with a pointer to the hash pointer is simple: -the hash macros modify it (in other words, they modify the 'pointer itself' not -just what it points to). - - -Replace item -~~~~~~~~~~~~ -`HASH_REPLACE` macros are equivalent to HASH_ADD macros except they attempt -to find and delete the item first. If it find and deletes and item, it will -also return that items pointer as an output parameter. - - -Find item -~~~~~~~~~ -To look up a structure in a hash, you need its key. Then call `HASH_FIND`. -(Here we use the convenience macro `HASH_FIND_INT` for keys of type `int`). - -.Find a structure using its key ----------------------------------------------------------------------- -struct my_struct *find_user(int user_id) { - struct my_struct *s; - - HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ - return s; -} ----------------------------------------------------------------------- - -Here, the hash table is `users`, and `&user_id` points to the key (an integer -in this case). Last, `s` is the 'output' variable of `HASH_FIND_INT`. The -final result is that `s` points to the structure with the given key, or -is `NULL` if the key wasn't found in the hash. - -[NOTE] -The middle argument is a 'pointer' to the key. You can't pass a literal key -value to `HASH_FIND`. Instead assign the literal value to a variable, and pass -a pointer to the variable. - - -Delete item -~~~~~~~~~~~ -To delete a structure from a hash, you must have a pointer to it. (If you only -have the key, first do a `HASH_FIND` to get the structure pointer). - -.Delete an item from a hash ----------------------------------------------------------------------- -void delete_user(struct my_struct *user) { - HASH_DEL( users, user); /* user: pointer to deletee */ - free(user); /* optional; it's up to you! */ -} ----------------------------------------------------------------------- - -Here again, `users` is the hash table, and `user` is a pointer to the -structure we want to remove from the hash. - -uthash never frees your structure -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Deleting a structure just removes it from the hash table-- it doesn't `free` -it. The choice of when to free your structure is entirely up to you; uthash -will never free your structure. For example when using `HASH_REPLACE` macros, -a replaced output argument is returned back, in order to make it possible for -the user to de-allocate it. - -Delete can change the pointer -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The hash table pointer (which initially points to the first item added to the -hash) can change in response to `HASH_DEL` (i.e. if you delete the first item -in the hash table). - -Iterative deletion -^^^^^^^^^^^^^^^^^^ -The `HASH_ITER` macro is a deletion-safe iteration construct which expands -to a simple 'for' loop. - -.Delete all items from a hash ----------------------------------------------------------------------- -void delete_all() { - struct my_struct *current_user, *tmp; - - HASH_ITER(hh, users, current_user, tmp) { - HASH_DEL(users,current_user); /* delete; users advances to next */ - free(current_user); /* optional- if you want to free */ - } -} ----------------------------------------------------------------------- - -All-at-once deletion -^^^^^^^^^^^^^^^^^^^^ -If you only want to delete all the items, but not free them or do any -per-element clean up, you can do this more efficiently in a single operation: - - HASH_CLEAR(hh,users); - -Afterward, the list head (here, `users`) will be set to `NULL`. - -Count items -~~~~~~~~~~~ - -The number of items in the hash table can be obtained using `HASH_COUNT`: - -.Count of items in the hash table ----------------------------------------------------------------------- -unsigned int num_users; -num_users = HASH_COUNT(users); -printf("there are %u users\n", num_users); ----------------------------------------------------------------------- - -Incidentally, this works even the list (`users`, here) is `NULL`, in -which case the count is 0. - -Iterating and sorting -~~~~~~~~~~~~~~~~~~~~~ - -You can loop over the items in the hash by starting from the beginning and -following the `hh.next` pointer. - -.Iterating over all the items in a hash ----------------------------------------------------------------------- -void print_users() { - struct my_struct *s; - - for(s=users; s != NULL; s=s->hh.next) { - printf("user id %d: name %s\n", s->id, s->name); - } -} ----------------------------------------------------------------------- - -There is also an `hh.prev` pointer you could use to iterate backwards through -the hash, starting from any known item. - -[[deletesafe]] -Deletion-safe iteration -^^^^^^^^^^^^^^^^^^^^^^^ -In the example above, it would not be safe to delete and free `s` in the body -of the 'for' loop, (because `s` is derefenced each time the loop iterates). -This is easy to rewrite correctly (by copying the `s->hh.next` pointer to a -temporary variable 'before' freeing `s`), but it comes up often enough that a -deletion-safe iteration macro, `HASH_ITER`, is included. It expands to a -`for`-loop header. Here is how it could be used to rewrite the last example: - - struct my_struct *s, *tmp; - - HASH_ITER(hh, users, s, tmp) { - printf("user id %d: name %s\n", s->id, s->name); - /* ... it is safe to delete and free s here */ - } - -.A hash is also a doubly-linked list. -******************************************************************************* -Iterating backward and forward through the items in the hash is possible -because of the `hh.prev` and `hh.next` fields. All the items in the hash can -be reached by repeatedly following these pointers, thus the hash is also a -doubly-linked list. -******************************************************************************* - -If you're using uthash in a C++ program, you need an extra cast on the `for` -iterator, e.g., `s=(struct my_struct*)s->hh.next`. - -Sorting -^^^^^^^ -The items in the hash are visited in "insertion order" when you follow the -`hh.next` pointer. You can sort the items into a new order using `HASH_SORT`. - - HASH_SORT( users, name_sort ); - -The second argument is a pointer to a comparison function. It must accept two -pointer arguments (the items to compare), and must return an `int` which is -less than zero, zero, or greater than zero, if the first item sorts before, -equal to, or after the second item, respectively. (This is the same convention -used by `strcmp` or `qsort` in the standard C library). - - int sort_function(void *a, void *b) { - /* compare a to b (cast a and b appropriately) - * return (int) -1 if (a < b) - * return (int) 0 if (a == b) - * return (int) 1 if (a > b) - */ - } - -Below, `name_sort` and `id_sort` are two examples of sort functions. - -.Sorting the items in the hash ----------------------------------------------------------------------- -int name_sort(struct my_struct *a, struct my_struct *b) { - return strcmp(a->name,b->name); -} - -int id_sort(struct my_struct *a, struct my_struct *b) { - return (a->id - b->id); -} - -void sort_by_name() { - HASH_SORT(users, name_sort); -} - -void sort_by_id() { - HASH_SORT(users, id_sort); -} ----------------------------------------------------------------------- - -When the items in the hash are sorted, the first item may change position. In -the example above, `users` may point to a different structure after calling -`HASH_SORT`. - -A complete example -~~~~~~~~~~~~~~~~~~ - -We'll repeat all the code and embellish it with a `main()` function to form a -working example. - -If this code was placed in a file called `example.c` in the same directory as -`uthash.h`, it could be compiled and run like this: - - cc -o example example.c - ./example - -Follow the prompts to try the program. - -.A complete program ----------------------------------------------------------------------- -#include /* gets */ -#include /* atoi, malloc */ -#include /* strcpy */ -#include "uthash.h" - -struct my_struct { - int id; /* key */ - char name[10]; - UT_hash_handle hh; /* makes this structure hashable */ -}; - -struct my_struct *users = NULL; - -void add_user(int user_id, char *name) { - struct my_struct *s; - - HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ - if (s==NULL) { - s = (struct my_struct*)malloc(sizeof(struct my_struct)); - s->id = user_id; - HASH_ADD_INT( users, id, s ); /* id: name of key field */ - } - strcpy(s->name, name); -} - -struct my_struct *find_user(int user_id) { - struct my_struct *s; - - HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ - return s; -} - -void delete_user(struct my_struct *user) { - HASH_DEL( users, user); /* user: pointer to deletee */ - free(user); -} - -void delete_all() { - struct my_struct *current_user, *tmp; - - HASH_ITER(hh, users, current_user, tmp) { - HASH_DEL(users,current_user); /* delete it (users advances to next) */ - free(current_user); /* free it */ - } -} - -void print_users() { - struct my_struct *s; - - for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) { - printf("user id %d: name %s\n", s->id, s->name); - } -} - -int name_sort(struct my_struct *a, struct my_struct *b) { - return strcmp(a->name,b->name); -} - -int id_sort(struct my_struct *a, struct my_struct *b) { - return (a->id - b->id); -} - -void sort_by_name() { - HASH_SORT(users, name_sort); -} - -void sort_by_id() { - HASH_SORT(users, id_sort); -} - -int main(int argc, char *argv[]) { - char in[10]; - int id=1, running=1; - struct my_struct *s; - unsigned num_users; - - while (running) { - printf(" 1. add user\n"); - printf(" 2. add/rename user by id\n"); - printf(" 3. find user\n"); - printf(" 4. delete user\n"); - printf(" 5. delete all users\n"); - printf(" 6. sort items by name\n"); - printf(" 7. sort items by id\n"); - printf(" 8. print users\n"); - printf(" 9. count users\n"); - printf("10. quit\n"); - gets(in); - switch(atoi(in)) { - case 1: - printf("name?\n"); - add_user(id++, gets(in)); - break; - case 2: - printf("id?\n"); - gets(in); id = atoi(in); - printf("name?\n"); - add_user(id, gets(in)); - break; - case 3: - printf("id?\n"); - s = find_user(atoi(gets(in))); - printf("user: %s\n", s ? s->name : "unknown"); - break; - case 4: - printf("id?\n"); - s = find_user(atoi(gets(in))); - if (s) delete_user(s); - else printf("id unknown\n"); - break; - case 5: - delete_all(); - break; - case 6: - sort_by_name(); - break; - case 7: - sort_by_id(); - break; - case 8: - print_users(); - break; - case 9: - num_users=HASH_COUNT(users); - printf("there are %u users\n", num_users); - break; - case 10: - running=0; - break; - } - } - - delete_all(); /* free any structures */ - return 0; -} ----------------------------------------------------------------------- - -This program is included in the distribution in `tests/example.c`. You can run -`make example` in that directory to compile it easily. - -Standard key types ------------------- -This section goes into specifics of how to work with different kinds of keys. -You can use nearly any type of key-- integers, strings, pointers, structures, etc. - -[NOTE] -.A note about float -================================================================================ -You can use floating point keys. This comes with the same caveats as with any -program that tests floating point equality. In other words, even the tiniest -difference in two floating point numbers makes them distinct keys. -================================================================================ - -Integer keys -~~~~~~~~~~~~ -The preceding examples demonstrated use of integer keys. To recap, use the -convenience macros `HASH_ADD_INT` and `HASH_FIND_INT` for structures with -integer keys. (The other operations such as `HASH_DELETE` and `HASH_SORT` are -the same for all types of keys). - -String keys -~~~~~~~~~~~ -If your structure has a string key, the operations to use depend on whether your -structure 'points to' the key (`char *`) or the string resides `within` the -structure (`char a[10]`). *This distinction is important*. As we'll see below, -you need to use `HASH_ADD_KEYPTR` when your structure 'points' to a key (that is, -the key itself is 'outside' of the structure); in contrast, use `HASH_ADD_STR` -for a string key that is contained *within* your structure. - -[NOTE] -.char[ ] vs. char* -================================================================================ -The string is 'within' the structure in the first example below-- `name` is a -`char[10]` field. In the second example, the key is 'outside' of the -structure-- `name` is a `char *`. So the first example uses `HASH_ADD_STR` but -the second example uses `HASH_ADD_KEYPTR`. For information on this macro, see -the <>. -================================================================================ - -String 'within' structure -^^^^^^^^^^^^^^^^^^^^^^^^^ - -.A string-keyed hash (string within structure) ----------------------------------------------------------------------- -#include /* strcpy */ -#include /* malloc */ -#include /* printf */ -#include "uthash.h" - -struct my_struct { - char name[10]; /* key (string is WITHIN the structure) */ - int id; - UT_hash_handle hh; /* makes this structure hashable */ -}; - - -int main(int argc, char *argv[]) { - const char **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 /* strcpy */ -#include /* malloc */ -#include /* printf */ -#include "uthash.h" - -struct my_struct { - const char *name; /* key */ - int id; - UT_hash_handle hh; /* makes this structure hashable */ -}; - - -int main(int argc, char *argv[]) { - const char **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 -#include -#include "uthash.h" - -typedef struct { - void *key; - int i; - UT_hash_handle hh; -} el_t; - -el_t *hash = NULL; -char *someaddr = NULL; - -int main() { - el_t *d; - el_t *e = (el_t*)malloc(sizeof(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 -#include -#include "uthash.h" - -typedef struct { - char a; - int b; -} record_key_t; - -typedef struct { - record_key_t key; - /* ... other data ... */ - UT_hash_handle hh; -} record_t; - -int main(int argc, char *argv[]) { - record_t l, *p, *r, *tmp, *records = NULL; - - r = (record_t*)malloc( sizeof(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 <>. - -Advanced Topics ---------------- - -Compound keys -~~~~~~~~~~~~~ -Your key can even comprise multiple contiguous fields. - -.A multi-field key ----------------------------------------------------------------------- -#include /* malloc */ -#include /* offsetof */ -#include /* printf */ -#include /* memset */ -#include "uthash.h" - -#define UTF32 1 - -typedef struct { - UT_hash_handle hh; - int len; - char encoding; /* these two fields */ - int text[]; /* comprise the key */ -} msg_t; - -typedef struct { - char encoding; - int text[]; -} lookup_key_t; - -int main(int argc, char *argv[]) { - unsigned keylen; - msg_t *msg, *tmp, *msgs = NULL; - lookup_key_t *lookup_key; - - int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ - - /* allocate and initialize our structure */ - msg = (msg_t*)malloc( sizeof(msg_t) + sizeof(beijing) ); - memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */ - msg->len = sizeof(beijing); - msg->encoding = UTF32; - memcpy(msg->text, beijing, sizeof(beijing)); - - /* calculate the key length including padding, using formula */ - keylen = offsetof(msg_t, text) /* offset of last key field */ - + sizeof(beijing) /* size of last key field */ - - offsetof(msg_t, encoding); /* offset of first key field */ - - /* add our structure to the hash table */ - HASH_ADD( hh, msgs, encoding, keylen, msg); - - /* look it up to prove that it worked :-) */ - msg=NULL; - - lookup_key = (lookup_key_t*)malloc(sizeof(*lookup_key) + sizeof(beijing)); - memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing)); - lookup_key->encoding = UTF32; - memcpy(lookup_key->text, beijing, sizeof(beijing)); - HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg ); - if (msg) printf("found \n"); - free(lookup_key); - - HASH_ITER(hh, msgs, msg, tmp) { - HASH_DEL(msgs, msg); - free(msg); - } - return 0; -} ----------------------------------------------------------------------- - -This example is included in the distribution in `tests/test22.c`. - -If you use multi-field keys, recognize that the compiler pads adjacent fields -(by inserting unused space between them) in order to fulfill the alignment -requirement of each field. For example a structure containing a `char` followed -by an `int` will normally have 3 "wasted" bytes of padding after the char, in -order to make the `int` field start on a multiple-of-4 address (4 is the length -of the int). - -.Calculating the length of a multi-field key: -******************************************************************************* -To determine the key length when using a multi-field key, you must include any -intervening structure padding the compiler adds for alignment purposes. - -An easy way to calculate the key length is to use the `offsetof` macro from -``. The formula is: - - key length = offsetof(last_key_field) - + sizeof(last_key_field) - - offsetof(first_key_field) - -In the example above, the `keylen` variable is set using this formula. -******************************************************************************* - -When dealing with a multi-field key, you must zero-fill your structure before -`HASH_ADD`'ing it to a hash table, or using its fields in a `HASH_FIND` key. - -In the previous example, `memset` is used to initialize the structure by -zero-filling it. This zeroes out any padding between the key fields. If we -didn't zero-fill the structure, this padding would contain random values. The -random values would lead to `HASH_FIND` failures; as two "identical" keys will -appear to mismatch if there are any differences within their padding. - -[[multilevel]] -Multi-level hash tables -~~~~~~~~~~~~~~~~~~~~~~~ -A multi-level hash table arises when each element of a hash table contains its -own secondary hash table. There can be any number of levels. In a scripting -language you might see: - - $items{bob}{age}=37 - -The C program below builds this example in uthash: the hash table is called -`items`. It contains one element (`bob`) whose own hash table contains one -element (`age`) with value 37. No special functions are necessary to build -a multi-level hash table. - -While this example represents both levels (`bob` and `age`) using the same -structure, it would also be fine to use two different structure definitions. -It would also be fine if there were three or more levels instead of two. - -.Multi-level hash table ----------------------------------------------------------------------- -#include -#include -#include -#include "uthash.h" - -/* hash of hashes */ -typedef struct item { - char name[10]; - struct item *sub; - int val; - UT_hash_handle hh; -} item_t; - -item_t *items=NULL; - -int main(int argc, char *argvp[]) { - item_t *item1, *item2, *tmp1, *tmp2; - - /* make initial element */ - item_t *i = malloc(sizeof(*i)); - strcpy(i->name, "bob"); - i->sub = NULL; - i->val = 0; - HASH_ADD_STR(items, name, i); - - /* add a sub hash table off this element */ - item_t *s = malloc(sizeof(*s)); - strcpy(s->name, "age"); - s->sub = NULL; - s->val = 37; - HASH_ADD_STR(i->sub, name, s); - - /* iterate over hash elements */ - HASH_ITER(hh, items, item1, tmp1) { - HASH_ITER(hh, item1->sub, item2, tmp2) { - printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); - } - } - - /* clean up both hash tables */ - HASH_ITER(hh, items, item1, tmp1) { - HASH_ITER(hh, item1->sub, item2, tmp2) { - HASH_DEL(item1->sub, item2); - free(item2); - } - HASH_DEL(items, item1); - free(item1); - } - - return 0; -} ----------------------------------------------------------------------- -The example above is included in `tests/test59.c`. - -[[multihash]] -Items in several hash tables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A structure can be added to more than one hash table. A few reasons you might do -this include: - -- each hash table may use 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 <>, 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 <>. It is not recommended - to use a hash function that has the `noexpand` flag set. -add_usec:: - the clock time in microseconds required to add all the keys to a hash -find_usec:: - the clock time in microseconds required to look up every key in the hash -del-all usec:: - the clock time in microseconds required to delete every item in the hash - -[[ideal]] -ideal% -^^^^^^ - -.What is ideal%? -***************************************************************************** -The 'n' items in a hash are distributed into 'k' buckets. Ideally each bucket -would contain an equal share '(n/k)' of the items. In other words, the maximum -linear position of any item in a bucket chain would be 'n/k' if every bucket is -equally used. If some buckets are overused and others are underused, the -overused buckets will contain items whose linear position surpasses 'n/k'. -Such items are considered non-ideal. - -As you might guess, `ideal%` is the percentage of ideal items in the hash. These -items have favorable linear positions in their bucket chains. As `ideal%` -approaches 100%, the hash table approaches constant-time lookup performance. -***************************************************************************** - -[[hashscan]] -hashscan -~~~~~~~~ -NOTE: This utility is only available on Linux, and on FreeBSD (8.1 and up). - -A utility called `hashscan` is included in the `tests/` directory. It -is built automatically when you run `make` in that directory. This tool -examines a running process and reports on the uthash tables that it finds in -that program's memory. It can also save the keys from each table in a format -that can be fed into `keystats`. - -Here is an example of using `hashscan`. First ensure that it is built: - - cd tests/ - make - -Since `hashscan` needs a running program to inspect, we'll start up a simple -program that makes a hash table and then sleeps as our test subject: - - ./test_sleep & - pid: 9711 - -Now that we have a test program, let's run `hashscan` on it: - - ./hashscan 9711 - Address ideal items buckets mc fl bloom/sat fcn keys saved to - ------------------ ----- -------- -------- -- -- --------- --- ------------- - 0x862e038 81% 10000 4096 11 ok 16 14% JEN - -If we wanted to copy out all its keys for external analysis using `keystats`, -add the `-k` flag: - - ./hashscan -k 9711 - Address ideal items buckets mc fl bloom/sat fcn keys saved to - ------------------ ----- -------- -------- -- -- --------- --- ------------- - 0x862e038 81% 10000 4096 11 ok 16 14% JEN /tmp/9711-0.key - -Now we could run `./keystats /tmp/9711-0.key` to analyze which hash function -has the best characteristics on this set of keys. - -hashscan column reference -^^^^^^^^^^^^^^^^^^^^^^^^^ -Address:: - virtual address of the hash table -ideal:: - The percentage of items in the table which can be looked up within an ideal - number of steps. See <> in the `keystats` section. -items:: - number of items in the hash table -buckets:: - number of buckets in the hash table -mc:: - the maximum chain length found in the hash table (uthash usually tries to - keep fewer than 10 items in each bucket, or in some cases a multiple of 10) -fl:: - flags (either `ok`, or `NX` if the expansion-inhibited flag is set) -bloom/sat:: - if the hash table uses a Bloom filter, this is the size (as a power of two) - of the filter (e.g. 16 means the filter is 2^16 bits in size). The second - number is the "saturation" of the bits expressed as a percentage. The lower - the percentage, the more potential benefit to identify cache misses quickly. -fcn:: - symbolic name of hash function -keys saved to:: - file to which keys were saved, if any - -.How hashscan works -***************************************************************************** -When hashscan runs, it attaches itself to the target process, which suspends -the target process momentarily. During this brief suspension, it scans the -target's virtual memory for the signature of a uthash hash table. It then -checks if a valid hash table structure accompanies the signature and reports -what it finds. When it detaches, the target process resumes running normally. -The hashscan is performed "read-only"-- the target process is not modified. -Since hashscan is analyzing a momentary snapshot of a running process, it may -return different results from one run to another. -***************************************************************************** - -[[expansion]] -Expansion internals -~~~~~~~~~~~~~~~~~~~ -Internally this hash manages the number of buckets, with the goal of having -enough buckets so that each one contains only a small number of items. - -.Why does the number of buckets matter? -******************************************************************************** -When looking up an item by its key, this hash scans linearly through the items -in the appropriate bucket. In order for the linear scan to run in constant -time, the number of items in each bucket must be bounded. This is accomplished -by increasing the number of buckets as needed. -******************************************************************************** - -Normal expansion -^^^^^^^^^^^^^^^^ -This hash attempts to keep fewer than 10 items in each bucket. When an item is -added that would cause a bucket to exceed this number, the number of buckets in -the hash is doubled and the items are redistributed into the new buckets. In an -ideal world, each bucket will then contain half as many items as it did before. - -Bucket expansion occurs automatically and invisibly as needed. There is -no need for the application to know when it occurs. - -Per-bucket expansion threshold -++++++++++++++++++++++++++++++ -Normally all buckets share the same threshold (10 items) at which point bucket -expansion is triggered. During the process of bucket expansion, uthash can -adjust this expansion-trigger threshold on a per-bucket basis if it sees that -certain buckets are over-utilized. - -When this threshold is adjusted, it goes from 10 to a multiple of 10 (for that -particular bucket). The multiple is based on how many times greater the actual -chain length is than the ideal length. It is a practical measure to reduce -excess bucket expansion in the case where a hash function over-utilizes a few -buckets but has good overall distribution. However, if the overall distribution -gets too bad, uthash changes tactics. - -Inhibited expansion -^^^^^^^^^^^^^^^^^^^ -You usually don't need to know or worry about this, particularly if you used -the `keystats` utility during development to select a good hash for your keys. - -A hash function may yield an uneven distribution of items across the buckets. -In moderation this is not a problem. Normal bucket expansion takes place as -the chain lengths grow. But when significant imbalance occurs (because the hash -function is not well suited to the key domain), bucket expansion may be -ineffective at reducing the chain lengths. - -Imagine a very bad hash function which always puts every item in bucket 0. No -matter how many times the number of buckets is doubled, the chain length of -bucket 0 stays the same. In a situation like this, the best behavior is to -stop expanding, and accept O(n) lookup performance. This is what uthash -does. It degrades gracefully if the hash function is ill-suited to the keys. - -If two consecutive bucket expansions yield `ideal%` values below 50%, uthash -inhibits expansion for that hash table. Once set, the 'bucket expansion -inhibited' flag remains in effect as long as the hash has items in it. -Inhibited expansion may cause `HASH_FIND` to exhibit worse than constant-time -performance. - -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_REPLACE_INT | (head, keyfiled_name, item_ptr,replaced_item_ptr) -|HASH_FIND_INT | (head, key_ptr, item_ptr) -|HASH_ADD_STR | (head, keyfield_name, item_ptr) -|HASH_REPLACE_STR | (head,keyfield_name, item_ptr, replaced_item_ptr) -|HASH_FIND_STR | (head, key_ptr, item_ptr) -|HASH_ADD_PTR | (head, keyfield_name, item_ptr) -|HASH_REPLACE_PTR | (head, keyfield_name, item_ptr, replaced_item_ptr) -|HASH_FIND_PTR | (head, key_ptr, item_ptr) -|HASH_DEL | (head, item_ptr) -|HASH_SORT | (head, cmp) -|HASH_COUNT | (head) -|=============================================================================== - -General macros -~~~~~~~~~~~~~~ - -These macros add, find, delete and sort the items in a hash. You need to -use the general macros if your `UT_hash_handle` is named something other -than `hh`, or if your key's data type isn't `int` or `char[]`. - -.General macros -[width="90%",cols="10m,30m",grid="none",options="header"] -|=============================================================================== -|macro | arguments -|HASH_ADD | (hh_name, head, keyfield_name, key_len, item_ptr) -|HASH_ADD_KEYPTR| (hh_name, head, key_ptr, key_len, item_ptr) -|HASH_REPLACE | (hh_name, head, keyfield_name, key_len, item_ptr, replaced_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) -|HASH_OVERHEAD | (hh_name, head) -|=============================================================================== - -[NOTE] -`HASH_ADD_KEYPTR` is used when the structure contains a pointer to the -key, rather than the key itself. - - -Argument descriptions -^^^^^^^^^^^^^^^^^^^^^ -hh_name:: - name of the `UT_hash_handle` field in the structure. Conventionally called - `hh`. -head:: - the structure pointer variable which acts as the "head" of the hash. So - named because it initially points to the first item that is added to the hash. -keyfield_name:: - the name of the key field in the structure. (In the case of a multi-field - key, this is the first field of the key). If you're new to macros, it - might seem strange to pass the name of a field as a parameter. See - <>. -key_len:: - the length of the key field in bytes. E.g. for an integer key, this is - `sizeof(int)`, while for a string key it's `strlen(key)`. (For a - multi-field key, see 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). -replaced_item_ptr:: - used in HASH_REPLACE macros. This is an output parameter that is set to point - to the replaced item (if no item is replaced it is set to NULL). -cmp:: - pointer to comparison function which accepts two arguments (pointers to - items to compare) and returns an int specifying whether the first item - should sort before, equal to, or after the second item (like `strcmp`). -condition:: - a function or macro which accepts a single argument-- a void pointer to a - structure, which needs to be cast to the appropriate structure type. The - function or macro should 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/src/util/uthash/doc/utarray.html b/src/util/uthash/doc/utarray.html deleted file mode 100644 index 5b46176..0000000 --- a/src/util/uthash/doc/utarray.html +++ /dev/null @@ -1,1265 +0,0 @@ - - - - - -utarray: dynamic array macros for C - - - - - -
-
-
-

Here’s a link back to the 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 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 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 -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 -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;
-}
-
-
-
-
-
-

Reference

-
-

This table lists all the utarray operations. These are loosely based on the C++ -vector class.

-
-

Operations

-
- --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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. -
  3. -

    -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) -

    -
  4. -
  5. -

    -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;
    -}
    -
    -
  6. -
  7. -

    -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. -

    -
  8. -
  9. -

    -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. -

    -
  10. -
-
-
-
-
-

- - - diff --git a/src/util/uthash/doc/utarray.txt b/src/util/uthash/doc/utarray.txt deleted file mode 100644 index 903d5d1..0000000 --- a/src/util/uthash/doc/utarray.txt +++ /dev/null @@ -1,374 +0,0 @@ -utarray: dynamic array macros for C -=================================== -Troy D. Hanson -v1.9.8, March 2013 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -A set of general-purpose 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 -accomodate 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 - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - ut hash - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/util/uthash/doc/uthash.png b/src/util/uthash/doc/uthash.png deleted file mode 100644 index 20df5a7..0000000 Binary files a/src/util/uthash/doc/uthash.png and /dev/null differ diff --git a/src/util/uthash/doc/utlist.html b/src/util/uthash/doc/utlist.html deleted file mode 100644 index 298594e..0000000 --- a/src/util/uthash/doc/utlist.html +++ /dev/null @@ -1,1189 +0,0 @@ - - - - - -utlist: linked list macros for C structures - - - - - -
-
-
-

Here’s a link back to the 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 -revised BSD license. -It is free and open source.

-
-
-

Platforms

-

The utlist macros have been tested on:

-
    -
  • -

    -Linux, -

    -
  • -
  • -

    -Mac OS X, and -

    -
  • -
  • -

    -Windows, using Visual Studio 2008, Visual Studio 2010, or Cygwin/MinGW. -

    -
  • -
-
-
-
-
-

Using utlist

-
-
-

Types of lists

-

Three types of linked lists are supported:

-
    -
  • -

    -singly-linked lists, -

    -
  • -
  • -

    -doubly-linked lists, and -

    -
  • -
  • -

    -circular, doubly-linked lists -

    -
  • -
-
-

Efficiency

-

For all types of lists, prepending elements and deleting elements are -constant-time operations. Appending to a singly-linked list is an O(n) -operation but appending to a doubly-linked list is constant time using these -macros. (This is because, in the utlist implementation of the doubly-linked -list, the head element’s prev member points back to the list tail, even when -the list is non-circular). Sorting is an O(n log(n)) operation. Iteration -and searching are O(n) for all list types.

-
-
-
-

List elements

-

You can use any structure with these macros, as long as the structure -contains a next pointer. If you want to make a doubly-linked list, -the element also needs to have a prev pointer.

-
-
-
typedef struct element {
-    char *name;
-    struct element *prev; /* needed for a doubly-linked list only */
-    struct element *next; /* needed for singly- or doubly-linked lists */
-} element;
-
-

You can name your structure anything. In the example above it is called element. -Within a particular list, all elements must be of the same type.

-
-

Flexible prev/next naming

-

You can name your prev and next pointers something else. If you do, there is -a family of macros 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.

-
- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Singly-linked Doubly-linked Circular, doubly-linked

LL_PREPEND(head,add);

DL_PREPEND(head,add);

CDL_PREPEND(head,add;

LL_PREPEND_ELEM(head,elt,add)

DL_PREPEND_ELEM(head,elt,add)

CDL_PREPEND_ELEM(head,elt,add)

LL_REPLACE_ELEM(head,elt,add)

DL_REPLACE_ELEM(head,elt,add)

CDL_REPLACE_ELEM(head,elt,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.) -To prepend before an arbitrary element instead of the list head, use the -_PREPEND_ELEM macro family. To replace an arbitary list element with another -element use the _REPLACE_ELEM family of macros.

-

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; or, the output pointer from - the search macros; or the element to be prepended to or replaced. -

-
-
-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;
-}
-
-
-
-

Other names for prev and next

-

If the prev and next fields are named something else, a separate group of -macros must be used. These work the same as the regular macros, but take the -field names as extra parameters.

-

These "flexible field name" macros are shown below. They all end with "2". Each -operates the same as its counterpart without the 2, but they take the name of -the prev and next fields (as applicable) as trailing arguments.

-
-
Flexible field name macros
-
-
LL_SORT2(list, cmp, next)
-DL_SORT2(list, cmp, prev, next)
-CDL_SORT2(list, cmp, prev, next)
-LL_PREPEND2(head,add,next)
-LL_CONCAT2(head1,head2,next)
-LL_APPEND2(head,add,next)
-LL_DELETE2(head,del,next)
-LL_FOREACH2(head,el,next)
-LL_FOREACH_SAFE2(head,el,tmp,next)
-LL_SEARCH_SCALAR2(head,out,field,val,next)
-LL_SEARCH2(head,out,elt,cmp,next)
-DL_PREPEND2(head,add,prev,next)
-DL_APPEND2(head,add,prev,next)
-DL_CONCAT2(head1,head2,prev,next)
-DL_DELETE2(head,del,prev,next)
-DL_FOREACH2(head,el,next)
-DL_FOREACH_SAFE2(head,el,tmp,next)
-CDL_PREPEND2(head,add,prev,next)
-CDL_DELETE2(head,del,prev,next)
-CDL_FOREACH2(head,el,next)
-CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
-CDL_SEARCH_SCALAR2(head,out,field,val,next)
-CDL_SEARCH2(head,out,elt,cmp,next)
-
-
-
-
-
-

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

Here’s a link back to the 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 operations 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 -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 demonstrates that utstring_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 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 <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;
-}
-
-
-
-
-
-

Reference

-
-

These are the utstring operations.

-
-

Operations

-
- --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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)

utstring_find(s,pos,str,len)

forward search from pos for a substring

utstring_findR(s,pos,str,len)

reverse search from pos a substring

-
-
-
-

New/free vs. init/done

-

Use utstring_new and utstring_free to allocate a new string or free it. If -the UT_string is statically allocated, use utstring_init and utstring_done -to initialize or free its internal memory.

-
-
- -

Use utstring_find and utstring_findR to search for a substring in a utstring. -It comes in forward and reverse varieties. The reverse search scans from the end of -the string backward. These take a position to start searching from, measured from 0 -(the start of the utstring). A negative position is counted from the end of -the string, so, -1 is the last position. Note that in the reverse search, the -initial position anchors to the end of the substring being searched for- -e.g., the t in cat. The return value always refers to the offset where the -substring starts in the utstring. When no substring match is found, -1 is -returned.

-

For example if a utstring called s contains:

-
-
-
ABC ABCDAB ABCDABCDABDE
-
-

Then these forward and reverse substring searches for ABC produce these results:

-
-
-
utstring_find(  s, -9, "ABC", 3 ) = 15
-utstring_find(  s,  3, "ABC", 3 ) =  4
-utstring_find(  s, 16, "ABC", 3 ) = -1
-utstring_findR( s, -9, "ABC", 3 ) = 11
-utstring_findR( s, 12, "ABC", 3 ) =  4
-utstring_findR( s,  2, "ABC", 3 ) =  0
-
-
- -

The preceding examples show "single use" versions of substring matching, where -the internal Knuth-Morris-Pratt (KMP) table is internally built and then freed -after the search. If your program needs to run many searches for a given -substring, it is more efficient to save the KMP table and reuse it.

-

To reuse the KMP table, build it manually and then pass it into the internal -search functions. The functions involved are:

-
-
-
_utstring_BuildTable  (build the KMP table for a forward search)
-_utstring_BuildTableR (build the KMP table for a reverse search)
-_utstring_find        (forward search using a prebuilt KMP table)
-_utstring_findR       (reverse search using a prebuilt KMP table)
-
-

This is an example of building a forward KMP table for the substring "ABC", and -then using it in a search:

-
-
-
long *KPM_TABLE, offset;
-KPM_TABLE = (long *)malloc( sizeof(long) * (strlen("ABC")) + 1));
-_utstring_BuildTable("ABC", 3, KPM_TABLE);
-offset = _utstring_find(utstring_body(s), utstring_len(s), "ABC", 3, KPM_TABLE );
-free(KPM_TABLE);
-
-

Note that the internal _utstring_find has the length of the UT_string as its -second argument, rather than the start position. You can emulate the position -parameter by adding to the string start address and subtracting from its length.

-
-
-
-
-
-

- - - diff --git a/src/util/uthash/doc/utstring.txt b/src/util/uthash/doc/utstring.txt deleted file mode 100644 index b1c6664..0000000 --- a/src/util/uthash/doc/utstring.txt +++ /dev/null @@ -1,229 +0,0 @@ -utstring: dynamic string macros for C -===================================== -Troy D. Hanson -v1.9.8, March 2013 - -Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page]. - -Introduction ------------- -A set of 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 /* size_t */ #include /* memset, etc */ #include /* exit */ -#define oom() exit(-1) +#ifdef __GNUC__ +#define UTARRAY_UNUSED __attribute__((__unused__)) +#else +#define UTARRAY_UNUSED +#endif + +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code." +#define utarray_oom() oom() +#endif + +#ifndef utarray_oom +#define utarray_oom() exit(-1) +#endif typedef void (ctor_f)(void *dst, const void *src); typedef void (dtor_f)(void *elt); @@ -58,13 +65,13 @@ typedef struct { #define utarray_init(a,_icd) do { \ memset(a,0,sizeof(UT_array)); \ - (a)->icd=*_icd; \ + (a)->icd = *(_icd); \ } while(0) #define utarray_done(a) do { \ if ((a)->n) { \ if ((a)->icd.dtor) { \ - size_t _ut_i; \ + unsigned _ut_i; \ for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ } \ @@ -75,7 +82,10 @@ typedef struct { } while(0) #define utarray_new(a,_icd) do { \ - a=(UT_array*)malloc(sizeof(UT_array)); \ + (a) = (UT_array*)malloc(sizeof(UT_array)); \ + if ((a) == NULL) { \ + utarray_oom(); \ + } \ utarray_init(a,_icd); \ } while(0) @@ -85,9 +95,14 @@ typedef struct { } 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(); \ + if (((a)->i+(by)) > (a)->n) { \ + char *utarray_tmp; \ + while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ + if (utarray_tmp == NULL) { \ + utarray_oom(); \ + } \ + (a)->d=utarray_tmp; \ } \ } while(0) @@ -112,10 +127,10 @@ typedef struct { #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_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) #define utarray_insert(a,p,j) do { \ - if (j > (a)->i) utarray_resize(a,j); \ + if ((j) > (a)->i) utarray_resize(a,j); \ utarray_reserve(a,1); \ if ((j) < (a)->i) { \ memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ @@ -128,7 +143,7 @@ typedef struct { #define utarray_inserta(a,w,j) do { \ if (utarray_len(w) == 0) break; \ - if (j > (a)->i) utarray_resize(a,j); \ + if ((j) > (a)->i) utarray_resize(a,j); \ utarray_reserve(a,utarray_len(w)); \ if ((j) < (a)->i) { \ memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ @@ -136,9 +151,9 @@ typedef struct { ((a)->i - (j))*((a)->icd.sz)); \ } \ if ((a)->icd.copy) { \ - size_t _ut_i; \ + unsigned _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)); \ + (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ } \ } else { \ memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ @@ -148,55 +163,55 @@ typedef struct { } while(0) #define utarray_resize(dst,num) do { \ - size_t _ut_i; \ - if (dst->i > (size_t)(num)) { \ + unsigned _ut_i; \ + if ((dst)->i > (unsigned)(num)) { \ if ((dst)->icd.dtor) { \ - for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ - (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ + 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); \ + } else if ((dst)->i < (unsigned)(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)); \ + for (_ut_i = (dst)->i; _ut_i < (unsigned)(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)); \ + memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ } \ } \ - dst->i = num; \ + (dst)->i = (num); \ } while(0) #define utarray_concat(dst,src) do { \ - utarray_inserta((dst),(src),utarray_len(dst)); \ + 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)); \ + unsigned _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)); \ + 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) + 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; \ + unsigned _ut_i; \ for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ } \ } \ (a)->i = 0; \ @@ -210,23 +225,24 @@ typedef struct { #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_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))/(ssize_t)(a)->icd.sz) : -1) +#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) /* 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); + char *const *srcc = (char *const *)src; + char **dstc = (char**)dst; + *dstc = (*srcc == NULL) ? NULL : strdup(*srcc); } static void utarray_str_dtor(void *elt) { char **eltc = (char**)elt; - if (*eltc) free(*eltc); + if (*eltc != NULL) 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}; +static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; +static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; +static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; #endif /* UTARRAY_H */ diff --git a/src/util/uthash/src/uthash.h b/src/util/uthash/src/uthash.h index f0e50f9..ac78fda 100644 --- a/src/util/uthash/src/uthash.h +++ b/src/util/uthash/src/uthash.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without @@ -22,59 +22,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UTHASH_H -#define UTHASH_H +#define UTHASH_H -#include /* memcmp,strlen */ +#define UTHASH_VERSION 2.3.0 + +#include /* memcmp, memset, strlen */ #include /* ptrdiff_t */ -#include /* exit() */ +#include /* exit */ + +#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT +/* This codepath is provided for backward compatibility, but I plan to remove it. */ +#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead" +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT +#else +#include /* uint8_t, uint32_t */ +#endif /* 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 !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_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 +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE #else /* GNU, Sun and other compilers */ #define DECLTYPE(x) (__typeof(x)) #endif +#endif #ifdef NO_DECLTYPE +#define DECLTYPE(x) #define DECLTYPE_ASSIGN(dst,src) \ do { \ char **_da_dst = (char**)(&(dst)); \ *_da_dst = (char*)(src); \ -} while(0) -#else +} while (0) +#else #define DECLTYPE_ASSIGN(dst,src) \ do { \ (dst) = DECLTYPE(dst)(src); \ -} while(0) +} 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 /* uint32_t */ -#endif - -#define UTHASH_VERSION 1.9.8 - -#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_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifndef HASH_FUNCTION +#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv) +#endif + +#ifndef HASH_KEYCMP +#define HASH_KEYCMP(a,b,n) memcmp(a,b,n) +#endif #ifndef uthash_noexpand_fyi #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ @@ -83,122 +100,338 @@ typedef unsigned char uint8_t; #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 */ +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif -/* calculate the element whose hash handle address is hhe */ +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FUNCTION(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) #define HASH_FIND(hh,head,keyptr,keylen,out) \ do { \ - unsigned _hf_bkt,_hf_hashv; \ - out=NULL; \ + (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); \ - } \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, 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) \ +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ 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) + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, 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) +} 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_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) #define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) #define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) #else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) #define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0 +#define HASH_BLOOM_BYTELEN 0U #endif -#define HASH_MAKE_TABLE(hh,head) \ +#define HASH_MAKE_TABLE(hh,head,oomed) \ 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) + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, 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)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) #define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ do { \ - replaced=NULL; \ - HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ - if (replaced!=NULL) { \ - HASH_DELETE(hh,head,replaced); \ - }; \ - HASH_ADD(hh,head,fieldname,keylen_in,add); \ -} while(0) - + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (const void*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + #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) + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) /* delete "delptr" from the hash table. * "the usual" patch-up process for the app-order doubly-linked-list. @@ -213,48 +446,53 @@ do { * 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*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((ptrdiff_t)((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*)((ptrdiff_t)_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) + HASH_DELETE_HH(hh, head, &(delptr)->hh) +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} 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) +do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +} while (0) #define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield,strlen(add->strfield),add) +do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +} while (0) #define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) +do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ +} while (0) #define HASH_FIND_INT(head,findint,out) \ HASH_FIND(hh,head,findint,sizeof(int),out) #define HASH_ADD_INT(head,intfield,add) \ @@ -265,7 +503,7 @@ do { 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_REPLACE_PTR(head,ptrfield,add) \ +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) #define HASH_DEL(head,delptr) \ HASH_DELETE(hh,head,delptr) @@ -274,120 +512,113 @@ do { * 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) \ +#include /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ unsigned _bkt_i; \ - unsigned _count, _bkt_count; \ + unsigned _count = 0; \ 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 ); \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_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("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ } while (0) #else -#define HASH_FSCK(hh,head) +#define HASH_FSCK(hh,head,where) #endif -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to +/* 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 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); \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)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 +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) #endif -/* The Bernstein hash function, used in Perl prior to v5.6 */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)(key); \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ } while (0) -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at +/* 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) \ +#define HASH_SAX(key,keylen,hashv) \ do { \ unsigned _sx_i; \ - char *_hs_key=(char*)(key); \ + const unsigned char *_hs_key = (const unsigned 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); \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ } while (0) - -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ 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) \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ do { \ unsigned _ho_i; \ - char *_ho_key=(char*)(key); \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ hashv = 0; \ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ hashv += _ho_key[_ho_i]; \ @@ -397,8 +628,7 @@ do { hashv += (hashv << 3); \ hashv ^= (hashv >> 11); \ hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) +} while (0) #define HASH_JEN_MIX(a,b,c) \ do { \ @@ -413,14 +643,14 @@ do { c -= a; c -= b; c ^= ( b >> 15 ); \ } while (0) -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ +#define HASH_JEN(key,keylen,hashv) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ - const unsigned char *_hj_key=(const unsigned char*)(key); \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = (unsigned)keylen; \ - while (_hj_k >= 12) { \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + ( (unsigned)_hj_key[2] << 16 ) \ + ( (unsigned)_hj_key[3] << 24 ) ); \ @@ -434,25 +664,25 @@ do { HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ \ _hj_key += 12; \ - _hj_k -= 12; \ + _hj_k -= 12U; \ } \ - hashv += keylen; \ + hashv += (unsigned)(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]; \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default: ; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) +} while (0) /* The Paul Hsieh hash function */ #undef get16bits @@ -465,21 +695,21 @@ do { #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) \ +#define HASH_SFH(key,keylen,hashv) \ do { \ - unsigned char *_sfh_key=(unsigned char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ \ - int _sfh_rem = _sfh_len & 3; \ + unsigned _sfh_rem = _sfh_len & 3U; \ _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ + hashv = 0xcafebabeu; \ \ /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ + for (;_sfh_len > 0U; _sfh_len--) { \ hashv += get16bits (_sfh_key); \ - _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ + _sfh_key += 2U*sizeof (uint16_t); \ hashv += hashv >> 11; \ } \ \ @@ -487,7 +717,7 @@ do { switch (_sfh_rem) { \ case 3: hashv += get16bits (_sfh_key); \ hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ hashv += hashv >> 11; \ break; \ case 2: hashv += get16bits (_sfh_key); \ @@ -497,223 +727,163 @@ do { case 1: hashv += *_sfh_key; \ hashv ^= hashv << 10; \ hashv += hashv >> 1; \ + break; \ + default: ; \ } \ \ - /* 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__) || defined(_M_IX86)) -#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; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - 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++) { \ - _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; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ - _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) + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) /* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,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 ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (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) + if ((out)->hh.hh_next != NULL) { \ + 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) \ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ 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) + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} 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; \ - } +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) /* 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). - * + * 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 + * 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 + * 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) \ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ 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; \ + 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( \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (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 != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _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_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ } \ uthash_expand_fyi(tbl); \ -} while(0) + } \ +} 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. +/* 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) \ @@ -721,153 +891,179 @@ 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; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ } \ - _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_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : 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; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ } \ - _hs_insize *= 2; \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ } \ - HASH_FSCK(hh,head); \ - } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ } 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 +/* 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; \ + 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; \ + if ((src) != NULL) { \ + 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 != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(void*)(((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 != NULL) { \ + _last_elt_hh->next = _elt; \ } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } 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], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ } \ } \ } \ - HASH_FSCK(hh_dst,dst); \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ } while (0) #define HASH_CLEAR(hh,head) \ do { \ - if (head) { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ 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; \ + (head) = NULL; \ } \ -} while(0) +} while (0) #define HASH_OVERHEAD(hh,head) \ - (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - (sizeof(UT_hash_table)) + \ - (HASH_BLOOM_BYTELEN))) + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) #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)) +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(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)) +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(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) +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) typedef struct UT_hash_bucket { struct UT_hash_handle *hh_head; @@ -875,7 +1071,7 @@ typedef struct UT_hash_bucket { /* 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). + * 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. @@ -883,15 +1079,15 @@ typedef struct UT_hash_bucket { * 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. + * 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 +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u typedef struct UT_hash_table { UT_hash_bucket *buckets; @@ -909,7 +1105,7 @@ typedef struct UT_hash_table { * hash distribution; reaching them in a chain traversal takes >ideal steps */ unsigned nonideal_items; - /* ineffective expands occur when a bucket doubling was performed, but + /* 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 @@ -921,7 +1117,7 @@ typedef struct UT_hash_table { #ifdef HASH_BLOOM uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ uint8_t *bloom_bv; - char bloom_nbits; + uint8_t bloom_nbits; #endif } UT_hash_table; @@ -932,7 +1128,7 @@ typedef struct UT_hash_handle { 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 */ + const 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; diff --git a/src/util/uthash/src/utlist.h b/src/util/uthash/src/utlist.h index 8d845dc..6230a67 100644 --- a/src/util/uthash/src/utlist.h +++ b/src/util/uthash/src/utlist.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2007-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without @@ -24,11 +24,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef UTLIST_H #define UTLIST_H -#define UTLIST_VERSION 1.9.8 +#define UTLIST_VERSION 2.3.0 #include -/* +/* * This file contains macros to manipulate singly and doubly-linked lists. * * 1. LL_ macros: singly-linked lists. @@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 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; @@ -61,41 +61,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* 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 + 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 !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_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) */ +#else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE -#define LDECLTYPE(x) char* #endif -#elif defined(__ICCARM__) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) #define NO_DECLTYPE -#define LDECLTYPE(x) char* -#else /* GNU, Sun and other compilers */ +#else /* GNU, Sun and other compilers */ #define LDECLTYPE(x) __typeof(x) #endif +#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,next) ((char*)((list)->next)) -#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } -/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */ -#define _PREVASGN(elt,list,to,prev) { 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,next) ((elt)->next) -#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to) -/* #define _PREV(elt,list,prev) ((elt)->prev) */ -#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) -#define _RS(list) -#define _CASTASGN(a,b) (a)=(b) +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) #endif /****************************************************************************** @@ -111,13 +114,14 @@ do { LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(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); \ - list = NULL; \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ @@ -126,35 +130,35 @@ do { _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,next); _RS(list); \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_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,next); _RS(list); _ls_qsize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ } else { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ } \ if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ } else { \ - _CASTASGN(list,_ls_e); \ + UTLIST_CASTASGN(list,_ls_e); \ } \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ } \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ @@ -174,13 +178,14 @@ do { LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(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); \ - list = NULL; \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ @@ -189,36 +194,36 @@ do { _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,next); _RS(list); \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ if (!_ls_q) break; \ } \ _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + 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,next); _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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ } else { \ - _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \ - _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ } \ if (_ls_tail) { \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ } else { \ - _CASTASGN(list,_ls_e); \ + UTLIST_CASTASGN(list,_ls_e); \ } \ - _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ - _CASTASGN(list->prev, _ls_tail); \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ } \ @@ -243,9 +248,9 @@ do { _ls_insize = 1; \ _ls_looping = 1; \ while (_ls_looping) { \ - _CASTASGN(_ls_p,list); \ - _CASTASGN(_ls_oldhead,list); \ - list = NULL; \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ @@ -254,47 +259,47 @@ do { _ls_psize = 0; \ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ _ls_psize++; \ - _SV(_ls_q,list); \ - if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ _ls_q = NULL; \ } else { \ - _ls_q = _NEXT(_ls_q,list,next); \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ } \ - _RS(list); \ + UTLIST_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,next); _RS(list); _ls_qsize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_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,next); _RS(list); _ls_psize--; \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_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,next); _RS(list); _ls_qsize--; \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_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,next); _RS(list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ } else { \ - _CASTASGN(list,_ls_e); \ + UTLIST_CASTASGN(list,_ls_e); \ } \ - _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ - _CASTASGN(list->prev,_ls_tail); \ - _CASTASGN(_tmp,list); \ - _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ } \ @@ -311,8 +316,8 @@ do { #define LL_PREPEND2(head,add,next) \ do { \ - (add)->next = head; \ - head = add; \ + (add)->next = (head); \ + (head) = (add); \ } while (0) #define LL_CONCAT(head1,head2) \ @@ -322,7 +327,7 @@ do { do { \ LDECLTYPE(head1) _tmp; \ if (head1) { \ - _tmp = head1; \ + _tmp = (head1); \ while (_tmp->next) { _tmp = _tmp->next; } \ _tmp->next=(head2); \ } else { \ @@ -338,7 +343,7 @@ do { LDECLTYPE(head) _tmp; \ (add)->next=NULL; \ if (head) { \ - _tmp = head; \ + _tmp = (head); \ while (_tmp->next) { _tmp = _tmp->next; } \ _tmp->next=(add); \ } else { \ @@ -346,6 +351,37 @@ do { } \ } while (0) +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + #define LL_DELETE(head,del) \ LL_DELETE2(head,del,next) @@ -355,21 +391,140 @@ do { if ((head) == (del)) { \ (head)=(head)->next; \ } else { \ - _tmp = head; \ + _tmp = (head); \ while (_tmp->next && (_tmp->next != (del))) { \ _tmp = _tmp->next; \ } \ if (_tmp->next) { \ - _tmp->next = ((del)->next); \ + _tmp->next = (del)->next; \ } \ } \ } while (0) -/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ -#define LL_APPEND_VS2008(head,add) \ - LL_APPEND2_VS2008(head,add,next) +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ -#define LL_APPEND2_VS2008(head,add,next) \ +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ do { \ if (head) { \ (add)->next = head; /* use add->next as a temp variable */ \ @@ -381,113 +536,84 @@ do { (add)->next=NULL; \ } while (0) -#define LL_DELETE_VS2008(head,del) \ - LL_DELETE2_VS2008(head,del,next) +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) -#define LL_DELETE2_VS2008(head,del,next) \ +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ do { \ if ((head) == (del)) { \ (head)=(head)->next; \ } else { \ char *_tmp = (char*)(head); \ while ((head)->next && ((head)->next != (del))) { \ - head = (head)->next; \ + (head) = (head)->next; \ } \ if ((head)->next) { \ (head)->next = ((del)->next); \ } \ - { \ - char **_head_alias = (char**)&(head); \ - *_head_alias = _tmp; \ - } \ + UTLIST_RS(head); \ } \ } 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_DELETE2 -#define LL_DELETE2 LL_DELETE2_VS2008 -#undef LL_APPEND2 -#define LL_APPEND2 LL_APPEND2_VS2008 -#undef LL_CONCAT /* no LL_CONCAT_VS2008 */ -#undef DL_CONCAT /* no DL_CONCAT_VS2008 */ -#endif -/* end VS2008 replacements */ -#define LL_FOREACH(head,el) \ - LL_FOREACH2(head,el,next) - -#define LL_FOREACH2(head,el,next) \ - for(el=head;el;el=(el)->next) - -#define LL_FOREACH_SAFE(head,el,tmp) \ - LL_FOREACH_SAFE2(head,el,tmp,next) - -#define LL_FOREACH_SAFE2(head,el,tmp,next) \ - for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) - -#define LL_SEARCH_SCALAR(head,out,field,val) \ - LL_SEARCH_SCALAR2(head,out,field,val,next) - -#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ do { \ - LL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ } \ -} while(0) - -#define LL_SEARCH(head,out,elt,cmp) \ - LL_SEARCH2(head,out,elt,cmp,next) - -#define LL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ } \ -} while(0) - -#define LL_REPLACE_ELEM(head, el, add) \ -do { \ - LDECLTYPE(head) _tmp; \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el)->next; \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = head; \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ + (add)->next = (el)->next; \ } while (0) -#define LL_PREPEND_ELEM(head, el, add) \ +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ do { \ - LDECLTYPE(head) _tmp; \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = head; \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ } while (0) \ +#endif /* NO_DECLTYPE */ /****************************************************************************** * doubly linked list macros (non-circular) * @@ -497,7 +623,7 @@ do { #define DL_PREPEND2(head,add,prev,next) \ do { \ - (add)->next = head; \ + (add)->next = (head); \ if (head) { \ (add)->prev = (head)->prev; \ (head)->prev = (add); \ @@ -522,7 +648,39 @@ do { (head)->prev = (head); \ (head)->next = NULL; \ } \ -} while (0) +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) #define DL_CONCAT(head1,head2) \ DL_CONCAT2(head1,head2,prev,next) @@ -532,21 +690,22 @@ do { LDECLTYPE(head1) _tmp; \ if (head2) { \ if (head1) { \ - _tmp = (head2)->prev; \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ (head2)->prev = (head1)->prev; \ (head1)->prev->next = (head2); \ - (head1)->prev = _tmp; \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ } else { \ (head1)=(head2); \ } \ } \ -} while (0) +} while (0) #define DL_DELETE(head,del) \ DL_DELETE2(head,del,prev,next) #define DL_DELETE2(head,del,prev,next) \ do { \ + assert((head) != NULL); \ assert((del)->prev != NULL); \ if ((del)->prev == (del)) { \ (head)=NULL; \ @@ -561,21 +720,29 @@ do { (head)->prev = (del)->prev; \ } \ } \ -} while (0) +} while (0) +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) #define DL_FOREACH(head,el) \ DL_FOREACH2(head,el,next) #define DL_FOREACH2(head,el,next) \ - for(el=head;el;el=(el)->next) + for ((el) = (head); el; (el) = (el)->next) /* this version is safe for deleting the elements during iteration */ #define DL_FOREACH_SAFE(head,el,tmp) \ DL_FOREACH_SAFE2(head,el,tmp,next) #define DL_FOREACH_SAFE2(head,el,tmp,next) \ - for((el)=(head);(el) && (tmp = (el)->next, 1); (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 @@ -583,11 +750,11 @@ do { #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 #define DL_SEARCH2 LL_SEARCH2 -#define DL_REPLACE_ELEM(head, el, add) \ +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ if ((head) == (el)) { \ (head) = (add); \ (add)->next = (el)->next; \ @@ -609,25 +776,104 @@ do { } \ } while (0) -#define DL_PREPEND_ELEM(head, el, add) \ +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ } else { \ - (add)->prev->next = (add); \ + DL_APPEND2(head, add, prev, next); \ } \ } while (0) \ +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ /****************************************************************************** * circular doubly linked list macros * *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +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_PREPEND(head,add) \ CDL_PREPEND2(head,add,prev,next) @@ -642,7 +888,39 @@ do { (add)->prev = (add); \ (add)->next = (add); \ } \ -(head)=(add); \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ } while (0) #define CDL_DELETE(head,del) \ @@ -650,28 +928,37 @@ do { #define CDL_DELETE2(head,del,prev,next) \ do { \ - if ( ((head)==(del)) && ((head)->next == (head))) { \ - (head) = 0L; \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ } else { \ (del)->next->prev = (del)->prev; \ (del)->prev->next = (del)->next; \ if ((del) == (head)) (head)=(del)->next; \ } \ -} while (0) +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) #define CDL_FOREACH(head,el) \ CDL_FOREACH2(head,el,next) #define CDL_FOREACH2(head,el,next) \ - for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ - for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ - (el) && ((tmp2)=(el)->next, 1); \ - ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) #define CDL_SEARCH_SCALAR(head,out,field,val) \ CDL_SEARCH_SCALAR2(head,out,field,val,next) @@ -681,7 +968,7 @@ do { CDL_FOREACH2(head,out,next) { \ if ((out)->field == (val)) break; \ } \ -} while(0) +} while (0) #define CDL_SEARCH(head,out,elt,cmp) \ CDL_SEARCH2(head,out,elt,cmp,next) @@ -691,13 +978,13 @@ do { CDL_FOREACH2(head,out,next) { \ if ((cmp(out,elt))==0) break; \ } \ -} while(0) +} while (0) -#define CDL_REPLACE_ELEM(head, el, add) \ +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ if ((el)->next == (el)) { \ (add)->next = (add); \ (add)->prev = (add); \ @@ -713,19 +1000,74 @@ do { } \ } while (0) -#define CDL_PREPEND_ELEM(head, el, add) \ +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ do { \ - assert(head != NULL); \ - assert(el != NULL); \ - assert(add != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ } \ -} while (0) \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ #endif /* UTLIST_H */ - diff --git a/src/util/uthash/src/utringbuffer.h b/src/util/uthash/src/utringbuffer.h new file mode 100644 index 0000000..cf48131 --- /dev/null +++ b/src/util/uthash/src/utringbuffer.h @@ -0,0 +1,108 @@ +/* +Copyright (c) 2015-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a ring-buffer implementation using macros + */ +#ifndef UTRINGBUFFER_H +#define UTRINGBUFFER_H + +#define UTRINGBUFFER_VERSION 2.3.0 + +#include +#include +#include "utarray.h" // for "UT_icd" + +typedef struct { + unsigned i; /* index of next available slot; wraps at n */ + unsigned n; /* capacity */ + unsigned char f; /* full */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz */ +} UT_ringbuffer; + +#define utringbuffer_init(a, _n, _icd) do { \ + memset(a, 0, sizeof(UT_ringbuffer)); \ + (a)->icd = *(_icd); \ + (a)->n = (_n); \ + if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \ +} while(0) + +#define utringbuffer_clear(a) do { \ + if ((a)->icd.dtor) { \ + if ((a)->f) { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } else { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } \ + } \ + (a)->i = 0; \ + (a)->f = 0; \ +} while(0) + +#define utringbuffer_done(a) do { \ + utringbuffer_clear(a); \ + free((a)->d); (a)->d = NULL; \ + (a)->n = 0; \ +} while(0) + +#define utringbuffer_new(a,n,_icd) do { \ + a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \ + utringbuffer_init(a, n, _icd); \ +} while(0) + +#define utringbuffer_free(a) do { \ + utringbuffer_done(a); \ + free(a); \ +} while(0) + +#define utringbuffer_push_back(a,p) do { \ + if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \ + if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \ + else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \ + if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \ +} while(0) + +#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i) +#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f) +#define utringbuffer_full(a) ((a)->f != 0) + +#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) +#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL) + +#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) +#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e)) + +#define utringbuffer_front(a) utringbuffer_eltptr(a,0) +#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1)) +#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1)) +#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1)) + +#endif /* UTRINGBUFFER_H */ diff --git a/src/util/uthash/src/utstack.h b/src/util/uthash/src/utstack.h new file mode 100644 index 0000000..2dbfec8 --- /dev/null +++ b/src/util/uthash/src/utstack.h @@ -0,0 +1,88 @@ +/* +Copyright (c) 2018-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTSTACK_H +#define UTSTACK_H + +#define UTSTACK_VERSION 2.3.0 + +/* + * This file contains macros to manipulate a singly-linked list as a stack. + * + * To use utstack, your structure must have a "next" pointer. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *next; + * } + * + * struct item *stack = NULL: + * + * int main() { + * int count; + * struct item *tmp; + * struct item *item = malloc(sizeof *item); + * item->id = 42; + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * STACK_PUSH(stack, item); + * STACK_COUNT(stack, tmp, count); assert(count == 1); + * STACK_POP(stack, item); + * free(item); + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * } + * -------------------------------------------------- + */ + +#define STACK_TOP(head) (head) + +#define STACK_EMPTY(head) (!(head)) + +#define STACK_PUSH(head,add) \ + STACK_PUSH2(head,add,next) + +#define STACK_PUSH2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define STACK_POP(head,result) \ + STACK_POP2(head,result,next) + +#define STACK_POP2(head,result,next) \ +do { \ + (result) = (head); \ + (head) = (head)->next; \ +} while (0) + +#define STACK_COUNT(head,el,counter) \ + STACK_COUNT2(head,el,counter,next) \ + +#define STACK_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \ +} while (0) + +#endif /* UTSTACK_H */ diff --git a/src/util/uthash/src/utstring.h b/src/util/uthash/src/utstring.h index 5ad3c4a..009b4c8 100644 --- a/src/util/uthash/src/utstring.h +++ b/src/util/uthash/src/utstring.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ +Copyright (c) 2008-2021, Troy D. Hanson http://troydhanson.github.com/uthash/ All rights reserved. Redistribution and use in source and binary forms, with or without @@ -21,36 +21,49 @@ 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 +/* a dynamic string implementation using macros */ #ifndef UTSTRING_H #define UTSTRING_H -#define UTSTRING_VERSION 1.9.8 - -#ifdef __GNUC__ -#define _UNUSED_ __attribute__ ((__unused__)) -#else -#define _UNUSED_ -#endif +#define UTSTRING_VERSION 2.3.0 #include #include +#include #include -#define oom() exit(-1) + +#ifdef __GNUC__ +#define UTSTRING_UNUSED __attribute__((__unused__)) +#else +#define UTSTRING_UNUSED +#endif + +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." +#define utstring_oom() oom() +#endif + +#ifndef utstring_oom +#define utstring_oom() exit(-1) +#endif typedef struct { - char *d; - size_t n; /* allocd size */ + char *d; /* pointer to allocated buffer */ + size_t n; /* allocated capacity */ 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; \ + char *utstring_tmp = (char*)realloc( \ + (s)->d, (s)->n + (amt)); \ + if (!utstring_tmp) { \ + utstring_oom(); \ + } \ + (s)->d = utstring_tmp; \ + (s)->n += (amt); \ } \ } while(0) @@ -58,7 +71,7 @@ do { \ do { \ (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ utstring_reserve(s,100); \ - (s)->d[0] = '\0'; \ + (s)->d[0] = '\0'; \ } while(0) #define utstring_done(s) \ @@ -75,9 +88,11 @@ do { \ #define utstring_new(s) \ do { \ - s = (UT_string*)calloc(sizeof(UT_string),1); \ - if (!s) oom(); \ - utstring_init(s); \ + (s) = (UT_string*)malloc(sizeof(UT_string)); \ + if (!(s)) { \ + utstring_oom(); \ + } \ + utstring_init(s); \ } while(0) #define utstring_renew(s) \ @@ -97,10 +112,10 @@ do { \ #define utstring_bincpy(s,b,l) \ do { \ - utstring_reserve((s),(l)+1); \ + utstring_reserve((s),(l)+1); \ if (l) memcpy(&(s)->d[(s)->i], b, l); \ - (s)->i += l; \ - (s)->d[(s)->i]='\0'; \ + (s)->i += (l); \ + (s)->d[(s)->i]='\0'; \ } while(0) #define utstring_concat(dst,src) \ @@ -111,14 +126,14 @@ do { \ (dst)->d[(dst)->i]='\0'; \ } while(0) -#define utstring_len(s) ((unsigned)((s)->i)) +#define utstring_len(s) ((s)->i) #define utstring_body(s) ((s)->d) -_UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { +UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { int n; va_list cp; - while (1) { + for (;;) { #ifdef _WIN32 cp = ap; #else @@ -127,7 +142,7 @@ _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list a n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); va_end(cp); - if ((n > -1) && (n < (int)(s->n-s->i))) { + if ((n > -1) && ((size_t) n < (s->n-s->i))) { s->i += n; return; } @@ -142,7 +157,7 @@ _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list a static void utstring_printf(UT_string *s, const char *fmt, ...) __attribute__ (( format( printf, 2, 3) )); #endif -_UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) { +UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { va_list ap; va_start(ap,fmt); utstring_printf_va(s,fmt,ap); @@ -153,9 +168,9 @@ _UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) { * begin substring search functions * ******************************************************************************/ /* Build KMP table from left to right. */ -_UNUSED_ static void _utstring_BuildTable( - const char *P_Needle, - size_t P_NeedleLen, +UTSTRING_UNUSED static void _utstring_BuildTable( + const char *P_Needle, + size_t P_NeedleLen, long *P_KMP_Table) { long i, j; @@ -163,7 +178,7 @@ _UNUSED_ static void _utstring_BuildTable( i = 0; j = i - 1; P_KMP_Table[i] = j; - while (i < P_NeedleLen) + while (i < (long) P_NeedleLen) { while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) { @@ -171,7 +186,7 @@ _UNUSED_ static void _utstring_BuildTable( } i++; j++; - if (i < P_NeedleLen) + if (i < (long) P_NeedleLen) { if (P_Needle[i] == P_Needle[j]) { @@ -193,9 +208,9 @@ _UNUSED_ static void _utstring_BuildTable( /* Build KMP table from right to left. */ -_UNUSED_ static void _utstring_BuildTableR( - const char *P_Needle, - size_t P_NeedleLen, +UTSTRING_UNUSED static void _utstring_BuildTableR( + const char *P_Needle, + size_t P_NeedleLen, long *P_KMP_Table) { long i, j; @@ -205,7 +220,7 @@ _UNUSED_ static void _utstring_BuildTableR( P_KMP_Table[i + 1] = j; while (i >= 0) { - while ( (j < P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) + while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) { j = P_KMP_Table[j + 1]; } @@ -233,11 +248,11 @@ _UNUSED_ static void _utstring_BuildTableR( /* Search data from left to right. ( Multiple search mode. ) */ -_UNUSED_ static long _utstring_find( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, +UTSTRING_UNUSED static long _utstring_find( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, long *P_KMP_Table) { long i, j; @@ -266,11 +281,11 @@ _UNUSED_ static long _utstring_find( /* Search data from right to left. ( Multiple search mode. ) */ -_UNUSED_ static long _utstring_findR( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, +UTSTRING_UNUSED static long _utstring_findR( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, long *P_KMP_Table) { long i, j; @@ -300,10 +315,10 @@ _UNUSED_ static long _utstring_findR( /* Search data from left to right. ( One time search mode. ) */ -_UNUSED_ static long utstring_find( - UT_string *s, +UTSTRING_UNUSED static long utstring_find( + UT_string *s, long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, + const char *P_Needle, size_t P_NeedleLen) { long V_StartPosition; @@ -320,17 +335,17 @@ _UNUSED_ static long utstring_find( V_StartPosition = P_StartPosition; } V_HaystackLen = s->i - V_StartPosition; - if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) { V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); if (V_KMP_Table != NULL) { _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); - V_FindPosition = _utstring_find(s->d + V_StartPosition, - V_HaystackLen, - P_Needle, - P_NeedleLen, + V_FindPosition = _utstring_find(s->d + V_StartPosition, + V_HaystackLen, + P_Needle, + P_NeedleLen, V_KMP_Table); if (V_FindPosition >= 0) { @@ -346,10 +361,10 @@ _UNUSED_ static long utstring_find( /* Search data from right to left. ( One time search mode. ) */ -_UNUSED_ static long utstring_findR( - UT_string *s, +UTSTRING_UNUSED static long utstring_findR( + UT_string *s, long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, + const char *P_Needle, size_t P_NeedleLen) { long V_StartPosition; @@ -366,17 +381,17 @@ _UNUSED_ static long utstring_findR( V_StartPosition = P_StartPosition; } V_HaystackLen = V_StartPosition + 1; - if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) ) + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) { V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); if (V_KMP_Table != NULL) { _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); - V_FindPosition = _utstring_findR(s->d, - V_HaystackLen, - P_Needle, - P_NeedleLen, + V_FindPosition = _utstring_findR(s->d, + V_HaystackLen, + P_Needle, + P_NeedleLen, V_KMP_Table); free(V_KMP_Table); diff --git a/src/util/uthash/tests/README b/src/util/uthash/tests/README deleted file mode 100644 index 7b03924..0000000 --- a/src/util/uthash/tests/README +++ /dev/null @@ -1,116 +0,0 @@ -Automated tests for uthash -============================================================================== -Run "make" in this directory to build the tests and run them. - -test1: make 10-item hash, iterate and print each one -test2: make 10-item hash, lookup items with even keys, print -test3: make 10-item hash, delete items with even keys, print others -test4: 10 structs have dual hash handles, separate keys -test5: 10 structs have dual hash handles, lookup evens by alt key -test6: test alt malloc macros -test7: test alt malloc macros with 1000 structs so bucket expansion occurs -test8: test num_items counter in UT_hash_handle -test9: test "find" after bucket expansion -test10: dual-hash handle test, bucket expansion on one and not the other -test11: read dat file of names into hash, sort them and print -test12: create hash with string keys, add 10 items, lookup each item -test13: make 10-item hash, delete items with even keys, reverse print others -test14: read dat file of names into hash, read file again and lookup each one -test15: build string-keyed hash of 3 items, lookup one item (c.f. test40.c) -test16: hash on aggregate key, iterate, lookup, using generalized macros -test17: sort, add more items, sort again -test18: test pathological HASH_DEL(a,a) scenario (single head,deletee variable) -test19: sort two hash tables with shared elements using HASH_SRT -test20: test a 5-byte "binary" key -test21: test a structure key (userguide) -test22: test multi-field key using flexible array member (userguide utf32) -test23: test whether delete in iteration works -test24: make 10-item hash and confirm item count (HASH_COUNT) -test25: CDL / DL / LL tests -test26: test the linked list sort macros in utlist.h -test27: LL_APPEND, SORT -test28: CDL / DL / LL tests -test29: DL_APPEND, SORT -test30: CDL_PREPEND, SORT -test31: CDL_PREPEND, SORT -test32: DL_PREPEND -test33: LL_PREPEND -test34: CDL_PREPEND -test35: CDL_PREPEND -test36: HASH_SELECT -test37: HASH_CLEAR -test38: find-or-add test on integer keys in short loop -test39: HASH_ADD_KEYPTR then HASH_FIND using array element as key pointer -test40: HASH_ADD_KEYPTR on string keys; pointer equivalent to test15.c -test41: test LL_FOREACH_SAFE,DL_FOREACH_SAFE,CDL_FOREACH_SAFE -test42: test LL_SEARCH, LL_SEARCH_SCALAR, and DL and CDL counterparts -test43: test utarray with intpair objects -test44: test utarray with int objects -test45: test utarray with int objects -test46: test utarray with char* objects -test47: test utstring -test48: test utarray of int -test49: test utarray of str -test50: test utarray of long -test51: test utarray of intpair -test52: test utarray of intchar -test53: test utstring -test54: test utstring -test55: test utstring -test56: test uthash, utlist and utstring together for #define conflicts etc -test57: test uthash HASH_ADD_PTR and HASH_FIND_PTR -test58: test HASH_ITER macro -test59: sample of multi-level hash -test60: sample of multi-level hash that also does HASH_DEL and free -test61: test utarray_find -test62: test macros used in safe unaligned reads on non-Intel type platforms -test63: LL_CONCAT test -test64: DL_CONCAT test -test65: LRU cache example courtesy of jehiah.cz with modifications -test66: test example where output variable to HASH_FIND needs extra parens -test67: test utarray_prev -test68: test DL_REPLACE_ELEM (Zoltán Lajos Kis) -test69: test DL_PREPEND_ELEM (Zoltán Lajos Kis) -test70: test LL_REPLACE_ELEM (Zoltán Lajos Kis) -test71: test LL_PREPEND_ELEM (Zoltán Lajos Kis) -test72: test CDL_REPLACE_ELEM (Zoltán Lajos Kis) -test73: test CDL_PREPEND_ELEM (Zoltán Lajos Kis) -test74: test utstring with utstring_find (Joe Wei) -test75: test utstring with utstring_findR (Joe Wei) -test76: test utstring with _utstring_find (Joe Wei) -test77: test utstring with _utstring_findR (Joe Wei) -test78: test utlist "2" family with flexible Prev/Next naming eg. DL_DELETE2 -test79: test HASH_REPLACE -test80: test utarray_insert past end of array -test81: test utarray_insert past end of array -test82: test utarray_inserta past end of array -test83: test HASH_OVERHEAD -test84: test HASH_OVERHEAD on hash with bloom filter - - -Other Make targets -================================================================================ -pedantic: makes the tests with extra CFLAGS for pedantic compiling -cplusplus: compiles all the C tests using the C++ compiler to test compatibility -debug: makes the tests with debugging symbols and no optimization -example: builds the 'example' program from the user guide -================================================================================ - -Other files -================================================================================ -keystats: key statistics analyzer. See the User Guide (http://uthash.sf.net) -emit_keys: reads a data file of unique strings, emits as keys w/HASH_EMIT_KEYS=1 -all_funcs: a script which executes the test suite with every hash function -win32tests:builds and runs the test suite under Microsoft Visual Studio - -LINUX-ONLY ----------- -hashscan: tool to examine a running process and get info on its hash tables -test_sleep:used as a subject for inspection by hashscan - -Manual performance testing -================================================================================ - # test performance characteristics on keys that are English dictionary words - emit_keys /usr/share/dict/words > words.keys - ./keystats words.keys - diff --git a/src/util/uthash/tests/all_funcs b/src/util/uthash/tests/all_funcs deleted file mode 100755 index 18df8a1..0000000 --- a/src/util/uthash/tests/all_funcs +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -function proceed { - read -p "proceed ? [n] " response - if [ "$response" != "y" ]; then exit -1; fi -} - -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_BER'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SAX'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_FNV'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_OAT'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_JEN'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_MUR'; proceed -make clean tests_only EXTRA_CFLAGS='-DHASH_FUNCTION=HASH_SFH'; diff --git a/src/util/uthash/tests/bloom_perf.c b/src/util/uthash/tests/bloom_perf.c deleted file mode 100644 index 58b3002..0000000 --- a/src/util/uthash/tests/bloom_perf.c +++ /dev/null @@ -1,64 +0,0 @@ -#include /* malloc */ -#include /* gettimeofday */ -#include /* perror */ -#include /* printf */ -#include "uthash.h" - -#define BUFLEN 20 -#if 0 -#undef uthash_expand_fyi -#define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) -#endif - -typedef struct name_rec { - char boy_name[BUFLEN]; - UT_hash_handle hh; -} name_rec; - -int main(int argc,char *argv[]) { - name_rec *name, *names=NULL; - char linebuf[BUFLEN]; - FILE *file; - int i=0,j,nloops=3,loopnum=0,miss; - struct timeval tv1,tv2; - long elapsed_usec; - if (argc > 1) nloops = atoi(argv[1]); - - if ( (file = fopen( "test14.dat", "r" )) == NULL ) { - perror("can't open: "); - exit(-1); - } - - while (fgets(linebuf,BUFLEN,file) != NULL) { - i++; - if ( (name = (name_rec*)malloc(sizeof(name_rec))) == NULL) exit(-1); - strncpy(name->boy_name,linebuf,BUFLEN); - HASH_ADD_STR(names,boy_name,name); - } - - again: - if (fseek(file,0,SEEK_SET) == -1) { - fprintf(stderr,"fseek failed: %s\n", strerror(errno)); - } - j=0; - - if (gettimeofday(&tv1,NULL) == -1) perror("gettimeofday: "); - while (fgets(linebuf,BUFLEN,file) != NULL) { - /* if we do 10 loops, the first has a 0% miss rate, - * the second has a 10% miss rate, etc */ - miss = ((rand()*1.0/RAND_MAX) < (loopnum*1.0/nloops)) ? 1 : 0; - /* generate a miss if we want one */ - if (miss) { linebuf[0]++; if (linebuf[1] != '\0') linebuf[1]++; } - HASH_FIND_STR(names,linebuf,name); - if (name) j++; - } - if (gettimeofday(&tv2,NULL) == -1) perror("gettimeofday: "); - elapsed_usec = ((tv2.tv_sec - tv1.tv_sec) * 1000000) + (tv2.tv_usec - tv1.tv_usec); - printf("lookup on %d of %d (%.2f%%) names succeeded (%.2f usec)\n", j, i, - j*100.0/i, (double)(elapsed_usec)); - if (++loopnum < nloops) goto again; - fclose(file); - - return 0; -} - diff --git a/src/util/uthash/tests/bloom_perf.sh b/src/util/uthash/tests/bloom_perf.sh deleted file mode 100755 index 0a04f23..0000000 --- a/src/util/uthash/tests/bloom_perf.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -BITS="16" - -cc -I../src -O3 -Wall -m64 bloom_perf.c -o bloom_perf.none -for bits in $BITS -do -cc -I../src -DHASH_BLOOM=$bits -O3 -Wall -m64 bloom_perf.c -o bloom_perf.$bits -done - -for bits in none $BITS -do -echo -echo "using $bits-bit filter:" -./bloom_perf.$bits 10 -done - diff --git a/src/util/uthash/tests/do_tests b/src/util/uthash/tests/do_tests deleted file mode 100755 index 574403f..0000000 --- a/src/util/uthash/tests/do_tests +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -my @tests; -for (glob "test*[0-9]") { - push @tests, $_ if -e "$_.ans"; -} - -my $num_failed=0; - -for my $test (@tests) { - `./$test > $test.out`; - `diff $test.out $test.ans`; - print "$test failed\n" if $?; - $num_failed++ if $?; -} - -print scalar @tests . " tests conducted, $num_failed failed.\n"; -exit $num_failed; diff --git a/src/util/uthash/tests/do_tests.cygwin b/src/util/uthash/tests/do_tests.cygwin deleted file mode 100755 index 0c01ebe..0000000 --- a/src/util/uthash/tests/do_tests.cygwin +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -my @tests; -for (glob "test*[0-9].exe") { - push @tests, "$_" if -e substr($_, 0, - 4).".ans"; -} - -my $num_failed=0; - -for my $test (@tests) { - `./$test > $test.out`; - my $ansfile = substr($test, 0, - 4).".ans"; - `diff $test.out $ansfile`; - print "$test failed\n" if $?; - $num_failed++ if $?; -} - -print scalar @tests . " tests conducted, $num_failed failed.\n"; -exit $num_failed; diff --git a/src/util/uthash/tests/do_tests.mingw b/src/util/uthash/tests/do_tests.mingw deleted file mode 100644 index 1820334..0000000 --- a/src/util/uthash/tests/do_tests.mingw +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -echo "MinGW test script starting" - -for f in test*.exe -do - t=`echo $f | sed s/.exe//` - `$f > $t.out` - diff -qb "$t.out" "$t.ans" - if [ $? -eq 1 ] - then - echo "$f failed" - else - true # can't have empty else - #echo "$f passed" - fi -done - -echo -echo "All tests complete" diff --git a/src/util/uthash/tests/do_tests_win32.cmd b/src/util/uthash/tests/do_tests_win32.cmd deleted file mode 100644 index be89301..0000000 --- a/src/util/uthash/tests/do_tests_win32.cmd +++ /dev/null @@ -1,16 +0,0 @@ -:: this compiles and runs the test suite under Visual Studio 2008 -::@echo off -call "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat" > vc.out -::call "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" > vc.out -set "COMPILE=cl.exe /I ..\src /EHsc /nologo" -echo compiling... -%COMPILE% tdiff.cpp > compile.out -::for %%f in (test*.c) do %COMPILE% /Tp %%f >> compile.out -for %%f in (test*.c) do %COMPILE% /Tc %%f >> compile.out -echo running tests... -for %%f in (test*.exe) do %%f > %%~nf.out -echo scanning for failures... -for %%f in (test*.out) do tdiff %%f %%~nf.ans -echo tests completed -::for %%f in (test*.out test*.obj test*.exe vc.out compile.out tdiff.obj tdiff.exe) do del %%f -pause diff --git a/src/util/uthash/tests/emit_keys.c b/src/util/uthash/tests/emit_keys.c deleted file mode 100644 index 8a0c0cd..0000000 --- a/src/util/uthash/tests/emit_keys.c +++ /dev/null @@ -1,44 +0,0 @@ -#include /* malloc */ -#include /* perror */ -#include /* printf */ -#include /* write */ - -/* this define must precede uthash.h */ -#define HASH_EMIT_KEYS 1 -#include "uthash.h" - -#define BUFLEN 30 - -typedef struct name_rec { - char boy_name[BUFLEN]; - UT_hash_handle hh; -} name_rec; - -int main(int argc,char *argv[]) { - name_rec *name, *names=NULL; - char linebuf[BUFLEN]; - FILE *file; - int i=0; - - if (argc != 2) { - fprintf(stderr,"usage: %s file\n", argv[0]); - exit(-1); - } - - if ( (file = fopen( argv[1], "r" )) == NULL ) { - perror("can't open: "); - exit(-1); - } - - while (fgets(linebuf,BUFLEN,file) != NULL) { - if ( (name = (name_rec*)malloc(sizeof(name_rec))) == NULL) exit(-1); - strncpy(name->boy_name,linebuf,BUFLEN); - HASH_ADD_STR(names,boy_name,name); - i++; - } - - fprintf(stderr,"%d keys emitted.\n", i); - fclose(file); - return 0; -} - diff --git a/src/util/uthash/tests/example.c b/src/util/uthash/tests/example.c deleted file mode 100644 index d0dca0c..0000000 --- a/src/util/uthash/tests/example.c +++ /dev/null @@ -1,135 +0,0 @@ -#include /* gets */ -#include /* atoi, malloc */ -#include /* strcpy */ -#include "uthash.h" - -struct my_struct { - int id; /* key */ - char name[10]; - UT_hash_handle hh; /* makes this structure hashable */ -}; - -struct my_struct *users = NULL; - -void add_user(int user_id, char *name) { - struct my_struct *s; - - HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */ - if (s==NULL) { - s = (struct my_struct*)malloc(sizeof(struct my_struct)); - s->id = user_id; - HASH_ADD_INT( users, id, s ); /* id: name of key field */ - } - strcpy(s->name, name); -} - -struct my_struct *find_user(int user_id) { - struct my_struct *s; - - HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */ - return s; -} - -void delete_user(struct my_struct *user) { - HASH_DEL( users, user); /* user: pointer to deletee */ - free(user); -} - -void delete_all() { - struct my_struct *current_user, *tmp; - - HASH_ITER(hh, users, current_user, tmp) { - HASH_DEL(users,current_user); /* delete it (users advances to next) */ - free(current_user); /* free it */ - } -} - -void print_users() { - struct my_struct *s; - - for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) { - printf("user id %d: name %s\n", s->id, s->name); - } -} - -int name_sort(struct my_struct *a, struct my_struct *b) { - return strcmp(a->name,b->name); -} - -int id_sort(struct my_struct *a, struct my_struct *b) { - return (a->id - b->id); -} - -void sort_by_name() { - HASH_SORT(users, name_sort); -} - -void sort_by_id() { - HASH_SORT(users, id_sort); -} - -int main(int argc, char *argv[]) { - char in[10]; - int id=1, running=1; - struct my_struct *s; - unsigned num_users; - - while (running) { - printf(" 1. add user\n"); - printf(" 2. add/rename user by id\n"); - printf(" 3. find user\n"); - printf(" 4. delete user\n"); - printf(" 5. delete all users\n"); - printf(" 6. sort items by name\n"); - printf(" 7. sort items by id\n"); - printf(" 8. print users\n"); - printf(" 9. count users\n"); - printf("10. quit\n"); - gets(in); - switch(atoi(in)) { - case 1: - printf("name?\n"); - add_user(id++, gets(in)); - break; - case 2: - printf("id?\n"); - gets(in); id = atoi(in); - printf("name?\n"); - add_user(id, gets(in)); - break; - case 3: - printf("id?\n"); - s = find_user(atoi(gets(in))); - printf("user: %s\n", s ? s->name : "unknown"); - break; - case 4: - printf("id?\n"); - s = find_user(atoi(gets(in))); - if (s) delete_user(s); - else printf("id unknown\n"); - break; - case 5: - delete_all(); - break; - case 6: - sort_by_name(); - break; - case 7: - sort_by_id(); - break; - case 8: - print_users(); - break; - case 9: - num_users=HASH_COUNT(users); - printf("there are %u users\n", num_users); - break; - case 10: - running=0; - break; - } - } - - delete_all(); /* free any structures */ - return 0; -} diff --git a/src/util/uthash/tests/hashscan.c b/src/util/uthash/tests/hashscan.c deleted file mode 100644 index ea6c5ff..0000000 --- a/src/util/uthash/tests/hashscan.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -Copyright (c) 2005-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __FreeBSD__ -#include /* MAXPATHLEN */ -#include /* VM_PROT_* flags */ -#endif - -/* need this defined so offsetof can give us bloom offsets in UT_hash_table */ -#define HASH_BLOOM 16 -#include "uthash.h" - -#ifdef __FreeBSD__ -typedef struct { - void *start; - void *end; -} vma_t; -#else -typedef struct { - off_t start; - off_t end; - char perms[4]; /* rwxp */ - char device[5]; /* fd:01 or 00:00 */ -} vma_t; -#endif - -const uint32_t sig = HASH_SIGNATURE; -int verbose=0; -int getkeys=0; - -#define vv(...) do {if (verbose>0) printf(__VA_ARGS__);} while(0) -#define vvv(...) do {if (verbose>1) printf(__VA_ARGS__);} while(0) - -/* these id's are arbitrary, only meaningful within this file */ -#define JEN 1 -#define BER 2 -#define SFH 3 -#define SAX 4 -#define FNV 5 -#define OAT 6 -#define MUR 7 -#define NUM_HASH_FUNCS 8 /* includes id 0, the non-function */ -char *hash_fcns[] = {"???","JEN","BER","SFH","SAX","FNV","OAT","MUR"}; - -/* given a peer key/len/hashv, reverse engineer its hash function */ -int infer_hash_function(char *key, size_t keylen, uint32_t hashv) { - uint32_t obkt, ohashv, num_bkts=0x01000000; /* anything ok */ - /* BER SAX FNV OAT JEN SFH */ - HASH_JEN(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return JEN; - HASH_BER(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return BER; - HASH_SFH(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return SFH; - HASH_SAX(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return SAX; - HASH_FNV(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return FNV; - HASH_OAT(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return OAT; - HASH_MUR(key,keylen,num_bkts,ohashv,obkt); if (ohashv == hashv) return MUR; - obkt++; // this quiets an unused variable warning. yes, this is a ugly hack - return 0; -} - -/* read peer's memory from addr for len bytes, store into our dst */ -#ifdef __FreeBSD__ -int read_mem(void *dst, pid_t pid, void *start, size_t len) { - struct ptrace_io_desc io_desc; - int ret; - - io_desc.piod_op = PIOD_READ_D; - io_desc.piod_offs = start; - io_desc.piod_addr = dst; - io_desc.piod_len = len; - - ret = ptrace(PT_IO, pid, (void *) &io_desc, 0); - - if (ret) { - vv("read_mem: ptrace failed: %s\n", strerror(errno)); - return -1; - } else if (io_desc.piod_len != len) { - vv("read_mem: short read!\n"); - return -1; - } - - return 0; -} -#else -int read_mem(void *dst, int fd, off_t start, size_t len) { - int rc; - size_t bytes_read=0; - if (lseek(fd, start, SEEK_SET) == (off_t)-1) { - fprintf(stderr, "lseek failed: %s\n", strerror(errno)); - return -1; - } - while ( len && ((rc=read(fd, (char*)dst+bytes_read, len)) > 0)) { - len -= rc; - bytes_read += rc; - } - if (rc==-1) vv("read_mem failed (%s)\n",strerror(errno)); - if ((len != 0 && rc >= 0)) vv("INTERNAL ERROR\n"); - return (rc == -1) ? -1 : 0; -} -#endif - -/* later compensate for possible presence of bloom filter */ -char *tbl_from_sig_addr(char *sig) { - return (sig - offsetof(UT_hash_table,signature)); -} - -#define HS_BIT_TEST(v,i) (v[i/8] & (1U << (i%8))) -void found(int fd, char* peer_sig, pid_t pid) { - UT_hash_table *tbl=NULL; - UT_hash_bucket *bkts=NULL; - UT_hash_handle hh; - size_t i, bloom_len, bloom_bitlen, bloom_on_bits=0,bloom_off_bits=0; - char *peer_tbl, *peer_bloom_sig, *peer_bloom_nbits, *peer_bloombv_ptr, - *peer_bloombv, *peer_bkts, *peer_key, *peer_hh, *key=NULL, - *hash_fcn=NULL, sat[10]; - unsigned char *bloombv=NULL; - static int fileno=0; - char keyfile[50]; - unsigned char bloom_nbits=0; - int keyfd=-1, mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, - hash_fcn_hits[NUM_HASH_FUNCS], hash_fcn_winner; - unsigned max_chain=0; - uint32_t bloomsig; - double bloom_sat=0; - snprintf(sat,sizeof(sat)," "); - for(i=0; i < NUM_HASH_FUNCS; i++) hash_fcn_hits[i]=0; - - if (getkeys) { - snprintf(keyfile, sizeof(keyfile), "/tmp/%u-%u.key", (unsigned)pid,fileno++); - if ( (keyfd = open(keyfile, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) { - fprintf(stderr, "can't open %s: %s\n", keyfile, strerror(errno)); - exit(-1); - } - } - - vv("found signature at peer %p\n", peer_sig); - peer_tbl = tbl_from_sig_addr(peer_sig); - vvv("reading table at peer %p\n", peer_tbl); - - if ( (tbl = (UT_hash_table*)malloc(sizeof(UT_hash_table))) == NULL) { - fprintf(stderr, "out of memory\n"); - exit(-1); - } -#ifdef __FreeBSD__ - if (read_mem(tbl, pid, (void *)peer_tbl, sizeof(UT_hash_table)) != 0) { -#else - if (read_mem(tbl, fd, (off_t)peer_tbl, sizeof(UT_hash_table)) != 0) { -#endif - fprintf(stderr, "failed to read peer memory\n"); - goto done; - } - - /* got the table. how about the buckets */ - peer_bkts = (char*)tbl->buckets; - vvv("reading buckets at peer %p\n", peer_bkts); - bkts = (UT_hash_bucket*)malloc(sizeof(UT_hash_bucket)*tbl->num_buckets); - if (bkts == NULL) { - fprintf(stderr, "out of memory\n"); - exit(-1); - } -#ifdef __FreeBSD__ - if (read_mem(bkts, pid, (void *)peer_bkts, sizeof(UT_hash_bucket)*tbl->num_buckets) != 0) { -#else - if (read_mem(bkts, fd, (off_t)peer_bkts, sizeof(UT_hash_bucket)*tbl->num_buckets) != 0) { -#endif - fprintf(stderr, "failed to read peer memory\n"); - goto done; - } - - vvv("scanning %u peer buckets\n", tbl->num_buckets); - for(i=0; i < tbl->num_buckets; i++) { - vvv("bucket %u has %u items\n", (unsigned)i, (unsigned)(bkts[i].count)); - if (bkts[i].count > max_chain) max_chain = bkts[i].count; - if (bkts[i].expand_mult) vvv(" bucket %u has expand_mult %u\n", (unsigned)i, (unsigned)(bkts[i].expand_mult)); - - vvv("scanning bucket %u chain:\n", (unsigned)i); - peer_hh = (char*)bkts[i].hh_head; - while(peer_hh) { -#ifdef __FreeBSD__ - if (read_mem(&hh, pid, (void *)peer_hh, sizeof(hh)) != 0) { -#else - if (read_mem(&hh, fd, (off_t)peer_hh, sizeof(hh)) != 0) { -#endif - fprintf(stderr, "failed to read peer memory\n"); - goto done; - } - if ((char*)hh.tbl != peer_tbl) goto done; - peer_hh = (char*)hh.hh_next; - peer_key = (char*)(hh.key); - /* malloc space to read the key, and read it */ - if ( (key = (char*)malloc(sizeof(hh.keylen))) == NULL) { - fprintf(stderr, "out of memory\n"); - exit(-1); - } -#ifdef __FreeBSD__ - if (read_mem(key, pid, (void*)peer_key, hh.keylen) != 0) { -#else - if (read_mem(key, fd, (off_t)peer_key, hh.keylen) != 0) { -#endif - fprintf(stderr, "failed to read peer memory\n"); - goto done; - } - hash_fcn_hits[infer_hash_function(key,hh.keylen,hh.hashv)]++; - /* write the key if requested */ - if (getkeys) { - write(keyfd, &hh.keylen, sizeof(unsigned)); - write(keyfd, key, hh.keylen); - } - free(key); key=NULL; - } - } - - /* does it have a bloom filter? */ - peer_bloom_sig = peer_tbl + offsetof(UT_hash_table, bloom_sig); - peer_bloombv_ptr = peer_tbl + offsetof(UT_hash_table, bloom_bv); - peer_bloom_nbits = peer_tbl + offsetof(UT_hash_table, bloom_nbits); - vvv("looking for bloom signature at peer %p\n", peer_bloom_sig); -#ifdef __FreeBSD__ - if ((read_mem(&bloomsig, pid, (void *)peer_bloom_sig, sizeof(uint32_t)) == 0) && - (bloomsig == HASH_BLOOM_SIGNATURE)) { -#else - if ((read_mem(&bloomsig, fd, (off_t)peer_bloom_sig, sizeof(uint32_t)) == 0) && - (bloomsig == HASH_BLOOM_SIGNATURE)) { -#endif - vvv("bloom signature (%x) found\n",bloomsig); - /* bloom found. get at bv, nbits */ -#ifdef __FreeBSD__ - if (read_mem(&bloom_nbits, pid, (void *)peer_bloom_nbits, sizeof(char)) == 0) { -#else - if (read_mem(&bloom_nbits, fd, (off_t)peer_bloom_nbits, sizeof(char)) == 0) { -#endif - /* scan bloom filter, calculate saturation */ - bloom_bitlen = (1ULL << bloom_nbits); - bloom_len = (bloom_bitlen / 8) + ((bloom_bitlen % 8) ? 1 : 0); - vvv("bloom bitlen is %u, bloom_bytelen is %u\n", (unsigned)bloom_bitlen, (unsigned)bloom_len); - if ( (bloombv = (unsigned char*)malloc(bloom_len)) == NULL) { - fprintf(stderr, "out of memory\n"); - exit(-1); - } - /* read the address of the bitvector in the peer, then read the bv itself */ -#ifdef __FreeBSD__ - if ((read_mem(&peer_bloombv, pid, (void *)peer_bloombv_ptr, sizeof(void*)) == 0) && - (read_mem(bloombv, pid, (void *)peer_bloombv, bloom_len) == 0)) { -#else - if ((read_mem(&peer_bloombv, fd, (off_t)peer_bloombv_ptr, sizeof(void*)) == 0) && - (read_mem(bloombv, fd, (off_t)peer_bloombv, bloom_len) == 0)) { -#endif - /* calculate saturation */ - vvv("read peer bloom bitvector from %p (%u bytes)\n", peer_bloombv, (unsigned)bloom_len); - for(i=0; i < bloom_bitlen; i++) { - if (HS_BIT_TEST(bloombv,(unsigned)i)) { - /* vvv("bit %u set\n",(unsigned)i); */ - bloom_on_bits++; - } else bloom_off_bits++; - } - vvv("there were %u on_bits among %u total bits\n", (unsigned)bloom_on_bits, (unsigned)bloom_bitlen); - bloom_sat = bloom_on_bits * 100.0 / bloom_bitlen; - snprintf(sat,sizeof(sat),"%2u %5.0f%%", bloom_nbits, bloom_sat); - } - } - } - - /* choose apparent hash function */ - hash_fcn_winner=0; - for(i=0;i hash_fcn_hits[hash_fcn_winner]) hash_fcn_winner=i; - } - hash_fcn = hash_fcns[hash_fcn_winner]; - -/* -Address items ideal buckets mxch/<10 fl bloom/sat fcn keys saved to ------------------- -------- ----- -------- -------- -- --------- --- ------------- -0x0123456789abcdef 10000000 98% 32000000 10 100% ok BER /tmp/9110-0.key -0x0123456789abcdef 10000000 100% 32000000 9 90% NX 27/0.010% BER /tmp/9110-1.key -*/ - printf("Address ideal items buckets mc fl bloom/sat fcn keys saved to\n"); - printf("------------------ ----- -------- -------- -- -- --------- --- -------------\n"); - printf("%-18p %4.0f%% %8u %8u %2u %s %s %s %s\n", - (void*)peer_tbl, - (tbl->num_items - tbl->nonideal_items) * 100.0 / tbl->num_items, - tbl->num_items, - tbl->num_buckets, - max_chain, - tbl->noexpand ? "NX" : "ok", - sat, - hash_fcn, - (getkeys ? keyfile : "")); - -#if 0 - printf("read peer tbl:\n"); - printf("num_buckets: %u\n", tbl->num_buckets); - printf("num_items: %u\n", tbl->num_items); - printf("nonideal_items: %u (%.2f%%)\n", tbl->nonideal_items, - tbl->nonideal_items*100.0/tbl->num_items); - printf("expand: %s\n", tbl->noexpand ? "inhibited": "normal"); - if (getkeys) printf("keys written to %s\n", keyfile); -#endif - - done: - if (bkts) free(bkts); - if (tbl) free(tbl); - if (key) free(key); - if (keyfd != -1) close(keyfd); - if (bloombv) free(bloombv); -} - - -#ifdef __FreeBSD__ -void sigscan(pid_t pid, void *start, void *end, uint32_t sig) { - struct ptrace_io_desc io_desc; - int page_size = getpagesize(); - char *buf; - char *pos; - - /* make sure page_size is a multiple of the signature size, code below assumes this */ - assert(page_size % sizeof(sig) == 0); - - buf = malloc(page_size); - - if (buf == NULL) { - fprintf(stderr, "malloc failed in sigscan()\n"); - return; - } - - io_desc.piod_op = PIOD_READ_D; - io_desc.piod_offs = start; - io_desc.piod_addr = buf; - io_desc.piod_len = page_size; - - /* read in one page after another and search sig */ - while(!ptrace(PT_IO, pid, (void *) &io_desc, 0)) { - if (io_desc.piod_len != page_size) { - fprintf(stderr, "PT_IO returned less than page size in sigscan()\n"); - return; - } - - /* iterate over the the page using the signature size and look for the sig */ - for (pos = buf; pos < (buf + page_size); pos += sizeof(sig)) { - if (*(uint32_t *) pos == sig) { - found(pid, (char *) io_desc.piod_offs + (pos - buf), pid); - } - } - - /* - * 'end' is inclusive (the address of the last valid byte), so if the current offset - * plus a page is beyond 'end', we're already done. since all vm map entries consist - * of entire pages and 'end' is inclusive, current offset plus one page should point - * exactly one byte beyond 'end'. this is assert()ed below to be on the safe side. - */ - if (io_desc.piod_offs + page_size > end) { - assert(io_desc.piod_offs + page_size == (end + 1)); - break; - } - - /* advance to the next page */ - io_desc.piod_offs += page_size; - } -} -#else -void sigscan(int fd, off_t start, off_t end, uint32_t sig, pid_t pid) { - int rlen; - uint32_t u; - off_t at=0; - - if (lseek(fd, start, SEEK_SET) == (off_t)-1) { - fprintf(stderr, "lseek failed: %s\n", strerror(errno)); - return; - } - - while ( (rlen = read(fd,&u,sizeof(u))) == sizeof(u)) { - if (!memcmp(&u,&sig,sizeof(u))) found(fd, (char*)(start+at),pid); - at += sizeof(u); - if ((off_t)(at + sizeof(u)) > end-start) break; - } - - if (rlen == -1) { - //fprintf(stderr,"read failed: %s\n", strerror(errno)); - //exit(-1); - } -} -#endif - - -#ifdef __FreeBSD__ -int scan(pid_t pid) { - vma_t *vmas=NULL, vma; - unsigned i, num_vmas = 0; - int ret; - struct ptrace_vm_entry vm_entry; - char path[MAXPATHLEN]; - - vv("attaching to peer\n"); - if (ptrace(PT_ATTACH,pid,NULL,0) == -1) { - fprintf(stderr,"failed to attach to %u: %s\n", (unsigned)pid, strerror(errno)); - exit(EXIT_FAILURE); - } - vv("waiting for peer to suspend temporarily\n"); - if (waitpid(pid,NULL,0) != pid) { - fprintf(stderr,"failed to wait for pid %u: %s\n",(unsigned)pid, strerror(errno)); - goto die; - } - - /* read memory map using ptrace */ - vv("listing peer virtual memory areas\n"); - vm_entry.pve_entry = 0; - vm_entry.pve_path = path; /* not used but required to make vm_entry.pve_pathlen work */ - while(1) { - /* set pve_pathlen every turn, it gets overwritten by ptrace */ - vm_entry.pve_pathlen = MAXPATHLEN; - errno = 0; - - ret = ptrace(PT_VM_ENTRY, pid, (void *) &vm_entry, 0); - - if (ret) { - if (errno == ENOENT) { - /* we've reached the last entry */ - break; - } - fprintf(stderr, "fetching vm map entry failed: %s (%i)\n", strerror(errno), errno); - goto die; - } - - vvv("vmmap entry: start: %p, end: %p", (void *) vm_entry.pve_start, (void *) vm_entry.pve_end); - - /* skip unreadable or vnode-backed entries */ - if (!(vm_entry.pve_prot & VM_PROT_READ) || vm_entry.pve_pathlen > 0) { - vvv(" -> skipped (not readable or vnode-backed)\n"); - vm_entry.pve_path[0] = 0; - continue; - } - - /* useful entry, add to list */ - vvv(" -> will be scanned\n"); - vma.start = (void *)vm_entry.pve_start; - vma.end = (void *)vm_entry.pve_end; - vmas = (vma_t *) realloc(vmas, (num_vmas + 1) * sizeof(vma_t)); - vmas[num_vmas++] = vma; - } - - vv("peer has %u virtual memory areas\n", num_vmas); - - /* look for the hash signature */ - vv("scanning peer memory for hash table signatures\n"); - for(i=0;i\n", prog); - exit(-1); -} - -int main(int argc, char *argv[]) { - pid_t pid; - int opt; - - while ( (opt = getopt(argc, argv, "kv")) != -1) { - switch (opt) { - case 'v': - verbose++; - break; - case 'k': - getkeys++; - break; - default: - usage(argv[0]); - break; - } - } - - if (optind < argc) pid=atoi(argv[optind++]); - else usage(argv[0]); - - return scan(pid); -} diff --git a/src/util/uthash/tests/keystat.c b/src/util/uthash/tests/keystat.c deleted file mode 100644 index bf1d6ff..0000000 --- a/src/util/uthash/tests/keystat.c +++ /dev/null @@ -1,219 +0,0 @@ -#include /* for 'open' */ -#include /* for 'open' */ -#include /* for 'open' */ -#include /* for 'malloc' */ -#include /* for 'printf' */ -#include /* for 'read' */ -#include /* for 'sterror' */ -#include /* for 'gettimeofday' */ -#include "uthash.h" - -#undef uthash_noexpand_fyi -#define uthash_noexpand_fyi(t) die() -#define UNALIGNED_KEYS 0 - -void die() { - fprintf(stderr,"expansion inhibited\n"); - exit(-1); -} - -/* Windows doesn't have gettimeofday. While Cygwin and some - * versions of MinGW supply one, it is very coarse. This substitute - * gives much more accurate elapsed times under Windows. */ -#if (( defined __CYGWIN__ ) || ( defined __MINGW32__ )) -#include -void win_gettimeofday(struct timeval* p, void* tz /* IGNORED */) { - LARGE_INTEGER q; - static long long freq; - static long long cyg_timer; - QueryPerformanceFrequency(&q); - freq = q.QuadPart; - QueryPerformanceCounter(&q); - cyg_timer = q.QuadPart; - p->tv_sec = (long)(cyg_timer / freq); - p->tv_usec = (long)(((cyg_timer % freq) * 1000000) / freq); -} -#define gettimeofday win_gettimeofday -#define MODE (O_RDONLY|O_BINARY) -#else -#define MODE (O_RDONLY) -#endif - -#ifndef timersub -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif - -typedef struct stat_key { - char *key; - unsigned len; - UT_hash_handle hh, hh2; -} stat_key; - -#define CHAIN_0 0 -#define CHAIN_5 1 -#define CHAIN_10 2 -#define CHAIN_20 3 -#define CHAIN_100 4 -#define CHAIN_MAX 5 -void hash_chain_len_histogram(UT_hash_table *tbl) { - unsigned i, bkt_hist[CHAIN_MAX+1]; - double pct = 100.0/tbl->num_buckets; - memset(bkt_hist,0,sizeof(bkt_hist)); - for(i=0; i < tbl->num_buckets; i++) { - unsigned count = tbl->buckets[i].count; - if (count == 0) bkt_hist[CHAIN_0]++; - else if (count < 5) bkt_hist[CHAIN_5]++; - else if (count < 10) bkt_hist[CHAIN_10]++; - else if (count < 20) bkt_hist[CHAIN_20]++; - else if (count < 100) bkt_hist[CHAIN_100]++; - else bkt_hist[CHAIN_MAX]++; - } - fprintf(stderr, "Buckets with 0 items: %.1f%%\n", bkt_hist[CHAIN_0 ]*pct); - fprintf(stderr, "Buckets with < 5 items: %.1f%%\n", bkt_hist[CHAIN_5 ]*pct); - fprintf(stderr, "Buckets with < 10 items: %.1f%%\n", bkt_hist[CHAIN_10]*pct); - fprintf(stderr, "Buckets with < 20 items: %.1f%%\n", bkt_hist[CHAIN_20]*pct); - fprintf(stderr, "Buckets with < 100 items: %.1f%%\n", bkt_hist[CHAIN_100]*pct); - fprintf(stderr, "Buckets with > 100 items: %.1f%%\n", bkt_hist[CHAIN_MAX]*pct); -} - -int main(int argc, char *argv[]) { - int dups=0, rc, fd, done=0, err=0, want, i=0, padding=0, v=1, percent=100; - unsigned keylen, max_keylen=0, verbose=0; - const char *filename = "/dev/stdin"; - char *dst; - stat_key *keyt, *keytmp, *keys=NULL, *keys2=NULL; - struct timeval start_tm, end_tm, elapsed_tm, elapsed_tm2, elapsed_tm3; - - if ((argc >= 3) && !strcmp(argv[1],"-p")) {percent = atoi(argv[2]); v = 3;} - if ((argc >= v) && !strcmp(argv[v],"-v")) {verbose=1; v++;} - if (argc >= v) filename=argv[v]; - fd=open(filename,MODE); - - if ( fd == -1 ) { - fprintf(stderr,"open failed %s: %s\n", filename, strerror(errno)); - return -1; - } - - for(i=0; !done; i++) { - - want = sizeof(int); - dst = (char*)&keylen; - readmore1: - rc = read(fd,dst,want); - if (rc != want) { - if (rc == 0) done=1; - else if (rc == -1) { - fprintf(stderr,"read failed: %s\n", strerror(errno)); - err=1; - } - else if (rc > 0) { want -= rc; dst += rc; goto readmore1; } - } - - if (done || err) break; - if (keylen > max_keylen) max_keylen=keylen; - - if ( (keyt = (stat_key*)malloc(sizeof(stat_key))) == NULL) { - fprintf(stderr,"out of memory\n"); - exit(-1); - } - - /* read key */ -#ifdef UNALIGNED_KEYS - padding = i%8; -#endif - if ( (keyt->key = (char*)malloc(padding+keylen)) == NULL) { - fprintf(stderr,"out of memory\n"); - exit(-1); - } - keyt->key += padding; /* forcibly alter the alignment of key */ - keyt->len = keylen; - - want = keylen; - dst = keyt->key; - readmore2: - rc = read(fd,dst,want); - if (rc != want) { - if (rc == -1) { - fprintf(stderr,"read failed: %s\n", strerror(errno)); - err=1; - } else if (rc == 0) { - fprintf(stderr,"incomplete file\n"); - err=1; - } else if (rc >= 0) { want -= rc; dst += rc; goto readmore2; } - } - if (err) break; - /* if percent was set to something less than 100%, skip some keys*/ - if (((rand()*1.0) / RAND_MAX) > ((percent*1.0)/100)) { - free(keyt->key-padding); - free(keyt); - continue; - } - - /* eliminate dups */ - HASH_FIND(hh,keys,keyt->key,keylen,keytmp); - if (keytmp) { - dups++; - free(keyt->key - padding); - free(keyt); - } else { - HASH_ADD_KEYPTR(hh,keys,keyt->key,keylen,keyt); - } - } - - if (verbose) { - unsigned key_count = HASH_COUNT(keys); - fprintf(stderr,"max key length: %u\n", max_keylen); - fprintf(stderr,"number unique keys: %u\n", key_count); - fprintf(stderr,"keystats memory: %u\n", - (unsigned)((sizeof(stat_key)+max_keylen)*key_count)); - hash_chain_len_histogram(keys->hh.tbl); - } - - /* add all keys to a new hash, so we can measure add time w/o malloc */ - gettimeofday(&start_tm,NULL); - for(keyt = keys; keyt != NULL; keyt=(stat_key*)keyt->hh.next) { - HASH_ADD_KEYPTR(hh2,keys2,keyt->key,keyt->len,keyt); - } - gettimeofday(&end_tm,NULL); - timersub(&end_tm, &start_tm, &elapsed_tm); - - /* now look up all keys in the new hash, again measuring elapsed time */ - gettimeofday(&start_tm,NULL); - for(keyt = keys; keyt != NULL; keyt=(stat_key*)keyt->hh.next) { - HASH_FIND(hh2,keys2,keyt->key,keyt->len,keytmp); - if (!keytmp) fprintf(stderr,"internal error, key not found\n"); - } - gettimeofday(&end_tm,NULL); - timersub(&end_tm, &start_tm, &elapsed_tm2); - - /* now delete all items in the new hash, measuring elapsed time */ - gettimeofday(&start_tm,NULL); - while (keys2) { - keytmp = keys2; - HASH_DELETE(hh2,keys2,keytmp); - } - gettimeofday(&end_tm,NULL); - timersub(&end_tm, &start_tm, &elapsed_tm3); - - if (!err) { - printf("%.3f,%d,%d,%d,%s,%ld,%ld,%ld\n", - 1-(1.0*keys->hh.tbl->nonideal_items/keys->hh.tbl->num_items), - keys->hh.tbl->num_items, - keys->hh.tbl->num_buckets, - dups, - (keys->hh.tbl->noexpand ? "nx" : "ok"), - (elapsed_tm.tv_sec * 1000000) + elapsed_tm.tv_usec, - (elapsed_tm2.tv_sec * 1000000) + elapsed_tm2.tv_usec, - (elapsed_tm3.tv_sec * 1000000) + elapsed_tm3.tv_usec ); - } - return 0; -} - diff --git a/src/util/uthash/tests/keystats b/src/util/uthash/tests/keystats deleted file mode 100755 index ea217b0..0000000 --- a/src/util/uthash/tests/keystats +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/perl - -use strict; - -use FindBin; - -sub usage { - print "usage: keystats [-v] keyfile\n"; - print "usage: keystats [-p [-v]] keyfile\n"; - exit -1; -} - -usage if ((@ARGV == 0) or ($ARGV[0] eq '-h')); - -my @exes = glob "$FindBin::Bin/keystat.???"; -my %stats; -for my $exe (@exes) { - $stats{$exe} = `$exe @ARGV`; - delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx) -} - -print( "fcn ideal% #items #buckets dup% fl add_usec find_usec del-all usec\n"); -printf("--- ------ ---------- ---------- ----- -- ---------- ---------- ------------\n"); -for my $exe (sort statsort keys %stats) { - my ($ideal,$items,$bkts,$dups,$ok,$add,$find,$del) = split /,/, $stats{$exe}; - - # convert 0-1 values to percentages - $dups = $items ? (100.0 * $dups / $items) : 0.0; - $ideal = 100.0 * $ideal; - - printf("%3s %5.1f%% %10d %10d %4.0f%% %2s %10d %10d %12d\n", substr($exe,-3,3), - $ideal,$items,$bkts,$dups,$ok,$add,$find,$del); -} - -# sort on hash_q (desc) then by find_usec (asc) -sub statsort { - my @a_stats = split /,/, $stats{$a}; - my @b_stats = split /,/, $stats{$b}; - return ($b_stats[0] <=> $a_stats[0]) || ($a_stats[-1] <=> $b_stats[-1]); -} diff --git a/src/util/uthash/tests/lru_cache/cache.c b/src/util/uthash/tests/lru_cache/cache.c deleted file mode 100644 index 632c558..0000000 --- a/src/util/uthash/tests/lru_cache/cache.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: cache.c - * - * Description: A simple cache - * - * Version: 1.0 - * Created: 04/11/2013 02:31:02 PM - * Revision: none - * Compiler: gcc - * - * Author: Oliver Lorenz (ol), olli@olorenz.org - * Company: https://olorenz.org - * License: This is licensed under the same terms as uthash itself - * - * ===================================================================================== - */ - -#include -#include -#include -#include "cache.h" -#include "uthash.h" - -/** - * A cache entry - */ -struct foo_cache_entry { - char *key; /**cache_lock), NULL)) != 0) - goto err_out; - - new->max_entries = capacity; - new->entries = NULL; - new->free_cb = free_cb; - *dst = new; - return 0; - -err_out: - if (new) - free(new); - return rv; -} - -/** Frees an allocated cache object - - @param cache - The cache object to free - - @param keep_data - Whether to free contained data or just delete references to it - - @return EINVAL if cache is NULL, 0 otherwise -*/ -int foo_cache_delete(struct foo_cache *cache, int keep_data) -{ - struct foo_cache_entry *entry, *tmp; - int rv; - - if (!cache) - return EINVAL; - - rv = pthread_rwlock_wrlock(&(cache->cache_lock)); - if (rv) - return rv; - - if (keep_data) { - HASH_CLEAR(hh, cache->entries); - } else { - HASH_ITER(hh, cache->entries, entry, tmp) { - HASH_DEL(cache->entries, entry); - if (cache->free_cb) - cache->free_cb(entry->data); - free(entry); - } - } - (void)pthread_rwlock_unlock(&(cache->cache_lock)); - (void)pthread_rwlock_destroy(&(cache->cache_lock)); - free(cache); - cache = NULL; - return 0; -} - -/** Checks if a given key is in the cache - - @param cache - The cache object - - @param key - The key to look-up - - @param result - Where to store the result if key is found. - - A warning: Even though result is just a pointer, - you have to call this function with a **ptr, - otherwise this will blow up in your face. - - @return EINVAL if cache is NULL, 0 otherwise -*/ -int foo_cache_lookup(struct foo_cache *cache, char *key, void *result) -{ - int rv; - struct foo_cache_entry *tmp = NULL; - char **dirty_hack = result; - - if (!cache || !key || !result) - return EINVAL; - - rv = pthread_rwlock_wrlock(&(cache->cache_lock)); - if (rv) - return rv; - - HASH_FIND_STR(cache->entries, key, tmp); - if (tmp) { - size_t key_len = strnlen(tmp->key, KEY_MAX_LENGTH); - HASH_DELETE(hh, cache->entries, tmp); - HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); - *dirty_hack = tmp->data; - } else { - *dirty_hack = result = NULL; - } - rv = pthread_rwlock_unlock(&(cache->cache_lock)); - return rv; -} - -/** Inserts a given pair into the cache - - @param cache - The cache object - - @param key - The key that identifies - - @param data - Data associated with - - @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise -*/ -int foo_cache_insert(struct foo_cache *cache, char *key, void *data) -{ - struct foo_cache_entry *entry = NULL; - struct foo_cache_entry *tmp_entry = NULL; - size_t key_len = 0; - int rv; - - if (!cache || !data) - return EINVAL; - - if ((entry = malloc(sizeof(*entry))) == NULL) - return ENOMEM; - - if ((rv = pthread_rwlock_wrlock(&(cache->cache_lock))) != 0) - goto err_out; - - entry->key = key; - entry->data = data; - key_len = strnlen(entry->key, KEY_MAX_LENGTH); - HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry); - - if (HASH_COUNT(cache->entries) >= cache->max_entries) { - HASH_ITER(hh, cache->entries, entry, tmp_entry) { - HASH_DELETE(hh, cache->entries, entry); - if (cache->free_cb) - cache->free_cb(entry->data); - else - free(entry->data); - /* free(key->key) if data has been copied */ - free(entry); - break; - } - } - - rv = pthread_rwlock_unlock(&(cache->cache_lock)); - return rv; - -err_out: - if (entry) - free(entry); - (void)pthread_rwlock_unlock(&(cache->cache_lock)); - return rv; - -} diff --git a/src/util/uthash/tests/lru_cache/cache.h b/src/util/uthash/tests/lru_cache/cache.h deleted file mode 100644 index 350576d..0000000 --- a/src/util/uthash/tests/lru_cache/cache.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ===================================================================================== - * - * Filename: cache.h - * - * Description: A simple cache - * - * Version: 1.0 - * Created: 04/11/2013 02:30:46 PM - * Revision: none - * Compiler: gcc - * - * Author: Oliver Lorenz (ol), olli@olorenz.org - * Company: https://olorenz.org - * License: This is licensed under the same terms as uthash itself - * - * ===================================================================================== - */ - -#ifndef _CACHE_ -#define _CACHE_ - -struct foo_cache; - -extern int foo_cache_create(struct foo_cache **dst, const size_t capacity, - void (*free_cb) (void *element)); -extern int foo_cache_delete(struct foo_cache *cache, int keep_data); -extern int foo_cache_lookup(struct foo_cache *cache, char *key, void *result); -extern int foo_cache_insert(struct foo_cache *cache, char *key, void *data); - -#endif diff --git a/src/util/uthash/tests/lru_cache/main.c b/src/util/uthash/tests/lru_cache/main.c deleted file mode 100644 index 95c8f3c..0000000 --- a/src/util/uthash/tests/lru_cache/main.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "cache.h" - -#define MAX_RANDOM_ENTRIES 32 - -struct key_record { - char *key; - char *value; -}; - -int generate_random_entry(struct key_record **entry); -int generate_random_string(char **dst, const size_t len); -void free_random_entry(void *entry); - -void *producer(void *arg) -{ - struct foo_cache *cache = arg; - int i; - - for (i = 0; i < MAX_RANDOM_ENTRIES; i++) { - struct key_record *entry = NULL; - if (generate_random_entry(&entry)) { - fprintf(stderr, "generate_random_entry() failed\n"); - continue; - } -#if defined(DEBUG) - printf("Random Entry:\n"); - printf(" key: %s\n", entry->key); - printf(" Key: %s\n", entry->value); -#else - printf("inserted %s (%d)\n", entry->key, - (int)strlen(entry->key)); -#endif - if (foo_cache_insert(cache, entry->key, entry)) { - fprintf(stderr, "foo_cache_insert() failed\n"); - continue; - } - } - - pthread_exit(NULL); -} - -void *consumer(void *arg) -{ - struct foo_cache *cache = arg; - struct key_record *result = NULL; - char *buffer = malloc(64); - char key[33]; - int stop = 0; - - if (!buffer) - goto out; - - /* give producer time to populate the cache */ - sleep(2); - printf("\n\n"); - - do { - memset(key, 0, 64); - result = NULL; - - printf("Enter key for lookup: "); - fgets(buffer, sizeof(key), stdin); - sscanf(buffer, "%s\n", key); - /* read '\n' from stdin */ - getchar(); - - if (strncmp(key, "exit", 4) == 0) { - stop = 1; - continue; - } - - printf("Got key %s (%d)\n", key, (int)strlen(key)); - - if (foo_cache_lookup(cache, key, &result)) { - fprintf(stderr, "Could not retrieve key %s\n", key); - continue; - } - - if (!result) { - printf("MISS\n"); - continue; - } - - printf("HIT\n"); - printf("key: %s\n", result->key); - printf("key : %s\n", result->value); - } while (!stop); - -out: - if (buffer) - free(buffer); - pthread_exit(NULL); -} - -int main(void) -{ - int rv; - struct foo_cache *cache = NULL; - pthread_t workers[2]; - - rv = foo_cache_create(&cache, MAX_RANDOM_ENTRIES / 2, - free_random_entry); - if (rv) { - fprintf(stderr, "Could not create cache\n"); - exit(1); - } - - (void)pthread_create(&workers[0], NULL, producer, (void *)cache); - (void)pthread_create(&workers[1], NULL, consumer, (void *)cache); - - pthread_join(workers[0], NULL); - pthread_join(workers[1], NULL); - - (void)foo_cache_delete(cache, 0); - return 0; -} - -int generate_random_entry(struct key_record **entry) -{ - struct key_record *new = NULL; - char *key = NULL; - char *value = NULL; - int rv; - - if (!entry) - return EINVAL; - - rv = generate_random_string(&key, 33); - if (rv) - return rv; - - rv = generate_random_string(&value, 129); - if (rv) - return rv; - - if ((new = malloc(sizeof(*new))) == NULL) { - free(key); - free(value); - return ENOMEM; - } - - new->key = key; - new->value = value; - - *entry = new; - return 0; -} - -int generate_random_string(char **dst, const size_t len) -{ - static const char alphanum[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - size_t i; - char *s; - - if (!dst || len == 0) - return EINVAL; - - if ((s = malloc(len)) == NULL) - return ENOMEM; - - for (i = 0; i < len - 1; i++) { - s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; - } - - s[len - 1] = '\0'; - *dst = s; - return 0; -} - -void free_random_entry(void *entry) -{ -#if defined(DEBUG) - fprintf(stderr, "In %s: entry @ %p\n", __func__, entry); -#endif - struct key_record *record = entry; - if (!record) - return; - if (record->key) - free(record->key); - if (record->value) - free(record->value); - free(record); - record = NULL; -} diff --git a/src/util/uthash/tests/mexpand b/src/util/uthash/tests/mexpand deleted file mode 100755 index e1562d9..0000000 --- a/src/util/uthash/tests/mexpand +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# utility to macro-expand a test program -CC=gcc -#CPPFLAGS=-DHASH_DEBUG=1 -#CC=g++ -CPPFLAGS="-m64 -O3" -CFLAGS="-O3 -m64 -pedantic -Wall" - -${CC} ${CPPFLAGS} -E -I../src $1 | egrep -v '^#' > /tmp/$1 -indent /tmp/$1 -${CC} ${CFLAGS} -o /tmp/$1.$$ /tmp/$1 -rm -f /tmp/$1.$$ - -read -p "open /tmp/$1 ? [n] " response -if [ "$response" = "y" ] -then - vi /tmp/$1 -fi - - diff --git a/src/util/uthash/tests/simkeys.pl b/src/util/uthash/tests/simkeys.pl deleted file mode 100755 index acc5583..0000000 --- a/src/util/uthash/tests/simkeys.pl +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/perl - -# This program generates a simkey10.dat (100, 1000, etc) each -# containing 100 random keys of length 10 (100, 1000, etc). -# These files can then be fed into keystats to observe that -# the time to add or find the keys is directly proportional to -# keylength n [in other words, O(n)]. -# -# The conclusion is that really long keys (e.g. 100k) are not -# efficient. TDH 23Jan07 - -use strict; -use warnings; - - -#for my $len (10,100,1000,10000,100000,1000000) { -for my $len (100) { - open OUTFILE, ">simkeys$len.dat" or die "can't open: $!\n"; - # we'll do 100 keys of $len - print "keylen $len\n"; - for my $i (0..99) { - my $key = pack "I", $len; - $key .= pack "C", (int(rand(256))) for (1..$len); - print OUTFILE $key; - } - close OUTFILE; -} - diff --git a/src/util/uthash/tests/sleep_test.c b/src/util/uthash/tests/sleep_test.c deleted file mode 100644 index ccc50c9..0000000 --- a/src/util/uthash/tests/sleep_test.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ -#include /* getpid */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL; - - /* create elements */ - for(i=0;i<10000;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - printf("pid: %u\n", (unsigned)getpid()); - /* printf("sig: %p\n", &users->hh.tbl->signature); */ - /* printf("bbv: %p\n", &users->hh.tbl->bloom_bv); */ - sleep(60*10); - return 0; -} diff --git a/src/util/uthash/tests/tdiff.cpp b/src/util/uthash/tests/tdiff.cpp deleted file mode 100644 index 4be14fe..0000000 --- a/src/util/uthash/tests/tdiff.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Windows does not have unix diff so this is a simple replacement -#include -#include -using namespace std; -int main(int argc, char *argv[] ) { - int rc=-1; - if (argc != 3) { - cout << "usage: " << argv[0] << " file1 file2\n"; - return -1; - } - char *file1 = argv[1]; - char *file2 = argv[2]; - ifstream is1(file1, ios::in); - ifstream is2(file2, ios::in); - if (is1.fail()) {cerr << "failed to open " << file1 << "\n"; goto done;} - if (is2.fail()) {cerr << "failed to open " << file2 << "\n"; goto done;} - char d1[256], d2[256]; - do { - is1.read(d1,sizeof(d1)); - is2.read(d2,sizeof(d2)); - if ((is1.gcount() != is2.gcount()) || memcmp(d1,d2,is1.gcount())) { - cout << file1 << " and " << file2 << " differ\n"; - goto done; - } - } while (!is1.eof() && !is2.eof()); - - rc=0; - - done: - is1.close(); - is2.close(); - return rc; -} - diff --git a/src/util/uthash/tests/test1.ans b/src/util/uthash/tests/test1.ans deleted file mode 100644 index 0b08c48..0000000 --- a/src/util/uthash/tests/test1.ans +++ /dev/null @@ -1,10 +0,0 @@ -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 diff --git a/src/util/uthash/tests/test1.c b/src/util/uthash/tests/test1.c deleted file mode 100644 index afae6d6..0000000 --- a/src/util/uthash/tests/test1.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test10.ans b/src/util/uthash/tests/test10.ans deleted file mode 100644 index b1a27a8..0000000 --- a/src/util/uthash/tests/test10.ans +++ /dev/null @@ -1,4 +0,0 @@ -9 found in hh -9 found in alth -10 not found in hh -10 found in alth diff --git a/src/util/uthash/tests/test10.c b/src/util/uthash/tests/test10.c deleted file mode 100644 index e8efc3b..0000000 --- a/src/util/uthash/tests/test10.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; - UT_hash_handle alth; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL, *altusers=NULL; - - /* create elements */ - for(i=0;i<1000;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - if (i<10) HASH_ADD_INT(users,id,user); - HASH_ADD(alth,altusers,id,sizeof(int),user); - } - - /* - printf("hh items: %d, alth items: %d\n", - users->hh.tbl->num_items, users->alth.tbl->num_items); - printf("hh buckets: %d, alth buckets: %d\n", - users->hh.tbl->num_buckets, users->alth.tbl->num_buckets); - */ - - i=9; - HASH_FIND_INT(users,&i,tmp); - printf("%d %s in hh\n", i, (tmp ? "found" : "not found")); - HASH_FIND(alth,altusers,&i,sizeof(int),tmp); - printf("%d %s in alth\n", i, (tmp ? "found" : "not found")); - - i=10; - HASH_FIND_INT(users,&i,tmp); - printf("%d %s in hh\n", i, (tmp ? "found" : "not found")); - HASH_FIND(alth,altusers,&i,sizeof(int),tmp); - printf("%d %s in alth\n", i, (tmp ? "found" : "not found")); - - return 0; -} diff --git a/src/util/uthash/tests/test11.ans b/src/util/uthash/tests/test11.ans deleted file mode 100644 index 2b72e98..0000000 --- a/src/util/uthash/tests/test11.ans +++ /dev/null @@ -1,51 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER diff --git a/src/util/uthash/tests/test11.c b/src/util/uthash/tests/test11.c deleted file mode 100644 index 81986c5..0000000 --- a/src/util/uthash/tests/test11.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* perror */ -#include /* printf */ - -#define BUFLEN 20 - -#if 0 -/* Print a message if the hash's no-expand flag is set. */ -#undef uthash_noexpand_fyi -#undef uthash_expand_fyi -#define uthash_noexpand_fyi(tbl) printf("noexpand set\n"); -#define uthash_expand_fyi(tbl) printf("hash expanded\n"); -#endif - -typedef struct name_rec { - char boy_name[BUFLEN]; - UT_hash_handle hh; -} name_rec; - -int namecmp(void *_a, void *_b) { - name_rec *a = (name_rec*)_a; - name_rec *b = (name_rec*)_b; - return strcmp(a->boy_name,b->boy_name); -} - -int main(int argc,char *argv[]) { - name_rec *name, *names=NULL; - 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 = (name_rec*)malloc(sizeof(name_rec))) == NULL) exit(-1); - strncpy(name->boy_name,linebuf,BUFLEN); - HASH_ADD_STR(names,boy_name,name); - } - - fclose(file); - HASH_SORT(names,namecmp); - for(name=names;name;name=(name_rec*)(name->hh.next)) - printf("%s",name->boy_name); - - return 0; -} - diff --git a/src/util/uthash/tests/test11.dat b/src/util/uthash/tests/test11.dat deleted file mode 100644 index bb6051b..0000000 --- a/src/util/uthash/tests/test11.dat +++ /dev/null @@ -1,51 +0,0 @@ -JOHN -WILLIAM -WALTER -DOUGLAS -GERALD -FREDERICK -WARREN -SHANE -LESTER -RON -HARVEY -ADRIAN -CODY -NELSON -CLIFTON -WILLARD -DOUG -ORLANDO -REX -OMAR -DAMON -LOWELL -IRVING -CARROLL -LAURENCE -ROLANDO -CARY -XAVIER -ISAIAH -GUS -JARVIS -WINFRED -RAYMUNDO -LINCOLN -CORNELL -NIGEL -NORMAND -FRITZ -DONN -TRINIDAD -ODIS -DANNIE -DARIO -KENTON -CHONG -NEVILLE -TONEY -WARNER -WES -COLTON -ARNOLDO diff --git a/src/util/uthash/tests/test12.ans b/src/util/uthash/tests/test12.ans deleted file mode 100644 index 727f397..0000000 --- a/src/util/uthash/tests/test12.ans +++ /dev/null @@ -1,20 +0,0 @@ -added bob (id 0) -added jack (id 1) -added gary (id 2) -added ty (id 3) -added bo (id 4) -added phil (id 5) -added art (id 6) -added gil (id 7) -added buck (id 8) -added ted (id 9) -found bob (id 0) -found jack (id 1) -found gary (id 2) -found ty (id 3) -found bo (id 4) -found phil (id 5) -found art (id 6) -found gil (id 7) -found buck (id 8) -found ted (id 9) diff --git a/src/util/uthash/tests/test12.c b/src/util/uthash/tests/test12.c deleted file mode 100644 index dfed3f4..0000000 --- a/src/util/uthash/tests/test12.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "uthash.h" -#include -#include /* malloc */ - -typedef struct person_t { - char first_name[10]; - int id; - UT_hash_handle hh; -} person_t; - -int main(int argc, char*argv[]) { - person_t *people=NULL, *person; - const char **name; - const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", - "gil", "buck", "ted", NULL }; - int id=0; - - for(name=names; *name; name++) { - if ( (person = (person_t*)malloc(sizeof(person_t))) == NULL) exit(-1); - strncpy(person->first_name, *name,10); - person->id = id++; - HASH_ADD_STR(people,first_name,person); - printf("added %s (id %d)\n", person->first_name, person->id); - } - - for(name=names; *name; name++) { - HASH_FIND_STR(people,*name,person); - if (person) - printf("found %s (id %d)\n", person->first_name, person->id); - else - printf("failed to find %s\n", *name); - } - return 0; -} diff --git a/src/util/uthash/tests/test13.ans b/src/util/uthash/tests/test13.ans deleted file mode 100644 index baf3ff2..0000000 --- a/src/util/uthash/tests/test13.ans +++ /dev/null @@ -1,5 +0,0 @@ -id 9, following prev... -id 7, following prev... -id 5, following prev... -id 3, following prev... -id 1, following prev... diff --git a/src/util/uthash/tests/test13.c b/src/util/uthash/tests/test13.c deleted file mode 100644 index ed624a8..0000000 --- a/src/util/uthash/tests/test13.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* delete each even ID */ - for(i=0;i<10;i+=2) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - HASH_DEL(users,tmp); - free(tmp); - } else printf("user id %d not found\n", i); - } - - i=9; - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - while(tmp) { - printf("id %d, following prev...\n", tmp->id); - tmp = (example_user_t*)tmp->hh.prev; - } - } else printf("user id %d not found\n", i); - - return 0; -} diff --git a/src/util/uthash/tests/test14.ans b/src/util/uthash/tests/test14.ans deleted file mode 100644 index 77aeaeb..0000000 --- a/src/util/uthash/tests/test14.ans +++ /dev/null @@ -1 +0,0 @@ -lookup on 1219 of 1219 names succeeded diff --git a/src/util/uthash/tests/test14.c b/src/util/uthash/tests/test14.c deleted file mode 100644 index c31f42a..0000000 --- a/src/util/uthash/tests/test14.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* perror */ -#include /* printf */ - -#define BUFLEN 20 -#if 0 -#undef uthash_expand_fyi -#define uthash_expand_fyi(tbl) printf("expanding to %d buckets\n", tbl->num_buckets) -#endif - -typedef struct name_rec { - char boy_name[BUFLEN]; - UT_hash_handle hh; -} name_rec; - -int main(int argc,char *argv[]) { - name_rec *name, *names=NULL; - char linebuf[BUFLEN]; - FILE *file; - int i=0,j=0; - - if ( (file = fopen( "test14.dat", "r" )) == NULL ) { - perror("can't open: "); - exit(-1); - } - - while (fgets(linebuf,BUFLEN,file) != NULL) { - i++; - if ( (name = (name_rec*)malloc(sizeof(name_rec))) == NULL) exit(-1); - strncpy(name->boy_name,linebuf,BUFLEN); - HASH_ADD_STR(names,boy_name,name); - } - - fseek(file,0,SEEK_SET); - - while (fgets(linebuf,BUFLEN,file) != NULL) { - HASH_FIND_STR(names,linebuf,name); - if (!name) printf("failed to find: %s", linebuf); - else j++; - } - fclose(file); - printf("lookup on %d of %d names succeeded\n", j, i); - return 0; -} - diff --git a/src/util/uthash/tests/test14.dat b/src/util/uthash/tests/test14.dat deleted file mode 100644 index ea0b4ea..0000000 --- a/src/util/uthash/tests/test14.dat +++ /dev/null @@ -1,1219 +0,0 @@ -JAMES -JOHN -ROBERT -MICHAEL -WILLIAM -DAVID -RICHARD -CHARLES -JOSEPH -THOMAS -CHRISTOPHER -DANIEL -PAUL -MARK -DONALD -GEORGE -KENNETH -STEVEN -EDWARD -BRIAN -RONALD -ANTHONY -KEVIN -JASON -MATTHEW -GARY -TIMOTHY -JOSE -LARRY -JEFFREY -FRANK -SCOTT -ERIC -STEPHEN -ANDREW -RAYMOND -GREGORY -JOSHUA -JERRY -DENNIS -WALTER -PATRICK -PETER -HAROLD -DOUGLAS -HENRY -CARL -ARTHUR -RYAN -ROGER -JOE -JUAN -JACK -ALBERT -JONATHAN -JUSTIN -TERRY -GERALD -KEITH -SAMUEL -WILLIE -RALPH -LAWRENCE -NICHOLAS -ROY -BENJAMIN -BRUCE -BRANDON -ADAM -HARRY -FRED -WAYNE -BILLY -STEVE -LOUIS -JEREMY -AARON -RANDY -HOWARD -EUGENE -CARLOS -RUSSELL -BOBBY -VICTOR -MARTIN -ERNEST -PHILLIP -TODD -JESSE -CRAIG -ALAN -SHAWN -CLARENCE -SEAN -PHILIP -CHRIS -JOHNNY -EARL -JIMMY -ANTONIO -DANNY -BRYAN -TONY -LUIS -MIKE -STANLEY -LEONARD -NATHAN -DALE -MANUEL -RODNEY -CURTIS -NORMAN -ALLEN -MARVIN -VINCENT -GLENN -JEFFERY -TRAVIS -JEFF -CHAD -JACOB -LEE -MELVIN -ALFRED -KYLE -FRANCIS -BRADLEY -JESUS -HERBERT -FREDERICK -RAY -JOEL -EDWIN -DON -EDDIE -RICKY -TROY -RANDALL -BARRY -ALEXANDER -BERNARD -MARIO -LEROY -FRANCISCO -MARCUS -MICHEAL -THEODORE -CLIFFORD -MIGUEL -OSCAR -JAY -JIM -TOM -CALVIN -ALEX -JON -RONNIE -BILL -LLOYD -TOMMY -LEON -DEREK -WARREN -DARRELL -JEROME -FLOYD -LEO -ALVIN -TIM -WESLEY -GORDON -DEAN -GREG -JORGE -DUSTIN -PEDRO -DERRICK -DAN -LEWIS -ZACHARY -COREY -HERMAN -MAURICE -VERNON -ROBERTO -CLYDE -GLEN -HECTOR -SHANE -RICARDO -SAM -RICK -LESTER -BRENT -RAMON -CHARLIE -TYLER -GILBERT -GENE -MARC -REGINALD -RUBEN -BRETT -ANGEL -NATHANIEL -RAFAEL -LESLIE -EDGAR -MILTON -RAUL -BEN -CHESTER -CECIL -DUANE -FRANKLIN -ANDRE -ELMER -BRAD -GABRIEL -RON -MITCHELL -ROLAND -ARNOLD -HARVEY -JARED -ADRIAN -KARL -CORY -CLAUDE -ERIK -DARRYL -JAMIE -NEIL -JESSIE -CHRISTIAN -JAVIER -FERNANDO -CLINTON -TED -MATHEW -TYRONE -DARREN -LONNIE -LANCE -CODY -JULIO -KELLY -KURT -ALLAN -NELSON -GUY -CLAYTON -HUGH -MAX -DWAYNE -DWIGHT -ARMANDO -FELIX -JIMMIE -EVERETT -JORDAN -IAN -WALLACE -KEN -BOB -JAIME -CASEY -ALFREDO -ALBERTO -DAVE -IVAN -JOHNNIE -SIDNEY -BYRON -JULIAN -ISAAC -MORRIS -CLIFTON -WILLARD -DARYL -ROSS -VIRGIL -ANDY -MARSHALL -SALVADOR -PERRY -KIRK -SERGIO -MARION -TRACY -SETH -KENT -TERRANCE -RENE -EDUARDO -TERRENCE -ENRIQUE -FREDDIE -WADE -AUSTIN -STUART -FREDRICK -ARTURO -ALEJANDRO -JACKIE -JOEY -NICK -LUTHER -WENDELL -JEREMIAH -EVAN -JULIUS -DANA -DONNIE -OTIS -SHANNON -TREVOR -OLIVER -LUKE -HOMER -GERARD -DOUG -KENNY -HUBERT -ANGELO -SHAUN -LYLE -MATT -LYNN -ALFONSO -ORLANDO -REX -CARLTON -ERNESTO -CAMERON -NEAL -PABLO -LORENZO -OMAR -WILBUR -BLAKE -GRANT -HORACE -RODERICK -KERRY -ABRAHAM -WILLIS -RICKEY -JEAN -IRA -ANDRES -CESAR -JOHNATHAN -MALCOLM -RUDOLPH -DAMON -KELVIN -RUDY -PRESTON -ALTON -ARCHIE -MARCO -WM -PETE -RANDOLPH -GARRY -GEOFFREY -JONATHON -FELIPE -BENNIE -GERARDO -ED -DOMINIC -ROBIN -LOREN -DELBERT -COLIN -GUILLERMO -EARNEST -LUCAS -BENNY -NOEL -SPENCER -RODOLFO -MYRON -EDMUND -GARRETT -SALVATORE -CEDRIC -LOWELL -GREGG -SHERMAN -WILSON -DEVIN -SYLVESTER -KIM -ROOSEVELT -ISRAEL -JERMAINE -FORREST -WILBERT -LELAND -SIMON -GUADALUPE -CLARK -IRVING -CARROLL -BRYANT -OWEN -RUFUS -WOODROW -SAMMY -KRISTOPHER -MACK -LEVI -MARCOS -GUSTAVO -JAKE -LIONEL -MARTY -TAYLOR -ELLIS -DALLAS -GILBERTO -CLINT -NICOLAS -LAURENCE -ISMAEL -ORVILLE -DREW -JODY -ERVIN -DEWEY -AL -WILFRED -JOSH -HUGO -IGNACIO -CALEB -TOMAS -SHELDON -ERICK -FRANKIE -STEWART -DOYLE -DARREL -ROGELIO -TERENCE -SANTIAGO -ALONZO -ELIAS -BERT -ELBERT -RAMIRO -CONRAD -PAT -NOAH -GRADY -PHIL -CORNELIUS -LAMAR -ROLANDO -CLAY -PERCY -DEXTER -BRADFORD -MERLE -DARIN -AMOS -TERRELL -MOSES -IRVIN -SAUL -ROMAN -DARNELL -RANDAL -TOMMIE -TIMMY -DARRIN -WINSTON -BRENDAN -TOBY -VAN -ABEL -DOMINICK -BOYD -COURTNEY -JAN -EMILIO -ELIJAH -CARY -DOMINGO -SANTOS -AUBREY -EMMETT -MARLON -EMANUEL -JERALD -EDMOND -EMIL -DEWAYNE -WILL -OTTO -TEDDY -REYNALDO -BRET -MORGAN -JESS -TRENT -HUMBERTO -EMMANUEL -STEPHAN -LOUIE -VICENTE -LAMONT -STACY -GARLAND -MILES -MICAH -EFRAIN -BILLIE -LOGAN -HEATH -RODGER -HARLEY -DEMETRIUS -ETHAN -ELDON -ROCKY -PIERRE -JUNIOR -FREDDY -ELI -BRYCE -ANTOINE -ROBBIE -KENDALL -ROYCE -STERLING -MICKEY -CHASE -GROVER -ELTON -CLEVELAND -DYLAN -CHUCK -DAMIAN -REUBEN -STAN -AUGUST -LEONARDO -JASPER -RUSSEL -ERWIN -BENITO -HANS -MONTE -BLAINE -ERNIE -CURT -QUENTIN -AGUSTIN -MURRAY -JAMAL -DEVON -ADOLFO -HARRISON -TYSON -BURTON -BRADY -ELLIOTT -WILFREDO -BART -JARROD -VANCE -DENIS -DAMIEN -JOAQUIN -HARLAN -DESMOND -ELLIOT -DARWIN -ASHLEY -GREGORIO -BUDDY -XAVIER -KERMIT -ROSCOE -ESTEBAN -ANTON -SOLOMON -SCOTTY -NORBERT -ELVIN -WILLIAMS -NOLAN -CAREY -ROD -QUINTON -HAL -BRAIN -ROB -ELWOOD -KENDRICK -DARIUS -MOISES -SON -MARLIN -FIDEL -THADDEUS -CLIFF -MARCEL -ALI -JACKSON -RAPHAEL -BRYON -ARMAND -ALVARO -JEFFRY -DANE -JOESPH -THURMAN -NED -SAMMIE -RUSTY -MICHEL -MONTY -RORY -FABIAN -REGGIE -MASON -GRAHAM -KRIS -ISAIAH -VAUGHN -GUS -AVERY -LOYD -DIEGO -ALEXIS -ADOLPH -NORRIS -MILLARD -ROCCO -GONZALO -DERICK -RODRIGO -GERRY -STACEY -CARMEN -WILEY -RIGOBERTO -ALPHONSO -TY -SHELBY -RICKIE -NOE -VERN -BOBBIE -REED -JEFFERSON -ELVIS -BERNARDO -MAURICIO -HIRAM -DONOVAN -BASIL -RILEY -OLLIE -NICKOLAS -MAYNARD -SCOT -VINCE -QUINCY -EDDY -SEBASTIAN -FEDERICO -ULYSSES -HERIBERTO -DONNELL -COLE -DENNY -DAVIS -GAVIN -EMERY -WARD -ROMEO -JAYSON -DION -DANTE -CLEMENT -COY -ODELL -MAXWELL -JARVIS -BRUNO -ISSAC -MARY -DUDLEY -BROCK -SANFORD -COLBY -CARMELO -BARNEY -NESTOR -HOLLIS -STEFAN -DONNY -ART -LINWOOD -BEAU -WELDON -GALEN -ISIDRO -TRUMAN -DELMAR -JOHNATHON -SILAS -FREDERIC -DICK -KIRBY -IRWIN -CRUZ -MERLIN -MERRILL -CHARLEY -MARCELINO -LANE -HARRIS -CLEO -CARLO -TRENTON -KURTIS -HUNTER -AURELIO -WINFRED -VITO -COLLIN -DENVER -CARTER -LEONEL -EMORY -PASQUALE -MOHAMMAD -MARIANO -DANIAL -BLAIR -LANDON -DIRK -BRANDEN -ADAN -NUMBERS -CLAIR -BUFORD -GERMAN -BERNIE -WILMER -JOAN -EMERSON -ZACHERY -FLETCHER -JACQUES -ERROL -DALTON -MONROE -JOSUE -DOMINIQUE -EDWARDO -BOOKER -WILFORD -SONNY -SHELTON -CARSON -THERON -RAYMUNDO -DAREN -TRISTAN -HOUSTON -ROBBY -LINCOLN -JAME -GENARO -GALE -BENNETT -OCTAVIO -CORNELL -LAVERNE -HUNG -ARRON -ANTONY -HERSCHEL -ALVA -GIOVANNI -GARTH -CYRUS -CYRIL -RONNY -STEVIE -LON -FREEMAN -ERIN -DUNCAN -KENNITH -CARMINE -AUGUSTINE -YOUNG -ERICH -CHADWICK -WILBURN -RUSS -REID -MYLES -ANDERSON -MORTON -JONAS -FOREST -MITCHEL -MERVIN -ZANE -RICH -JAMEL -LAZARO -ALPHONSE -RANDELL -MAJOR -JOHNIE -JARRETT -BROOKS -ARIEL -ABDUL -DUSTY -LUCIANO -LINDSEY -TRACEY -SEYMOUR -SCOTTIE -EUGENIO -MOHAMMED -SANDY -VALENTIN -CHANCE -ARNULFO -LUCIEN -FERDINAND -THAD -EZRA -SYDNEY -ALDO -RUBIN -ROYAL -MITCH -EARLE -ABE -WYATT -MARQUIS -LANNY -KAREEM -JAMAR -BORIS -ISIAH -EMILE -ELMO -ARON -LEOPOLDO -EVERETTE -JOSEF -GAIL -ELOY -DORIAN -RODRICK -REINALDO -LUCIO -JERROD -WESTON -HERSHEL -BARTON -PARKER -LEMUEL -LAVERN -BURT -JULES -GIL -ELISEO -AHMAD -NIGEL -EFREN -ANTWAN -ALDEN -MARGARITO -COLEMAN -REFUGIO -DINO -OSVALDO -LES -DEANDRE -NORMAND -KIETH -IVORY -ANDREA -TREY -NORBERTO -NAPOLEON -JEROLD -FRITZ -ROSENDO -MILFORD -SANG -DEON -CHRISTOPER -ALFONZO -LYMAN -JOSIAH -BRANT -WILTON -RICO -JAMAAL -DEWITT -CAROL -BRENTON -YONG -OLIN -FOSTER -FAUSTINO -CLAUDIO -JUDSON -GINO -EDGARDO -BERRY -ALEC -TANNER -JARRED -DONN -TRINIDAD -TAD -SHIRLEY -PRINCE -PORFIRIO -ODIS -MARIA -LENARD -CHAUNCEY -CHANG -TOD -MEL -MARCELO -KORY -AUGUSTUS -KEVEN -HILARIO -BUD -SAL -ROSARIO -ORVAL -MAURO -DANNIE -ZACHARIAH -OLEN -ANIBAL -MILO -JED -FRANCES -THANH -DILLON -AMADO -NEWTON -CONNIE -LENNY -TORY -RICHIE -LUPE -HORACIO -BRICE -MOHAMED -DELMER -DARIO -REYES -DEE -MAC -JONAH -JERROLD -ROBT -HANK -SUNG -RUPERT -ROLLAND -KENTON -DAMION -CHI -ANTONE -WALDO -FREDRIC -BRADLY -QUINN -KIP -BURL -WALKER -TYREE -JEFFEREY -AHMED -WILLY -STANFORD -OREN -NOBLE -MOSHE -MIKEL -ENOCH -BRENDON -QUINTIN -JAMISON -FLORENCIO -DARRICK -TOBIAS -MINH -HASSAN -GIUSEPPE -DEMARCUS -CLETUS -TYRELL -LYNDON -KEENAN -WERNER -THEO -GERALDO -LOU -COLUMBUS -CHET -BERTRAM -MARKUS -HUEY -HILTON -DWAIN -DONTE -TYRON -OMER -ISAIAS -HIPOLITO -FERMIN -CHUNG -ADALBERTO -VALENTINE -JAMEY -BO -BARRETT -WHITNEY -TEODORO -MCKINLEY -MAXIMO -GARFIELD -SOL -RALEIGH -LAWERENCE -ABRAM -RASHAD -KING -EMMITT -DARON -CHONG -SAMUAL -PARIS -OTHA -MIQUEL -LACY -EUSEBIO -DONG -DOMENIC -DARRON -BUSTER -ANTONIA -WILBER -RENATO -JC -HOYT -HAYWOOD -EZEKIEL -CHAS -FLORENTINO -ELROY -CLEMENTE -ARDEN -NEVILLE -KELLEY -EDISON -DESHAWN -CARROL -SHAYNE -NATHANIAL -JORDON -DANILO -CLAUD -VAL -SHERWOOD -RAYMON -RAYFORD -CRISTOBAL -AMBROSE -TITUS -HYMAN -FELTON -EZEQUIEL -ERASMO -STANTON -LONNY -LEN -IKE -MILAN -LINO -JAROD -HERB -ANDREAS -WALTON -RHETT -PALMER -JUDE -DOUGLASS -CORDELL -OSWALDO -ELLSWORTH -VIRGILIO -TONEY -NATHANAEL -DEL -BRITT -BENEDICT -MOSE -HONG -LEIGH -JOHNSON -ISREAL -GAYLE -GARRET -FAUSTO -ASA -ARLEN -ZACK -WARNER -MODESTO -FRANCESCO -MANUAL -JAE -GAYLORD -GASTON -FILIBERTO -DEANGELO -MICHALE -GRANVILLE -WES -MALIK -ZACKARY -TUAN -NICKY -ELDRIDGE -CRISTOPHER -CORTEZ -ANTIONE -MALCOM -LONG -KOREY -JOSPEH -COLTON -WAYLON -VON -HOSEA -SHAD -SANTO -RUDOLF -ROLF -REY -RENALDO -MARCELLUS -LUCIUS -LESLEY -KRISTOFER -BOYCE -BENTON -MAN -KASEY -JEWELL -HAYDEN -HARLAND -ARNOLDO -RUEBEN -LEANDRO -KRAIG -JERRELL -JEROMY -HOBERT -CEDRICK -ARLIE -WINFORD -WALLY -PATRICIA -LUIGI -KENETH -JACINTO -GRAIG -FRANKLYN -EDMUNDO -SID -PORTER -LEIF -LAUREN -JERAMY -ELISHA -BUCK -WILLIAN -VINCENZO -SHON -MICHAL -LYNWOOD -LINDSAY -JEWEL -JERE -HAI -ELDEN -DORSEY -DARELL -BRODERICK -ALONSO diff --git a/src/util/uthash/tests/test15.ans b/src/util/uthash/tests/test15.ans deleted file mode 100644 index ad69a94..0000000 --- a/src/util/uthash/tests/test15.ans +++ /dev/null @@ -1 +0,0 @@ -betty's id is 2 diff --git a/src/util/uthash/tests/test15.c b/src/util/uthash/tests/test15.c deleted file mode 100644 index 93a69f3..0000000 --- a/src/util/uthash/tests/test15.c +++ /dev/null @@ -1,34 +0,0 @@ -#include /* strcpy */ -#include /* malloc */ -#include /* printf */ -#include "uthash.h" - -struct my_struct { - char name[10]; /* 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)); - 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; -} diff --git a/src/util/uthash/tests/test16.ans b/src/util/uthash/tests/test16.ans deleted file mode 100644 index 1b4d7e1..0000000 --- a/src/util/uthash/tests/test16.ans +++ /dev/null @@ -1 +0,0 @@ -found: user 5, unix time 157680000 diff --git a/src/util/uthash/tests/test16.c b/src/util/uthash/tests/test16.c deleted file mode 100644 index 59b14f4..0000000 --- a/src/util/uthash/tests/test16.c +++ /dev/null @@ -1,46 +0,0 @@ -#include /* malloc */ -#include /* offsetof */ -#include /* printf */ -#include /* memset */ -#include "uthash.h" - -struct inner { - int a; - int b; -}; - -struct my_event { - struct inner is; /* key is aggregate of this field */ - char event_code; /* and this field. */ - int user_id; - UT_hash_handle hh; /* makes this structure hashable */ -}; - - -int main(int argc, char *argv[]) { - struct my_event *e, ev, *events = NULL; - unsigned i, keylen; - - keylen = offsetof(struct my_event, event_code) + sizeof(char) - - offsetof(struct my_event, is); - - for(i = 0; i < 10; i++) { - e = (struct my_event*)malloc(sizeof(struct my_event)); - memset(e,0,sizeof(struct my_event)); - e->is.a = i * (60*60*24*365); /* i years (sec)*/ - e->is.b = 0; - e->event_code = 'a'+(i%2); /* meaningless */ - e->user_id = i; - - HASH_ADD( hh, events, is, keylen, e); - } - - /* look for one specific event */ - memset(&ev,0,sizeof(struct my_event)); - ev.is.a = 5 * (60*60*24*365); - ev.is.b = 0; - ev.event_code = 'b'; - HASH_FIND( hh, events, &ev.is, keylen , e); - if (e) printf("found: user %d, unix time %d\n", e->user_id, e->is.a); - return 0; -} diff --git a/src/util/uthash/tests/test17.ans b/src/util/uthash/tests/test17.ans deleted file mode 100644 index 92ae3ef..0000000 --- a/src/util/uthash/tests/test17.ans +++ /dev/null @@ -1,134 +0,0 @@ -user 9, cookie 81 -user 8, cookie 64 -user 7, cookie 49 -user 6, cookie 36 -user 5, cookie 25 -user 4, cookie 16 -user 3, cookie 9 -user 2, cookie 4 -user 1, cookie 1 -user 0, cookie 0 -sorting -called for a:9, b:8 -called for a:7, b:6 -called for a:5, b:4 -called for a:3, b:2 -called for a:1, b:0 -called for a:8, b:6 -called for a:8, b:7 -called for a:4, b:2 -called for a:4, b:3 -called for a:6, b:2 -called for a:6, b:3 -called for a:6, b:4 -called for a:6, b:5 -called for a:2, b:0 -called for a:2, b:1 -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -adding 10-20 -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -user 20, cookie 400 -user 19, cookie 361 -user 18, cookie 324 -user 17, cookie 289 -user 16, cookie 256 -user 15, cookie 225 -user 14, cookie 196 -user 13, cookie 169 -user 12, cookie 144 -user 11, cookie 121 -user 10, cookie 100 -sorting -called for a:0, b:1 -called for a:2, b:3 -called for a:4, b:5 -called for a:6, b:7 -called for a:8, b:9 -called for a:20, b:19 -called for a:18, b:17 -called for a:16, b:15 -called for a:14, b:13 -called for a:12, b:11 -called for a:0, b:2 -called for a:1, b:2 -called for a:4, b:6 -called for a:5, b:6 -called for a:8, b:19 -called for a:9, b:19 -called for a:17, b:15 -called for a:17, b:16 -called for a:13, b:11 -called for a:13, b:12 -called for a:0, b:4 -called for a:1, b:4 -called for a:2, b:4 -called for a:3, b:4 -called for a:8, b:15 -called for a:9, b:15 -called for a:19, b:15 -called for a:19, b:16 -called for a:19, b:17 -called for a:19, b:18 -called for a:11, b:10 -called for a:0, b:8 -called for a:1, b:8 -called for a:2, b:8 -called for a:3, b:8 -called for a:4, b:8 -called for a:5, b:8 -called for a:6, b:8 -called for a:7, b:8 -called for a:0, b:10 -called for a:1, b:10 -called for a:2, b:10 -called for a:3, b:10 -called for a:4, b:10 -called for a:5, b:10 -called for a:6, b:10 -called for a:7, b:10 -called for a:8, b:10 -called for a:9, b:10 -called for a:15, b:10 -called for a:15, b:11 -called for a:15, b:12 -called for a:15, b:13 -called for a:15, b:14 -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -user 10, cookie 100 -user 11, cookie 121 -user 12, cookie 144 -user 13, cookie 169 -user 14, cookie 196 -user 15, cookie 225 -user 16, cookie 256 -user 17, cookie 289 -user 18, cookie 324 -user 19, cookie 361 -user 20, cookie 400 diff --git a/src/util/uthash/tests/test17.c b/src/util/uthash/tests/test17.c deleted file mode 100644 index 4684e45..0000000 --- a/src/util/uthash/tests/test17.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int rev(void *_a, void *_b) { - example_user_t *a = (example_user_t*)_a; - example_user_t *b = (example_user_t*)_b; - printf("called for a:%d, b:%d\n",a->id, b->id); - return (a->id - b->id); -} - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL; - - /* create elements */ - for(i=9;i>=0;i--) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - printf("sorting\n"); - HASH_SORT(users,rev); - for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - - printf("adding 10-20\n"); - for(i=20;i>=10;i--) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - printf("sorting\n"); - HASH_SORT(users,rev); - for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test18.ans b/src/util/uthash/tests/test18.ans deleted file mode 100644 index db48dcf..0000000 --- a/src/util/uthash/tests/test18.ans +++ /dev/null @@ -1,20 +0,0 @@ -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -deleting id 0 -deleting id 1 -deleting id 2 -deleting id 3 -deleting id 4 -deleting id 5 -deleting id 6 -deleting id 7 -deleting id 8 -deleting id 9 diff --git a/src/util/uthash/tests/test18.c b/src/util/uthash/tests/test18.c deleted file mode 100644 index 80c4cf6..0000000 --- a/src/util/uthash/tests/test18.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user != NULL; user=(example_user_t*)user->hh.next) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - - /* delete them all, pathologically */ - while(users) { - printf("deleting id %i\n", users->id); - HASH_DEL(users,users); /* single head/deletee var! */ - } - return 0; -} diff --git a/src/util/uthash/tests/test19.ans b/src/util/uthash/tests/test19.ans deleted file mode 100644 index 588d0d9..0000000 --- a/src/util/uthash/tests/test19.ans +++ /dev/null @@ -1,1012 +0,0 @@ -sorting users ascending -user 0 -user 1 -user 2 -user 3 -user 4 -user 5 -user 6 -user 7 -user 8 -user 9 -sorting altusers descending -altuser 999 -altuser 998 -altuser 997 -altuser 996 -altuser 995 -altuser 994 -altuser 993 -altuser 992 -altuser 991 -altuser 990 -altuser 989 -altuser 988 -altuser 987 -altuser 986 -altuser 985 -altuser 984 -altuser 983 -altuser 982 -altuser 981 -altuser 980 -altuser 979 -altuser 978 -altuser 977 -altuser 976 -altuser 975 -altuser 974 -altuser 973 -altuser 972 -altuser 971 -altuser 970 -altuser 969 -altuser 968 -altuser 967 -altuser 966 -altuser 965 -altuser 964 -altuser 963 -altuser 962 -altuser 961 -altuser 960 -altuser 959 -altuser 958 -altuser 957 -altuser 956 -altuser 955 -altuser 954 -altuser 953 -altuser 952 -altuser 951 -altuser 950 -altuser 949 -altuser 948 -altuser 947 -altuser 946 -altuser 945 -altuser 944 -altuser 943 -altuser 942 -altuser 941 -altuser 940 -altuser 939 -altuser 938 -altuser 937 -altuser 936 -altuser 935 -altuser 934 -altuser 933 -altuser 932 -altuser 931 -altuser 930 -altuser 929 -altuser 928 -altuser 927 -altuser 926 -altuser 925 -altuser 924 -altuser 923 -altuser 922 -altuser 921 -altuser 920 -altuser 919 -altuser 918 -altuser 917 -altuser 916 -altuser 915 -altuser 914 -altuser 913 -altuser 912 -altuser 911 -altuser 910 -altuser 909 -altuser 908 -altuser 907 -altuser 906 -altuser 905 -altuser 904 -altuser 903 -altuser 902 -altuser 901 -altuser 900 -altuser 899 -altuser 898 -altuser 897 -altuser 896 -altuser 895 -altuser 894 -altuser 893 -altuser 892 -altuser 891 -altuser 890 -altuser 889 -altuser 888 -altuser 887 -altuser 886 -altuser 885 -altuser 884 -altuser 883 -altuser 882 -altuser 881 -altuser 880 -altuser 879 -altuser 878 -altuser 877 -altuser 876 -altuser 875 -altuser 874 -altuser 873 -altuser 872 -altuser 871 -altuser 870 -altuser 869 -altuser 868 -altuser 867 -altuser 866 -altuser 865 -altuser 864 -altuser 863 -altuser 862 -altuser 861 -altuser 860 -altuser 859 -altuser 858 -altuser 857 -altuser 856 -altuser 855 -altuser 854 -altuser 853 -altuser 852 -altuser 851 -altuser 850 -altuser 849 -altuser 848 -altuser 847 -altuser 846 -altuser 845 -altuser 844 -altuser 843 -altuser 842 -altuser 841 -altuser 840 -altuser 839 -altuser 838 -altuser 837 -altuser 836 -altuser 835 -altuser 834 -altuser 833 -altuser 832 -altuser 831 -altuser 830 -altuser 829 -altuser 828 -altuser 827 -altuser 826 -altuser 825 -altuser 824 -altuser 823 -altuser 822 -altuser 821 -altuser 820 -altuser 819 -altuser 818 -altuser 817 -altuser 816 -altuser 815 -altuser 814 -altuser 813 -altuser 812 -altuser 811 -altuser 810 -altuser 809 -altuser 808 -altuser 807 -altuser 806 -altuser 805 -altuser 804 -altuser 803 -altuser 802 -altuser 801 -altuser 800 -altuser 799 -altuser 798 -altuser 797 -altuser 796 -altuser 795 -altuser 794 -altuser 793 -altuser 792 -altuser 791 -altuser 790 -altuser 789 -altuser 788 -altuser 787 -altuser 786 -altuser 785 -altuser 784 -altuser 783 -altuser 782 -altuser 781 -altuser 780 -altuser 779 -altuser 778 -altuser 777 -altuser 776 -altuser 775 -altuser 774 -altuser 773 -altuser 772 -altuser 771 -altuser 770 -altuser 769 -altuser 768 -altuser 767 -altuser 766 -altuser 765 -altuser 764 -altuser 763 -altuser 762 -altuser 761 -altuser 760 -altuser 759 -altuser 758 -altuser 757 -altuser 756 -altuser 755 -altuser 754 -altuser 753 -altuser 752 -altuser 751 -altuser 750 -altuser 749 -altuser 748 -altuser 747 -altuser 746 -altuser 745 -altuser 744 -altuser 743 -altuser 742 -altuser 741 -altuser 740 -altuser 739 -altuser 738 -altuser 737 -altuser 736 -altuser 735 -altuser 734 -altuser 733 -altuser 732 -altuser 731 -altuser 730 -altuser 729 -altuser 728 -altuser 727 -altuser 726 -altuser 725 -altuser 724 -altuser 723 -altuser 722 -altuser 721 -altuser 720 -altuser 719 -altuser 718 -altuser 717 -altuser 716 -altuser 715 -altuser 714 -altuser 713 -altuser 712 -altuser 711 -altuser 710 -altuser 709 -altuser 708 -altuser 707 -altuser 706 -altuser 705 -altuser 704 -altuser 703 -altuser 702 -altuser 701 -altuser 700 -altuser 699 -altuser 698 -altuser 697 -altuser 696 -altuser 695 -altuser 694 -altuser 693 -altuser 692 -altuser 691 -altuser 690 -altuser 689 -altuser 688 -altuser 687 -altuser 686 -altuser 685 -altuser 684 -altuser 683 -altuser 682 -altuser 681 -altuser 680 -altuser 679 -altuser 678 -altuser 677 -altuser 676 -altuser 675 -altuser 674 -altuser 673 -altuser 672 -altuser 671 -altuser 670 -altuser 669 -altuser 668 -altuser 667 -altuser 666 -altuser 665 -altuser 664 -altuser 663 -altuser 662 -altuser 661 -altuser 660 -altuser 659 -altuser 658 -altuser 657 -altuser 656 -altuser 655 -altuser 654 -altuser 653 -altuser 652 -altuser 651 -altuser 650 -altuser 649 -altuser 648 -altuser 647 -altuser 646 -altuser 645 -altuser 644 -altuser 643 -altuser 642 -altuser 641 -altuser 640 -altuser 639 -altuser 638 -altuser 637 -altuser 636 -altuser 635 -altuser 634 -altuser 633 -altuser 632 -altuser 631 -altuser 630 -altuser 629 -altuser 628 -altuser 627 -altuser 626 -altuser 625 -altuser 624 -altuser 623 -altuser 622 -altuser 621 -altuser 620 -altuser 619 -altuser 618 -altuser 617 -altuser 616 -altuser 615 -altuser 614 -altuser 613 -altuser 612 -altuser 611 -altuser 610 -altuser 609 -altuser 608 -altuser 607 -altuser 606 -altuser 605 -altuser 604 -altuser 603 -altuser 602 -altuser 601 -altuser 600 -altuser 599 -altuser 598 -altuser 597 -altuser 596 -altuser 595 -altuser 594 -altuser 593 -altuser 592 -altuser 591 -altuser 590 -altuser 589 -altuser 588 -altuser 587 -altuser 586 -altuser 585 -altuser 584 -altuser 583 -altuser 582 -altuser 581 -altuser 580 -altuser 579 -altuser 578 -altuser 577 -altuser 576 -altuser 575 -altuser 574 -altuser 573 -altuser 572 -altuser 571 -altuser 570 -altuser 569 -altuser 568 -altuser 567 -altuser 566 -altuser 565 -altuser 564 -altuser 563 -altuser 562 -altuser 561 -altuser 560 -altuser 559 -altuser 558 -altuser 557 -altuser 556 -altuser 555 -altuser 554 -altuser 553 -altuser 552 -altuser 551 -altuser 550 -altuser 549 -altuser 548 -altuser 547 -altuser 546 -altuser 545 -altuser 544 -altuser 543 -altuser 542 -altuser 541 -altuser 540 -altuser 539 -altuser 538 -altuser 537 -altuser 536 -altuser 535 -altuser 534 -altuser 533 -altuser 532 -altuser 531 -altuser 530 -altuser 529 -altuser 528 -altuser 527 -altuser 526 -altuser 525 -altuser 524 -altuser 523 -altuser 522 -altuser 521 -altuser 520 -altuser 519 -altuser 518 -altuser 517 -altuser 516 -altuser 515 -altuser 514 -altuser 513 -altuser 512 -altuser 511 -altuser 510 -altuser 509 -altuser 508 -altuser 507 -altuser 506 -altuser 505 -altuser 504 -altuser 503 -altuser 502 -altuser 501 -altuser 500 -altuser 499 -altuser 498 -altuser 497 -altuser 496 -altuser 495 -altuser 494 -altuser 493 -altuser 492 -altuser 491 -altuser 490 -altuser 489 -altuser 488 -altuser 487 -altuser 486 -altuser 485 -altuser 484 -altuser 483 -altuser 482 -altuser 481 -altuser 480 -altuser 479 -altuser 478 -altuser 477 -altuser 476 -altuser 475 -altuser 474 -altuser 473 -altuser 472 -altuser 471 -altuser 470 -altuser 469 -altuser 468 -altuser 467 -altuser 466 -altuser 465 -altuser 464 -altuser 463 -altuser 462 -altuser 461 -altuser 460 -altuser 459 -altuser 458 -altuser 457 -altuser 456 -altuser 455 -altuser 454 -altuser 453 -altuser 452 -altuser 451 -altuser 450 -altuser 449 -altuser 448 -altuser 447 -altuser 446 -altuser 445 -altuser 444 -altuser 443 -altuser 442 -altuser 441 -altuser 440 -altuser 439 -altuser 438 -altuser 437 -altuser 436 -altuser 435 -altuser 434 -altuser 433 -altuser 432 -altuser 431 -altuser 430 -altuser 429 -altuser 428 -altuser 427 -altuser 426 -altuser 425 -altuser 424 -altuser 423 -altuser 422 -altuser 421 -altuser 420 -altuser 419 -altuser 418 -altuser 417 -altuser 416 -altuser 415 -altuser 414 -altuser 413 -altuser 412 -altuser 411 -altuser 410 -altuser 409 -altuser 408 -altuser 407 -altuser 406 -altuser 405 -altuser 404 -altuser 403 -altuser 402 -altuser 401 -altuser 400 -altuser 399 -altuser 398 -altuser 397 -altuser 396 -altuser 395 -altuser 394 -altuser 393 -altuser 392 -altuser 391 -altuser 390 -altuser 389 -altuser 388 -altuser 387 -altuser 386 -altuser 385 -altuser 384 -altuser 383 -altuser 382 -altuser 381 -altuser 380 -altuser 379 -altuser 378 -altuser 377 -altuser 376 -altuser 375 -altuser 374 -altuser 373 -altuser 372 -altuser 371 -altuser 370 -altuser 369 -altuser 368 -altuser 367 -altuser 366 -altuser 365 -altuser 364 -altuser 363 -altuser 362 -altuser 361 -altuser 360 -altuser 359 -altuser 358 -altuser 357 -altuser 356 -altuser 355 -altuser 354 -altuser 353 -altuser 352 -altuser 351 -altuser 350 -altuser 349 -altuser 348 -altuser 347 -altuser 346 -altuser 345 -altuser 344 -altuser 343 -altuser 342 -altuser 341 -altuser 340 -altuser 339 -altuser 338 -altuser 337 -altuser 336 -altuser 335 -altuser 334 -altuser 333 -altuser 332 -altuser 331 -altuser 330 -altuser 329 -altuser 328 -altuser 327 -altuser 326 -altuser 325 -altuser 324 -altuser 323 -altuser 322 -altuser 321 -altuser 320 -altuser 319 -altuser 318 -altuser 317 -altuser 316 -altuser 315 -altuser 314 -altuser 313 -altuser 312 -altuser 311 -altuser 310 -altuser 309 -altuser 308 -altuser 307 -altuser 306 -altuser 305 -altuser 304 -altuser 303 -altuser 302 -altuser 301 -altuser 300 -altuser 299 -altuser 298 -altuser 297 -altuser 296 -altuser 295 -altuser 294 -altuser 293 -altuser 292 -altuser 291 -altuser 290 -altuser 289 -altuser 288 -altuser 287 -altuser 286 -altuser 285 -altuser 284 -altuser 283 -altuser 282 -altuser 281 -altuser 280 -altuser 279 -altuser 278 -altuser 277 -altuser 276 -altuser 275 -altuser 274 -altuser 273 -altuser 272 -altuser 271 -altuser 270 -altuser 269 -altuser 268 -altuser 267 -altuser 266 -altuser 265 -altuser 264 -altuser 263 -altuser 262 -altuser 261 -altuser 260 -altuser 259 -altuser 258 -altuser 257 -altuser 256 -altuser 255 -altuser 254 -altuser 253 -altuser 252 -altuser 251 -altuser 250 -altuser 249 -altuser 248 -altuser 247 -altuser 246 -altuser 245 -altuser 244 -altuser 243 -altuser 242 -altuser 241 -altuser 240 -altuser 239 -altuser 238 -altuser 237 -altuser 236 -altuser 235 -altuser 234 -altuser 233 -altuser 232 -altuser 231 -altuser 230 -altuser 229 -altuser 228 -altuser 227 -altuser 226 -altuser 225 -altuser 224 -altuser 223 -altuser 222 -altuser 221 -altuser 220 -altuser 219 -altuser 218 -altuser 217 -altuser 216 -altuser 215 -altuser 214 -altuser 213 -altuser 212 -altuser 211 -altuser 210 -altuser 209 -altuser 208 -altuser 207 -altuser 206 -altuser 205 -altuser 204 -altuser 203 -altuser 202 -altuser 201 -altuser 200 -altuser 199 -altuser 198 -altuser 197 -altuser 196 -altuser 195 -altuser 194 -altuser 193 -altuser 192 -altuser 191 -altuser 190 -altuser 189 -altuser 188 -altuser 187 -altuser 186 -altuser 185 -altuser 184 -altuser 183 -altuser 182 -altuser 181 -altuser 180 -altuser 179 -altuser 178 -altuser 177 -altuser 176 -altuser 175 -altuser 174 -altuser 173 -altuser 172 -altuser 171 -altuser 170 -altuser 169 -altuser 168 -altuser 167 -altuser 166 -altuser 165 -altuser 164 -altuser 163 -altuser 162 -altuser 161 -altuser 160 -altuser 159 -altuser 158 -altuser 157 -altuser 156 -altuser 155 -altuser 154 -altuser 153 -altuser 152 -altuser 151 -altuser 150 -altuser 149 -altuser 148 -altuser 147 -altuser 146 -altuser 145 -altuser 144 -altuser 143 -altuser 142 -altuser 141 -altuser 140 -altuser 139 -altuser 138 -altuser 137 -altuser 136 -altuser 135 -altuser 134 -altuser 133 -altuser 132 -altuser 131 -altuser 130 -altuser 129 -altuser 128 -altuser 127 -altuser 126 -altuser 125 -altuser 124 -altuser 123 -altuser 122 -altuser 121 -altuser 120 -altuser 119 -altuser 118 -altuser 117 -altuser 116 -altuser 115 -altuser 114 -altuser 113 -altuser 112 -altuser 111 -altuser 110 -altuser 109 -altuser 108 -altuser 107 -altuser 106 -altuser 105 -altuser 104 -altuser 103 -altuser 102 -altuser 101 -altuser 100 -altuser 99 -altuser 98 -altuser 97 -altuser 96 -altuser 95 -altuser 94 -altuser 93 -altuser 92 -altuser 91 -altuser 90 -altuser 89 -altuser 88 -altuser 87 -altuser 86 -altuser 85 -altuser 84 -altuser 83 -altuser 82 -altuser 81 -altuser 80 -altuser 79 -altuser 78 -altuser 77 -altuser 76 -altuser 75 -altuser 74 -altuser 73 -altuser 72 -altuser 71 -altuser 70 -altuser 69 -altuser 68 -altuser 67 -altuser 66 -altuser 65 -altuser 64 -altuser 63 -altuser 62 -altuser 61 -altuser 60 -altuser 59 -altuser 58 -altuser 57 -altuser 56 -altuser 55 -altuser 54 -altuser 53 -altuser 52 -altuser 51 -altuser 50 -altuser 49 -altuser 48 -altuser 47 -altuser 46 -altuser 45 -altuser 44 -altuser 43 -altuser 42 -altuser 41 -altuser 40 -altuser 39 -altuser 38 -altuser 37 -altuser 36 -altuser 35 -altuser 34 -altuser 33 -altuser 32 -altuser 31 -altuser 30 -altuser 29 -altuser 28 -altuser 27 -altuser 26 -altuser 25 -altuser 24 -altuser 23 -altuser 22 -altuser 21 -altuser 20 -altuser 19 -altuser 18 -altuser 17 -altuser 16 -altuser 15 -altuser 14 -altuser 13 -altuser 12 -altuser 11 -altuser 10 -altuser 9 -altuser 8 -altuser 7 -altuser 6 -altuser 5 -altuser 4 -altuser 3 -altuser 2 -altuser 1 -altuser 0 diff --git a/src/util/uthash/tests/test19.c b/src/util/uthash/tests/test19.c deleted file mode 100644 index f0e26b6..0000000 --- a/src/util/uthash/tests/test19.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; - UT_hash_handle alth; -} example_user_t; - -int ascending_sort(void *_a, void *_b) { - example_user_t *a = (example_user_t*)_a; - example_user_t *b = (example_user_t*)_b; - if (a->id == b->id) return 0; - return (a->id < b->id) ? -1 : 1; -} - -int descending_sort(void *_a, void *_b) { - example_user_t *a = (example_user_t*)_a; - example_user_t *b = (example_user_t*)_b; - if (a->id == b->id) return 0; - return (a->id < b->id) ? 1 : -1; -} - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL, *altusers=NULL; - - /* create elements */ - for(i=0;i<1000;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - if (i<10) HASH_ADD_INT(users,id,user); - HASH_ADD(alth,altusers,id,sizeof(int),user); - } - - printf("sorting users ascending\n"); - HASH_SRT(hh,users,ascending_sort); - for(user=users; user; user=(example_user_t*)user->hh.next) - printf("user %d\n", user->id); - - printf("sorting altusers descending\n"); - HASH_SRT(alth,altusers,descending_sort); - for(user=altusers; user; user=(example_user_t*)user->alth.next) - printf("altuser %d\n", user->id); - - /* HASH_FSCK(hh,users); */ - /* HASH_FSCK(alth,altusers); */ - return 0; -} diff --git a/src/util/uthash/tests/test2.ans b/src/util/uthash/tests/test2.ans deleted file mode 100644 index fd4e2f8..0000000 --- a/src/util/uthash/tests/test2.ans +++ /dev/null @@ -1,5 +0,0 @@ -user id 0 found, cookie 0 -user id 2 found, cookie 4 -user id 4 found, cookie 16 -user id 6 found, cookie 36 -user id 8 found, cookie 64 diff --git a/src/util/uthash/tests/test2.c b/src/util/uthash/tests/test2.c deleted file mode 100644 index 591ca79..0000000 --- a/src/util/uthash/tests/test2.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "uthash.h" -#include -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* find each even ID */ - for(i=0;i<10;i+=2) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) printf("user id %d found, cookie %d\n", tmp->id, tmp->cookie); - else printf("user id %d not found\n", i); - } - return 0; -} diff --git a/src/util/uthash/tests/test20.ans b/src/util/uthash/tests/test20.ans deleted file mode 100644 index 4d3bb1d..0000000 --- a/src/util/uthash/tests/test20.ans +++ /dev/null @@ -1 +0,0 @@ -found diff --git a/src/util/uthash/tests/test20.c b/src/util/uthash/tests/test20.c deleted file mode 100644 index 152df39..0000000 --- a/src/util/uthash/tests/test20.c +++ /dev/null @@ -1,28 +0,0 @@ -#include /* memcpy */ -#include /* malloc */ -#include /* printf */ -#include "uthash.h" - -struct my_struct { - char bkey[5]; /* "binary" key */ - int data; - UT_hash_handle hh; -}; - -int main(int argc, char *argv[]) { - struct my_struct *s, *t, *bins = NULL; - char binary[5] = {3,1,4,1,6}; - - /* allocate our structure. initialize to some values */ - s = (struct my_struct*)calloc(1,sizeof(struct my_struct)); - memcpy(s->bkey, binary, sizeof(binary)); - - /* add to hash table using general macro */ - HASH_ADD( hh, bins, bkey, sizeof(binary), s); - - /* look up the structure we just added */ - HASH_FIND( hh, bins, binary, sizeof(binary), t ); - - if (t) printf("found\n"); - return 0; -} diff --git a/src/util/uthash/tests/test21.ans b/src/util/uthash/tests/test21.ans deleted file mode 100644 index af89f48..0000000 --- a/src/util/uthash/tests/test21.ans +++ /dev/null @@ -1 +0,0 @@ -found a 1 diff --git a/src/util/uthash/tests/test21.c b/src/util/uthash/tests/test21.c deleted file mode 100644 index 6043554..0000000 --- a/src/util/uthash/tests/test21.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include "uthash.h" - -typedef struct { - char a; - int b; -} record_key_t; - -typedef struct { - record_key_t key; - /* ... other data ... */ - UT_hash_handle hh; -} record_t; - -int main(int argc, char *argv[]) { - record_t l, *p, *r, *tmp, *records = NULL; - - r = (record_t*)malloc( sizeof(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; -} - diff --git a/src/util/uthash/tests/test22.ans b/src/util/uthash/tests/test22.ans deleted file mode 100644 index 2483a24..0000000 --- a/src/util/uthash/tests/test22.ans +++ /dev/null @@ -1 +0,0 @@ -found diff --git a/src/util/uthash/tests/test22.c b/src/util/uthash/tests/test22.c deleted file mode 100644 index 3435074..0000000 --- a/src/util/uthash/tests/test22.c +++ /dev/null @@ -1,59 +0,0 @@ -#include /* malloc */ -#include /* offsetof */ -#include /* printf */ -#include /* memset */ -#include "uthash.h" - -#define UTF32 1 - -typedef struct { - UT_hash_handle hh; - int len; - char encoding; /* these two fields */ - int text[]; /* comprise the key */ -} msg_t; - -typedef struct { - char encoding; - int text[]; -} lookup_key_t; - -int main(int argc, char *argv[]) { - unsigned keylen; - msg_t *msg, *tmp, *msgs = NULL; - lookup_key_t *lookup_key; - - int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */ - - /* allocate and initialize our structure */ - msg = (msg_t*)malloc( sizeof(msg_t) + sizeof(beijing) ); - memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */ - msg->len = sizeof(beijing); - msg->encoding = UTF32; - memcpy(msg->text, beijing, sizeof(beijing)); - - /* calculate the key length including padding, using formula */ - keylen = offsetof(msg_t, text) /* offset of last key field */ - + sizeof(beijing) /* size of last key field */ - - offsetof(msg_t, encoding); /* offset of first key field */ - - /* add our structure to the hash table */ - HASH_ADD( hh, msgs, encoding, keylen, msg); - - /* look it up to prove that it worked :-) */ - msg=NULL; - - lookup_key = (lookup_key_t*)malloc(sizeof(*lookup_key) + sizeof(beijing)); - memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing)); - lookup_key->encoding = UTF32; - memcpy(lookup_key->text, beijing, sizeof(beijing)); - HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg ); - if (msg) printf("found \n"); - free(lookup_key); - - HASH_ITER(hh, msgs, msg, tmp) { - HASH_DEL(msgs, msg); - free(msg); - } - return 0; -} diff --git a/src/util/uthash/tests/test23.ans b/src/util/uthash/tests/test23.ans deleted file mode 100644 index 79ed10a..0000000 --- a/src/util/uthash/tests/test23.ans +++ /dev/null @@ -1,6 +0,0 @@ -found 12345 -found 6789 -found 98765 -deleting 12345 -deleting 6789 -deleting 98765 diff --git a/src/util/uthash/tests/test23.c b/src/util/uthash/tests/test23.c deleted file mode 100644 index 78b633c..0000000 --- a/src/util/uthash/tests/test23.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include "uthash.h" - -typedef struct { - int key; - int data; - UT_hash_handle hh; -} item; - -int main() { - item *i, *j, *items=NULL; - int k; - - /* first item */ - k = 12345; - i = (item*)malloc(sizeof(item)); - i->key = k; i->data = 0; - HASH_ADD_INT(items,key,i); - - /* second item */ - k = 6789; - i = (item*)malloc(sizeof(item)); - i->key = k; i->data = 0; - HASH_ADD_INT(items,key,i); - - /* third item */ - k = 98765; - i = (item*)malloc(sizeof(item)); - i->key = k; i->data = 0; - HASH_ADD_INT(items,key,i); - - /* look them all up */ - k = 12345; HASH_FIND_INT(items, &k, j); if (j) printf("found %d\n",k); - k = 6789; HASH_FIND_INT(items, &k, j); if (j) printf("found %d\n",k); - k = 98765; HASH_FIND_INT(items, &k, j); if (j) printf("found %d\n",k); - - /* delete them not the way we prefer but it works */ - for(j=items; j != NULL; j=(item*)j->hh.next) { - printf("deleting %d\n", j->key); - HASH_DEL(items,j); - } - return 0; -} diff --git a/src/util/uthash/tests/test24.ans b/src/util/uthash/tests/test24.ans deleted file mode 100644 index 4a2034a..0000000 --- a/src/util/uthash/tests/test24.ans +++ /dev/null @@ -1 +0,0 @@ -hash contains 10 items diff --git a/src/util/uthash/tests/test24.c b/src/util/uthash/tests/test24.c deleted file mode 100644 index 28d3bf4..0000000 --- a/src/util/uthash/tests/test24.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - printf("hash contains %d items\n", HASH_COUNT(users)); - return 0; -} diff --git a/src/util/uthash/tests/test25.ans b/src/util/uthash/tests/test25.ans deleted file mode 100644 index 5c71cdf..0000000 --- a/src/util/uthash/tests/test25.ans +++ /dev/null @@ -1,28 +0,0 @@ -CDL macros -c b a -advancing head pointer -b a c -b a c b a c b a c b -b c a b c a b c a b -deleting b -a c -deleting (a) -c -deleting (c) - -DL macros -a b c -deleting tail c -a b -deleting head a -b -deleting head b - -LL macros -a b c -deleting tail c -a b -deleting head a -b -deleting head b - diff --git a/src/util/uthash/tests/test25.c b/src/util/uthash/tests/test25.c deleted file mode 100644 index c22be85..0000000 --- a/src/util/uthash/tests/test25.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *head = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND(head,&els[0]); - CDL_PREPEND(head,&els[1]); - CDL_PREPEND(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* point head to head->next */ - printf("advancing head pointer\n"); - head = head->next; - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop a few times */ - for(i=0,e=head;e && i<10;i++,e=e->next) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop backwards a few times */ - for(i=0,e=head;e && i<10;i++,e=e->prev) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - CDL_DELETE(head,&els[1]); - CDL_FOREACH(head,e) printf("%c ", e->id); - printf("\n"); - printf("deleting (a)\n"); - CDL_DELETE(head,&els[0]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - printf("deleting (c)\n"); - CDL_DELETE(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_APPEND(head,&els[0]); - DL_APPEND(head,&els[1]); - DL_APPEND(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting tail c\n"); - DL_DELETE(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head a\n"); - DL_DELETE(head,&els[0]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head b\n"); - DL_DELETE(head,&els[1]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test LL macros */ - printf("LL macros\n"); - LL_APPEND(head,&els[0]); - LL_APPEND(head,&els[1]); - LL_APPEND(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting tail c\n"); - LL_DELETE(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head a\n"); - LL_DELETE(head,&els[0]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head b\n"); - LL_DELETE(head,&els[1]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test26.ans b/src/util/uthash/tests/test26.ans deleted file mode 100644 index 764b01d..0000000 --- a/src/util/uthash/tests/test26.ans +++ /dev/null @@ -1,53 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER -found WES - diff --git a/src/util/uthash/tests/test26.c b/src/util/uthash/tests/test26.c deleted file mode 100644 index 0627739..0000000 --- a/src/util/uthash/tests/test26.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (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; -} diff --git a/src/util/uthash/tests/test27.ans b/src/util/uthash/tests/test27.ans deleted file mode 100644 index 80b476c..0000000 --- a/src/util/uthash/tests/test27.ans +++ /dev/null @@ -1,28 +0,0 @@ -CDL macros -c b a -advancing head pointer -b a c -b a c b a c b a c b -b c a b c a b c a b -deleting b -a c -deleting head (a) -c -deleting new head (c) - -DL macros -c b a -deleting c -b a -deleting a -b -deleting b - -LL macros -c b a -deleting c -b a -deleting a -b -deleting b - diff --git a/src/util/uthash/tests/test27.c b/src/util/uthash/tests/test27.c deleted file mode 100644 index 1b33e8c..0000000 --- a/src/util/uthash/tests/test27.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *head = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND(head,&els[0]); - CDL_PREPEND(head,&els[1]); - CDL_PREPEND(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* point head to head->next */ - printf("advancing head pointer\n"); - head = head->next; - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop a few times */ - for(i=0,e=head;e && i<10;i++,e=e->next) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop backwards a few times */ - for(i=0,e=head;e && i<10;i++,e=e->prev) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - CDL_DELETE(head,&els[1]); - CDL_FOREACH(head,e) printf("%c ", e->id); - printf("\n"); - printf("deleting head (a)\n"); - CDL_DELETE(head,&els[0]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - printf("deleting new head (c)\n"); - CDL_DELETE(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_PREPEND(head,&els[0]); - DL_PREPEND(head,&els[1]); - DL_PREPEND(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting c\n"); - DL_DELETE(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting a\n"); - DL_DELETE(head,&els[0]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - DL_DELETE(head,&els[1]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test LL macros */ - printf("LL macros\n"); - LL_PREPEND(head,&els[0]); - LL_PREPEND(head,&els[1]); - LL_PREPEND(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting c\n"); - LL_DELETE(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting a\n"); - LL_DELETE(head,&els[0]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - LL_DELETE(head,&els[1]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test28.ans b/src/util/uthash/tests/test28.ans deleted file mode 100644 index eb88650..0000000 --- a/src/util/uthash/tests/test28.ans +++ /dev/null @@ -1,34 +0,0 @@ -CDL macros -d c b a -advancing head pointer -c b a d -c b a d c b a d c b -c d a b c d a b c d -deleting b -c a d -deleting (a) -c d -deleting (c) -d -deleting (d) - -DL macros -c b a d -deleting c -b a d -deleting a -b d -deleting b -d -deleting d - -LL macros -c b a d -deleting c -b a d -deleting a -b d -deleting b -d -deleting d - diff --git a/src/util/uthash/tests/test28.c b/src/util/uthash/tests/test28.c deleted file mode 100644 index 279d891..0000000 --- a/src/util/uthash/tests/test28.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *head = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND(head,&els[0]); - CDL_PREPEND(head,&els[1]); - CDL_PREPEND(head,&els[2]); - CDL_PREPEND(head,&els[3]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* point head to head->next */ - printf("advancing head pointer\n"); - head = head->next; - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop a few times */ - for(i=0,e=head;e && i<10;i++,e=e->next) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop backwards a few times */ - for(i=0,e=head;e && i<10;i++,e=e->prev) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - CDL_DELETE(head,&els[1]); - CDL_FOREACH(head,e) printf("%c ", e->id); - printf("\n"); - printf("deleting (a)\n"); - CDL_DELETE(head,&els[0]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - printf("deleting (c)\n"); - CDL_DELETE(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - printf("deleting (d)\n"); - CDL_DELETE(head,&els[3]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_PREPEND(head,&els[0]); - DL_PREPEND(head,&els[1]); - DL_PREPEND(head,&els[2]); - DL_APPEND(head,&els[3]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting c\n"); - DL_DELETE(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting a\n"); - DL_DELETE(head,&els[0]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - DL_DELETE(head,&els[1]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting d\n"); - DL_DELETE(head,&els[3]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - /* test LL macros */ - printf("LL macros\n"); - LL_PREPEND(head,&els[0]); - LL_PREPEND(head,&els[1]); - LL_PREPEND(head,&els[2]); - LL_APPEND(head,&els[3]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting c\n"); - LL_DELETE(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting a\n"); - LL_DELETE(head,&els[0]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - LL_DELETE(head,&els[1]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - printf("deleting d\n"); - LL_DELETE(head,&els[3]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test29.ans b/src/util/uthash/tests/test29.ans deleted file mode 100644 index 6467b60..0000000 --- a/src/util/uthash/tests/test29.ans +++ /dev/null @@ -1,103 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER -deleting head ADRIAN -head->prev: XAVIER -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER diff --git a/src/util/uthash/tests/test29.c b/src/util/uthash/tests/test29.c deleted file mode 100644 index 8e54a02..0000000 --- a/src/util/uthash/tests/test29.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (el*)_b; - return strcmp(a->bname,b->bname); -} - -el *head = NULL; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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,tmp) printf("%s", tmp->bname); - - /* now delete the list head */ - printf("deleting head %shead->prev: %s", head->bname, head->prev->bname); - DL_DELETE(head,head); - DL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test3.ans b/src/util/uthash/tests/test3.ans deleted file mode 100644 index 56a52a3..0000000 --- a/src/util/uthash/tests/test3.ans +++ /dev/null @@ -1,5 +0,0 @@ -user 1, cookie 1 -user 3, cookie 9 -user 5, cookie 25 -user 7, cookie 49 -user 9, cookie 81 diff --git a/src/util/uthash/tests/test3.c b/src/util/uthash/tests/test3.c deleted file mode 100644 index 3f3e479..0000000 --- a/src/util/uthash/tests/test3.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) - exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* delete each even ID */ - for(i=0;i<10;i+=2) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - HASH_DEL(users,tmp); - free(tmp); - } else printf("user id %d not found\n", i); - } - - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test30.ans b/src/util/uthash/tests/test30.ans deleted file mode 100644 index 2b72e98..0000000 --- a/src/util/uthash/tests/test30.ans +++ /dev/null @@ -1,51 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER diff --git a/src/util/uthash/tests/test30.c b/src/util/uthash/tests/test30.c deleted file mode 100644 index 711c7d9..0000000 --- a/src/util/uthash/tests/test30.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (el*)_b; - return strcmp(a->bname,b->bname); -} - -el *head = NULL; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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); - CDL_PREPEND(head, name); - } - CDL_SORT(head, namecmp); - CDL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test31.ans b/src/util/uthash/tests/test31.ans deleted file mode 100644 index 2b72e98..0000000 --- a/src/util/uthash/tests/test31.ans +++ /dev/null @@ -1,51 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER diff --git a/src/util/uthash/tests/test31.c b/src/util/uthash/tests/test31.c deleted file mode 100644 index 711c7d9..0000000 --- a/src/util/uthash/tests/test31.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (el*)_b; - return strcmp(a->bname,b->bname); -} - -el *head = NULL; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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); - CDL_PREPEND(head, name); - } - CDL_SORT(head, namecmp); - CDL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test32.ans b/src/util/uthash/tests/test32.ans deleted file mode 100644 index 2a4d7f7..0000000 --- a/src/util/uthash/tests/test32.ans +++ /dev/null @@ -1,51 +0,0 @@ -ARNOLDO -COLTON -WES -WARNER -TONEY -NEVILLE -CHONG -KENTON -DARIO -DANNIE -ODIS -TRINIDAD -DONN -FRITZ -NORMAND -NIGEL -CORNELL -LINCOLN -RAYMUNDO -WINFRED -JARVIS -GUS -ISAIAH -XAVIER -CARY -ROLANDO -LAURENCE -CARROLL -IRVING -LOWELL -DAMON -OMAR -REX -ORLANDO -DOUG -WILLARD -CLIFTON -NELSON -CODY -ADRIAN -HARVEY -RON -LESTER -SHANE -WARREN -FREDERICK -GERALD -DOUGLAS -WALTER -WILLIAM -JOHN diff --git a/src/util/uthash/tests/test32.c b/src/util/uthash/tests/test32.c deleted file mode 100644 index fad2030..0000000 --- a/src/util/uthash/tests/test32.c +++ /dev/null @@ -1,41 +0,0 @@ -#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; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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_PREPEND(head, name); - } - /* DL_SORT(head, namecmp); */ - DL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test33.ans b/src/util/uthash/tests/test33.ans deleted file mode 100644 index 2b72e98..0000000 --- a/src/util/uthash/tests/test33.ans +++ /dev/null @@ -1,51 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER diff --git a/src/util/uthash/tests/test33.c b/src/util/uthash/tests/test33.c deleted file mode 100644 index d946ec1..0000000 --- a/src/util/uthash/tests/test33.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include "utlist.h" - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (el*)_b; - return strcmp(a->bname,b->bname); -} - -el *head = NULL; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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); - LL_PREPEND(head, name); - } - LL_SORT(head, namecmp); - LL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test34.ans b/src/util/uthash/tests/test34.ans deleted file mode 100644 index 2a4d7f7..0000000 --- a/src/util/uthash/tests/test34.ans +++ /dev/null @@ -1,51 +0,0 @@ -ARNOLDO -COLTON -WES -WARNER -TONEY -NEVILLE -CHONG -KENTON -DARIO -DANNIE -ODIS -TRINIDAD -DONN -FRITZ -NORMAND -NIGEL -CORNELL -LINCOLN -RAYMUNDO -WINFRED -JARVIS -GUS -ISAIAH -XAVIER -CARY -ROLANDO -LAURENCE -CARROLL -IRVING -LOWELL -DAMON -OMAR -REX -ORLANDO -DOUG -WILLARD -CLIFTON -NELSON -CODY -ADRIAN -HARVEY -RON -LESTER -SHANE -WARREN -FREDERICK -GERALD -DOUGLAS -WALTER -WILLIAM -JOHN diff --git a/src/util/uthash/tests/test34.c b/src/util/uthash/tests/test34.c deleted file mode 100644 index 653cdb8..0000000 --- a/src/util/uthash/tests/test34.c +++ /dev/null @@ -1,41 +0,0 @@ -#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; - -int main(int argc, char *argv[]) { - el *name, *tmp; - - 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); - CDL_PREPEND(head, name); - } - /* CDL_SORT(head, namecmp); */ - CDL_FOREACH(head,tmp) printf("%s", tmp->bname); - - fclose(file); - - return 0; -} diff --git a/src/util/uthash/tests/test35.ans b/src/util/uthash/tests/test35.ans deleted file mode 100644 index b33c808..0000000 --- a/src/util/uthash/tests/test35.ans +++ /dev/null @@ -1,30 +0,0 @@ -0: aello -1: bello -2: cello -3: dello -4: eello -5: fello -6: gello -7: hello -8: iello -9: jello -found aello -right address? yes -found bello -right address? yes -found cello -right address? yes -found dello -right address? yes -found eello -right address? yes -found fello -right address? yes -found gello -right address? yes -found hello -right address? yes -found iello -right address? yes -found jello -right address? yes diff --git a/src/util/uthash/tests/test35.c b/src/util/uthash/tests/test35.c deleted file mode 100644 index 6d41e5e..0000000 --- a/src/util/uthash/tests/test35.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "uthash.h" -#include /* strcpy */ -#include /* malloc */ -#include /* printf */ - -typedef struct elt { - char *s; - UT_hash_handle hh; -} elt; - -int main(int argc,char *argv[]) { - int i; - elt *head = NULL; - elt elts[10]; - char label[6]; - for(i=0;i<10;i++) { - elts[i].s = (char*)malloc(6); - strncpy(elts[i].s, "hello",6); - elts[i].s[0] = 'a' + i; - printf("%d: %s\n", i, elts[i].s); - HASH_ADD_KEYPTR(hh, head, elts[i].s, 6, &elts[i]); - } - - /* look up each element and verify the result pointer */ - strncpy(label, "hello", 6); - for(i=0;i<10;i++) { - elt *e; - label[0] = 'a' + i; - HASH_FIND(hh,head,label,6,e); - if (e) { - printf( "found %s\n", e->s); - printf( "right address? %s\n", (e == &elts[i]) ? "yes" : "no"); - } - } - - return 0; -} diff --git a/src/util/uthash/tests/test36.ans b/src/util/uthash/tests/test36.ans deleted file mode 100644 index 3b5283b..0000000 --- a/src/util/uthash/tests/test36.ans +++ /dev/null @@ -1,15 +0,0 @@ -user 0 -user 1 -user 2 -user 3 -user 4 -user 5 -user 6 -user 7 -user 8 -user 9 -auser 0 -auser 2 -auser 4 -auser 6 -auser 8 diff --git a/src/util/uthash/tests/test36.c b/src/util/uthash/tests/test36.c deleted file mode 100644 index d91350b..0000000 --- a/src/util/uthash/tests/test36.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct { - int id; - UT_hash_handle hh; - UT_hash_handle ah; -} example_user_t; - -#define EVENS(x) (((x)->id & 1) == 0) -int evens(void *userv) { - example_user_t *user = (example_user_t*)userv; - return ((user->id & 1) ? 0 : 1); -} - -int idcmp(void *_a, void *_b) { - example_user_t *a = (example_user_t*)_a; - example_user_t *b = (example_user_t*)_b; - return (a->id - b->id); -} - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL, *ausers=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - user = (example_user_t*)malloc(sizeof(example_user_t)); - user->id = i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user; user=(example_user_t*)(user->hh.next)) { - printf("user %d\n", user->id); - } - - /* now select some users into ausers */ - HASH_SELECT(ah,ausers,hh,users,evens); - HASH_SRT(ah,ausers,idcmp); - - for(user=ausers; user; user=(example_user_t*)(user->ah.next)) { - printf("auser %d\n", user->id); - } - return 0; -} diff --git a/src/util/uthash/tests/test37.ans b/src/util/uthash/tests/test37.ans deleted file mode 100644 index f42a945..0000000 --- a/src/util/uthash/tests/test37.ans +++ /dev/null @@ -1,20 +0,0 @@ -user 0 -user 1 -user 2 -user 3 -user 4 -user 5 -user 6 -user 7 -user 8 -user 9 -users count: 10 -auser 0 -auser 2 -auser 4 -auser 6 -auser 8 -ausers count: 5 -cleared ausers. -ausers count: 0 -users count: 10 diff --git a/src/util/uthash/tests/test37.c b/src/util/uthash/tests/test37.c deleted file mode 100644 index 7071e1c..0000000 --- a/src/util/uthash/tests/test37.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct { - int id; - UT_hash_handle hh; - UT_hash_handle ah; -} example_user_t; - -#define EVENS(x) ((((example_user_t*)(x))->id & 1) == 0) - -int idcmp(void *_a, void *_b) { - example_user_t *a = (example_user_t*)_a; - example_user_t *b = (example_user_t*)_b; - return (a->id - b->id); -} - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL, *ausers=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - user = (example_user_t*)malloc(sizeof(example_user_t)); - user->id = i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user; user=(example_user_t*)(user->hh.next)) { - printf("user %d\n", user->id); - } - printf("users count: %u\n", HASH_CNT(hh,users)); - - /* now select some users into ausers */ - HASH_SELECT(ah,ausers,hh,users,EVENS); - HASH_SRT(ah,ausers,idcmp); - - for(user=ausers; user; user=(example_user_t*)(user->ah.next)) { - printf("auser %d\n", user->id); - } - printf("ausers count: %u\n", HASH_CNT(ah,ausers)); - HASH_CLEAR(ah,ausers); - printf("cleared ausers.\n"); - printf("ausers count: %u\n", HASH_CNT(ah,ausers)); - for(user=ausers; user; user=(example_user_t*)(user->ah.next)) { - printf("auser %d\n", user->id); - } - printf("users count: %u\n", HASH_CNT(hh,users)); - return 0; -} diff --git a/src/util/uthash/tests/test38.ans b/src/util/uthash/tests/test38.ans deleted file mode 100644 index b20e04b..0000000 --- a/src/util/uthash/tests/test38.ans +++ /dev/null @@ -1 +0,0 @@ -hash count 10 diff --git a/src/util/uthash/tests/test38.c b/src/util/uthash/tests/test38.c deleted file mode 100644 index 500d160..0000000 --- a/src/util/uthash/tests/test38.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "uthash.h" -#include -#include - -struct test_t { - int a; - UT_hash_handle hh; -}; - -struct test_t *tests=NULL, *test; - -int main(void) { - int a, b; - for (b=0; b < 3; b++) { - for (a=0; a < 10; a++) { - test = NULL; - HASH_FIND(hh, tests, &a, sizeof(a), test); - if (! test) { - test = (struct test_t*)malloc(sizeof(struct test_t)); - memset(test, 0, sizeof(struct test_t)); - test->a = a; - HASH_ADD(hh, tests, a, sizeof(a), test); - } - } - } - printf("hash count %u\n", HASH_COUNT(tests)); - return 0; -} diff --git a/src/util/uthash/tests/test39.ans b/src/util/uthash/tests/test39.ans deleted file mode 100644 index a7e7e6c..0000000 --- a/src/util/uthash/tests/test39.ans +++ /dev/null @@ -1,7 +0,0 @@ -adding key eins -adding key zwei -adding key drei -hash count is 3 -looking for key eins... found. -looking for key zwei... found. -looking for key drei... found. diff --git a/src/util/uthash/tests/test39.c b/src/util/uthash/tests/test39.c deleted file mode 100644 index b0a5310..0000000 --- a/src/util/uthash/tests/test39.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include "uthash.h" - -typedef struct { - const char *name; - UT_hash_handle hh; -} ns_t; - -ns_t *head = NULL; - -int main() { - const char *keys[] = {"eins", "zwei", "drei"}; - unsigned i; - ns_t *nsp; - - for(i=0; i < sizeof(keys)/sizeof(keys[0]); i++) { - printf("adding key %s\n", keys[i]); - nsp = (ns_t*)malloc(sizeof(ns_t)); - nsp->name = keys[i]; - HASH_ADD_KEYPTR(hh,head,nsp->name,strlen(nsp->name),nsp); - } - printf("hash count is %u\n", HASH_COUNT(head)); - - for(i=0; i < sizeof(keys)/sizeof(keys[0]); i++) { - printf("looking for key %s... ", keys[i]); - HASH_FIND(hh,head,keys[i],strlen(keys[i]),nsp); - printf("%s.\n", (nsp?"found":"not found")); - } - return 0; -} diff --git a/src/util/uthash/tests/test4.ans b/src/util/uthash/tests/test4.ans deleted file mode 100644 index 19b148f..0000000 --- a/src/util/uthash/tests/test4.ans +++ /dev/null @@ -1,10 +0,0 @@ -cookie 0, user 0 -cookie 1, user 1 -cookie 4, user 2 -cookie 9, user 3 -cookie 16, user 4 -cookie 25, user 5 -cookie 36, user 6 -cookie 49, user 7 -cookie 64, user 8 -cookie 81, user 9 diff --git a/src/util/uthash/tests/test4.c b/src/util/uthash/tests/test4.c deleted file mode 100644 index 945c9ae..0000000 --- a/src/util/uthash/tests/test4.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; - UT_hash_handle alth; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *users=NULL, *altusers=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - HASH_ADD(alth,altusers,cookie,sizeof(int),user); - } - - for(user=altusers; user != NULL; user=(example_user_t*)(user->alth.next)) { - printf("cookie %d, user %d\n", user->cookie, user->id); - } - return 0; -} diff --git a/src/util/uthash/tests/test40.ans b/src/util/uthash/tests/test40.ans deleted file mode 100644 index ad69a94..0000000 --- a/src/util/uthash/tests/test40.ans +++ /dev/null @@ -1 +0,0 @@ -betty's id is 2 diff --git a/src/util/uthash/tests/test40.c b/src/util/uthash/tests/test40.c deleted file mode 100644 index 191c2f2..0000000 --- a/src/util/uthash/tests/test40.c +++ /dev/null @@ -1,34 +0,0 @@ -#include /* strcpy */ -#include /* malloc */ -#include /* printf */ -#include "uthash.h" - -struct my_struct { - const char *name; /* key */ - int id; - UT_hash_handle hh; /* makes this structure hashable */ -}; - - -int main(int argc, char *argv[]) { - const char **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; -} diff --git a/src/util/uthash/tests/test41.ans b/src/util/uthash/tests/test41.ans deleted file mode 100644 index f19e34b..0000000 --- a/src/util/uthash/tests/test41.ans +++ /dev/null @@ -1,6 +0,0 @@ -CDL macros -c b a deleting c deleting b deleting a -DL macros -a b c deleting a deleting b deleting c -LL macros -a b c deleting a deleting b deleting c diff --git a/src/util/uthash/tests/test41.c b/src/util/uthash/tests/test41.c deleted file mode 100644 index 1e35443..0000000 --- a/src/util/uthash/tests/test41.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *head = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e, *tmp, *tmp2; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND(head,&els[0]); - CDL_PREPEND(head,&els[1]); - CDL_PREPEND(head,&els[2]); - CDL_FOREACH(head,e) printf("%c ", e->id); - - /* point head to head->next */ - CDL_FOREACH_SAFE(head,e,tmp,tmp2) { - printf("deleting %c ", e->id); - CDL_DELETE(head,e); - } - printf("\n"); - if (head) printf("non-null head\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_APPEND(head,&els[0]); - DL_APPEND(head,&els[1]); - DL_APPEND(head,&els[2]); - DL_FOREACH(head,e) printf("%c ", e->id); - DL_FOREACH_SAFE(head,e,tmp) { - printf("deleting %c ", e->id); - DL_DELETE(head,e); - } - printf("\n"); - if (head) printf("non-null head\n"); - - /* test LL macros */ - printf("LL macros\n"); - LL_APPEND(head,&els[0]); - LL_APPEND(head,&els[1]); - LL_APPEND(head,&els[2]); - LL_FOREACH(head,e) printf("%c ", e->id); - LL_FOREACH_SAFE(head,e,tmp) { - printf("deleting %c ", e->id); - LL_DELETE(head,e); - } - printf("\n"); - if (head) printf("non-null head\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test42.ans b/src/util/uthash/tests/test42.ans deleted file mode 100644 index 581660e..0000000 --- a/src/util/uthash/tests/test42.ans +++ /dev/null @@ -1,14 +0,0 @@ -LL macros -a b c -search scalar found b -search found a - -DL macros -a b c -search scalar found b -search found a - -CDL macros -c b a -search scalar found b -search found a diff --git a/src/util/uthash/tests/test42.c b/src/util/uthash/tests/test42.c deleted file mode 100644 index b20c579..0000000 --- a/src/util/uthash/tests/test42.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *head = NULL; - -int eltcmp(el *a, el *b) {return a->id - b->id;} - -int main(int argc, char *argv[]) { - int i; - el els[10], *e, *tmp, *tmp2; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test LL macros */ - printf("LL macros\n"); - LL_APPEND(head,&els[0]); - LL_APPEND(head,&els[1]); - LL_APPEND(head,&els[2]); - LL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - LL_SEARCH_SCALAR(head, e, id, 'b'); - if (e) printf("search scalar found b\n"); - LL_SEARCH(head, e, &els[0], eltcmp); - if (e) printf("search found %c\n",e->id); - LL_FOREACH_SAFE(head,e,tmp) LL_DELETE(head,e); - - printf("\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_APPEND(head,&els[0]); - DL_APPEND(head,&els[1]); - DL_APPEND(head,&els[2]); - DL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - DL_SEARCH_SCALAR(head, e, id, 'b'); - if (e) printf("search scalar found b\n"); - DL_SEARCH(head, e, &els[0], eltcmp); - if (e) printf("search found %c\n",e->id); - DL_FOREACH_SAFE(head,e,tmp) DL_DELETE(head,e); - printf("\n"); - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND(head,&els[0]); - CDL_PREPEND(head,&els[1]); - CDL_PREPEND(head,&els[2]); - CDL_FOREACH(head,e) - printf("%c ", e->id); - printf("\n"); - CDL_SEARCH_SCALAR(head, e, id, 'b'); - if (e) printf("search scalar found b\n"); - CDL_SEARCH(head, e, &els[0], eltcmp); - if (e) printf("search found %c\n",e->id); - CDL_FOREACH_SAFE(head,e,tmp,tmp2) CDL_DELETE(head,e); - - - return 0; -} diff --git a/src/util/uthash/tests/test43.ans b/src/util/uthash/tests/test43.ans deleted file mode 100644 index d09e9bd..0000000 --- a/src/util/uthash/tests/test43.ans +++ /dev/null @@ -1,88 +0,0 @@ -length is 0 -push -length is 1 -back is 1 2 -pop -length is 0 -push -push -length is 2 -1 2 -3 4 -erase [0] -length is 1 -3 4 -push -3 4 -1 2 -clear -length is 0 -extend -length is 1 -ip points to [0] ? yes -push -0 0 -1 2 -erase [1] -length is 1 -0 0 -push -0 0 -3 4 -back is 3 4 -copy -cpy length is 2 -cpy 0 0 -cpy 3 4 -insert cpy[0] -cpy length is 3 -cpy 5 6 -cpy 0 0 -cpy 3 4 -erase cpy [0] [1] -cpy length is 1 -cpy 3 4 -inserta at cpy[1] -cpy length is 3 -cpy 3 4 -cpy 0 0 -cpy 3 4 -free cpy -length is 2 -resize to 30 -length is 30 -0 0 -3 4 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -0 0 -resize to 1 -length is 1 -resize to 0 -length is 0 -free diff --git a/src/util/uthash/tests/test43.c b/src/util/uthash/tests/test43.c deleted file mode 100644 index fbd40c8..0000000 --- a/src/util/uthash/tests/test43.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include "utarray.h" - -typedef struct { - int a; - int b; -} intpair_t; - -UT_icd pairicd = { sizeof(intpair_t),NULL,NULL,NULL}; - -int main() { - UT_array *pairs, *pairs_cpy; - intpair_t it, *ip; - size_t zero=0; - utarray_new(pairs, &pairicd); - printf("length is %d\n", utarray_len(pairs)); - it.a = 1; it.b=2; utarray_push_back(pairs, &it); printf("push\n"); - printf("length is %d\n", utarray_len(pairs)); - ip = (intpair_t*)utarray_back(pairs); - printf("back is %d %d\n", ip->a, ip->b); - utarray_pop_back(pairs); printf("pop\n"); - printf("length is %d\n", utarray_len(pairs)); - it.a = 1; it.b=2; utarray_push_back(pairs, &it); printf("push\n"); - it.a = 3; it.b=4; utarray_push_back(pairs, &it); printf("push\n"); - printf("length is %d\n", utarray_len(pairs)); - ip=NULL; - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - utarray_erase(pairs,0,1); printf("erase [0]\n"); - printf("length is %d\n", utarray_len(pairs)); - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - it.a = 1; it.b=2; utarray_push_back(pairs, &it); printf("push\n"); - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - utarray_clear(pairs); printf("clear\n"); - printf("length is %d\n", utarray_len(pairs)); - utarray_extend_back(pairs); printf("extend\n"); - ip = (intpair_t*)utarray_back(pairs); - printf("length is %d\n", utarray_len(pairs)); - printf("ip points to [0] ? %s\n", (ip==(intpair_t*)utarray_front(pairs)) ? "yes" : "no"); - it.a = 1; it.b=2; utarray_push_back(pairs, &it); printf("push\n"); - ip=NULL; - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - utarray_erase(pairs,1,1); printf("erase [1]\n"); - printf("length is %d\n", utarray_len(pairs)); - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - it.a = 3; it.b=4; utarray_push_back(pairs, &it); printf("push\n"); - for(ip=(intpair_t*)utarray_front(pairs);ip;ip=(intpair_t*)utarray_next(pairs,ip)) { - printf("%d %d\n", ip->a,ip->b); - } - ip = (intpair_t*)utarray_back(pairs); - printf("back is %d %d\n", ip->a, ip->b); - utarray_new(pairs_cpy, &pairicd); - utarray_concat(pairs_cpy, pairs); printf("copy\n"); - printf("cpy length is %d\n", utarray_len(pairs_cpy)); - ip=NULL; - while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip))) printf("cpy %d %d\n", ip->a, ip->b); - it.a=5; it.b=6; utarray_insert(pairs_cpy, &it, 0); printf("insert cpy[0]\n"); - printf("cpy length is %d\n", utarray_len(pairs_cpy)); - while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip))) printf("cpy %d %d\n", ip->a, ip->b); - utarray_erase(pairs_cpy,0,2); printf("erase cpy [0] [1]\n"); - printf("cpy length is %d\n", utarray_len(pairs_cpy)); - while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip))) printf("cpy %d %d\n", ip->a, ip->b); - utarray_inserta(pairs_cpy, pairs, 1); printf("inserta at cpy[1]\n"); - printf("cpy length is %d\n", utarray_len(pairs_cpy)); - while( (ip=(intpair_t*)utarray_next(pairs_cpy,ip))) printf("cpy %d %d\n", ip->a, ip->b); - utarray_free(pairs_cpy); printf("free cpy\n"); - printf("length is %d\n", utarray_len(pairs)); - utarray_resize(pairs, 30); printf("resize to 30\n"); - printf("length is %d\n", utarray_len(pairs)); - while( (ip=(intpair_t*)utarray_next(pairs,ip))) printf("%d %d\n", ip->a, ip->b); - utarray_resize(pairs, 1); printf("resize to 1\n"); - printf("length is %d\n", utarray_len(pairs)); - utarray_resize(pairs, zero); printf("resize to 0\n"); - printf("length is %d\n", utarray_len(pairs)); - utarray_free(pairs); printf("free\n"); - return 0; -} diff --git a/src/util/uthash/tests/test44.ans b/src/util/uthash/tests/test44.ans deleted file mode 100644 index f771df8..0000000 --- a/src/util/uthash/tests/test44.ans +++ /dev/null @@ -1,9 +0,0 @@ -0 1 2 3 4 5 6 7 8 9 -9 8 7 6 5 4 3 2 1 0 -9 8 7 3 2 1 0 -9 3 2 1 0 -3 2 1 0 -3 2 1 -3 2 1 0 0 -3 2 1 - diff --git a/src/util/uthash/tests/test44.c b/src/util/uthash/tests/test44.c deleted file mode 100644 index 6c419c2..0000000 --- a/src/util/uthash/tests/test44.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include "utarray.h" - -int reverse(const void *a,const void*b) { - int _a = *(int*)a; - int _b = *(int*)b; - return _b - _a; -} - -int main() { - UT_array *a; - int i, *p; - utarray_new(a, &ut_int_icd); - for(i=0;i<10;i++) utarray_push_back(a,&i); - for(p=(int*)utarray_front(a); p; p=(int*)utarray_next(a,p)) printf("%d ",*p); - printf("\n"); - utarray_sort(a,reverse); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_erase(a,3,3); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_erase(a,1,2); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_erase(a,0,1); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_erase(a,3,1); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_resize(a,5); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_resize(a,3); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_erase(a,0,3); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); - printf("\n"); - utarray_free(a); - return 0; -} - diff --git a/src/util/uthash/tests/test45.ans b/src/util/uthash/tests/test45.ans deleted file mode 100644 index 7e744bc..0000000 --- a/src/util/uthash/tests/test45.ans +++ /dev/null @@ -1,3 +0,0 @@ -1 2 3 4 5 6 7 8 -1 2 3 100 4 5 6 7 8 -1 2 3 100 4 5 6 7 8 1000 diff --git a/src/util/uthash/tests/test45.c b/src/util/uthash/tests/test45.c deleted file mode 100644 index dca7d9b..0000000 --- a/src/util/uthash/tests/test45.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include "utarray.h" - -int main() { - UT_array *a; - int i, *p=NULL; - utarray_new(a, &ut_int_icd); - for(i=0;i<10;i++) utarray_push_back(a,&i); - utarray_pop_back(a); - utarray_erase(a,0,1); - while ( (p=(int*)utarray_next(a,p))) printf("%d ",*p); printf("\n"); - i = 100; - utarray_insert(a,&i,3); - while ( (p=(int*)utarray_next(a,p))) printf("%d ",*p); printf("\n"); - utarray_extend_back(a); - p = (int*)utarray_back(a); - *p = 1000; - p = NULL; - while ( (p=(int*)utarray_next(a,p))) printf("%d ",*p); printf("\n"); - utarray_clear(a); - utarray_free(a); - return 0; -} - diff --git a/src/util/uthash/tests/test46.ans b/src/util/uthash/tests/test46.ans deleted file mode 100644 index be625f3..0000000 --- a/src/util/uthash/tests/test46.ans +++ /dev/null @@ -1,11 +0,0 @@ -hello world -begin hello world -alt begin hello world oth -hello world oth -hello world -hello world begin hello world -begin hello world -sorting strs2 -begin hello world -reverse sorting strs2 -world hello begin diff --git a/src/util/uthash/tests/test46.c b/src/util/uthash/tests/test46.c deleted file mode 100644 index b7b785a..0000000 --- a/src/util/uthash/tests/test46.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "utarray.h" - -int strsort(const void *_a, const void *_b) { - char *a = *(char**)_a; - char *b = *(char**)_b; - return strcmp(a,b); -} - -int revsort(const void *_a, const void *_b) { - char *a = *(char**)_a; - char *b = *(char**)_b; - return strcmp(b,a); -} - -int main() { - UT_array *strs,*strs2; - char *s, **p=NULL; - utarray_new(strs, &ut_str_icd); - s="hello"; utarray_push_back(strs, &s); - s="world"; utarray_push_back(strs, &s); - while ( (p=(char**)utarray_next(strs,p))) printf("%s ",*p); printf("\n"); - s="begin"; utarray_insert(strs,&s,0); - while ( (p=(char**)utarray_next(strs,p))) printf("%s ",*p); printf("\n"); - utarray_new(strs2, &ut_str_icd); - s="alt"; utarray_push_back(strs2, &s); - s="oth"; utarray_push_back(strs2, &s); - utarray_inserta(strs2, strs, 1); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - utarray_erase(strs2,0,2); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - utarray_pop_back(strs2); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - utarray_concat(strs2, strs); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - utarray_clear(strs2); - utarray_concat(strs2, strs); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - printf("sorting strs2\n"); - utarray_sort(strs2,strsort); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - printf("reverse sorting strs2\n"); - utarray_sort(strs2,revsort); - while ( (p=(char**)utarray_next(strs2,p))) printf("%s ",*p); printf("\n"); - utarray_clear(strs2); - utarray_free(strs2); - utarray_free(strs); - return 0; -} diff --git a/src/util/uthash/tests/test47.ans b/src/util/uthash/tests/test47.ans deleted file mode 100644 index 546e064..0000000 --- a/src/util/uthash/tests/test47.ans +++ /dev/null @@ -1,8 +0,0 @@ -hello world -hello world text - second -hello world text second -cleared, length t now: 0 -length s now: 23 -one 1 two 2 three (3) -length t now: 21 diff --git a/src/util/uthash/tests/test47.c b/src/util/uthash/tests/test47.c deleted file mode 100644 index 1434d5a..0000000 --- a/src/util/uthash/tests/test47.c +++ /dev/null @@ -1,28 +0,0 @@ -#include /* printf */ -#include "utstring.h" - -int main() { - UT_string *s,*t; - char a[] = " text"; - utstring_new(s); - utstring_new(t); - - utstring_printf(s,"hello %s", "world"); - printf("%s\n", utstring_body(s)); - utstring_bincpy(s,a,sizeof(a)-1); - printf("%s\n", utstring_body(s)); - utstring_printf(t," second"); - printf("%s\n", utstring_body(t)); - utstring_concat(s,t); - printf("%s\n", utstring_body(s)); - utstring_clear(t); - printf("cleared, length t now: %d\n", utstring_len(t)); - printf("length s now: %d\n", utstring_len(s)); - utstring_printf(t,"one %d two %u three %s", 1, 2, "(3)"); - printf("%s\n", utstring_body(t)); - printf("length t now: %d\n", utstring_len(t)); - - - utstring_free(s); - return 0; -} diff --git a/src/util/uthash/tests/test48.ans b/src/util/uthash/tests/test48.ans deleted file mode 100644 index 8b1acc1..0000000 --- a/src/util/uthash/tests/test48.ans +++ /dev/null @@ -1,10 +0,0 @@ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 diff --git a/src/util/uthash/tests/test48.c b/src/util/uthash/tests/test48.c deleted file mode 100644 index dd0fa75..0000000 --- a/src/util/uthash/tests/test48.c +++ /dev/null @@ -1,20 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test49.ans b/src/util/uthash/tests/test49.ans deleted file mode 100644 index 94954ab..0000000 --- a/src/util/uthash/tests/test49.ans +++ /dev/null @@ -1,2 +0,0 @@ -hello -world diff --git a/src/util/uthash/tests/test49.c b/src/util/uthash/tests/test49.c deleted file mode 100644 index 00afb7a..0000000 --- a/src/util/uthash/tests/test49.c +++ /dev/null @@ -1,20 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test5.ans b/src/util/uthash/tests/test5.ans deleted file mode 100644 index 2ece88f..0000000 --- a/src/util/uthash/tests/test5.ans +++ /dev/null @@ -1,5 +0,0 @@ -cookie 0 found, user id 0 -cookie 4 found, user id 2 -cookie 16 found, user id 4 -cookie 36 found, user id 6 -cookie 64 found, user id 8 diff --git a/src/util/uthash/tests/test5.c b/src/util/uthash/tests/test5.c deleted file mode 100644 index 7cfd278..0000000 --- a/src/util/uthash/tests/test5.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; - UT_hash_handle alth; -} example_user_t; - -int main(int argc,char *argv[]) { - int i,j; - example_user_t *user, *tmp, *users=NULL, *altusers=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - HASH_ADD(alth,altusers,cookie,sizeof(int),user); - } - - /* find cookie corresponding to each even ID */ - for(i=0;i<10;i+=2) { - j=i*i; - HASH_FIND(alth,altusers,&j,sizeof(int),tmp); - if (tmp) printf("cookie %d found, user id %d\n", tmp->cookie, tmp->id); - else printf("cookie %d not found\n", j); - } - return 0; -} diff --git a/src/util/uthash/tests/test50.ans b/src/util/uthash/tests/test50.ans deleted file mode 100644 index 1191247..0000000 --- a/src/util/uthash/tests/test50.ans +++ /dev/null @@ -1,2 +0,0 @@ -1 -2 diff --git a/src/util/uthash/tests/test50.c b/src/util/uthash/tests/test50.c deleted file mode 100644 index 0ef78d7..0000000 --- a/src/util/uthash/tests/test50.c +++ /dev/null @@ -1,19 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test51.ans b/src/util/uthash/tests/test51.ans deleted file mode 100644 index 3caf269..0000000 --- a/src/util/uthash/tests/test51.ans +++ /dev/null @@ -1,2 +0,0 @@ -1 2 -10 20 diff --git a/src/util/uthash/tests/test51.c b/src/util/uthash/tests/test51.c deleted file mode 100644 index 48df2e0..0000000 --- a/src/util/uthash/tests/test51.c +++ /dev/null @@ -1,28 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test52.ans b/src/util/uthash/tests/test52.ans deleted file mode 100644 index bd37407..0000000 --- a/src/util/uthash/tests/test52.ans +++ /dev/null @@ -1,2 +0,0 @@ -1 hello -2 world diff --git a/src/util/uthash/tests/test52.c b/src/util/uthash/tests/test52.c deleted file mode 100644 index b4b3465..0000000 --- a/src/util/uthash/tests/test52.c +++ /dev/null @@ -1,39 +0,0 @@ -#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; -} - diff --git a/src/util/uthash/tests/test53.ans b/src/util/uthash/tests/test53.ans deleted file mode 100644 index a042389..0000000 --- a/src/util/uthash/tests/test53.ans +++ /dev/null @@ -1 +0,0 @@ -hello world! diff --git a/src/util/uthash/tests/test53.c b/src/util/uthash/tests/test53.c deleted file mode 100644 index b8fafc5..0000000 --- a/src/util/uthash/tests/test53.c +++ /dev/null @@ -1,13 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test54.ans b/src/util/uthash/tests/test54.ans deleted file mode 100644 index df0083e..0000000 --- a/src/util/uthash/tests/test54.ans +++ /dev/null @@ -1,2 +0,0 @@ -length: 21 -hello world hi there diff --git a/src/util/uthash/tests/test54.c b/src/util/uthash/tests/test54.c deleted file mode 100644 index 8774bc5..0000000 --- a/src/util/uthash/tests/test54.c +++ /dev/null @@ -1,23 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test55.ans b/src/util/uthash/tests/test55.ans deleted file mode 100644 index a75e7be..0000000 --- a/src/util/uthash/tests/test55.ans +++ /dev/null @@ -1,2 +0,0 @@ -length is 3 -number 10 diff --git a/src/util/uthash/tests/test55.c b/src/util/uthash/tests/test55.c deleted file mode 100644 index e421d68..0000000 --- a/src/util/uthash/tests/test55.c +++ /dev/null @@ -1,18 +0,0 @@ -#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; -} diff --git a/src/util/uthash/tests/test56.ans b/src/util/uthash/tests/test56.ans deleted file mode 100644 index f615d00..0000000 --- a/src/util/uthash/tests/test56.ans +++ /dev/null @@ -1,65 +0,0 @@ -ADRIAN -ARNOLDO -CARROLL -CARY -CHONG -CLIFTON -CODY -COLTON -CORNELL -DAMON -DANNIE -DARIO -DONN -DOUG -DOUGLAS -FREDERICK -FRITZ -GERALD -GUS -HARVEY -IRVING -ISAIAH -JARVIS -JOHN -KENTON -LAURENCE -LESTER -LINCOLN -LOWELL -NELSON -NEVILLE -NIGEL -NORMAND -ODIS -OMAR -ORLANDO -RAYMUNDO -REX -ROLANDO -RON -SHANE -TONEY -TRINIDAD -WALTER -WARNER -WARREN -WES -WILLARD -WILLIAM -WINFRED -XAVIER -found WES - -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -length is 3 -number 10 diff --git a/src/util/uthash/tests/test56.c b/src/util/uthash/tests/test56.c deleted file mode 100644 index 88c015c..0000000 --- a/src/util/uthash/tests/test56.c +++ /dev/null @@ -1,86 +0,0 @@ -#include /* malloc */ -#include /* printf */ -#include -#include "uthash.h" -#include "utlist.h" -#include "utstring.h" - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -#define BUFLEN 20 - -typedef struct el { - char bname[BUFLEN]; - struct el *next, *prev; -} el; - -int namecmp(void *_a, void *_b) { - el *a = (el*)_a; - el *b = (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; - int i; - example_user_t *user, *users=NULL; - - char linebuf[BUFLEN]; - FILE *file; - - UT_string *s; - char binary[] = "\xff\xff"; - - 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); - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - - 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; -} diff --git a/src/util/uthash/tests/test57.ans b/src/util/uthash/tests/test57.ans deleted file mode 100644 index 4d3bb1d..0000000 --- a/src/util/uthash/tests/test57.ans +++ /dev/null @@ -1 +0,0 @@ -found diff --git a/src/util/uthash/tests/test57.c b/src/util/uthash/tests/test57.c deleted file mode 100644 index 6a96e27..0000000 --- a/src/util/uthash/tests/test57.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include "uthash.h" - -typedef struct { - void *key; - int i; - UT_hash_handle hh; -} el_t; - -el_t *hash = NULL; -char *someaddr = NULL; - -int main() { - el_t *d; - el_t *e = (el_t*)malloc(sizeof(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; -} diff --git a/src/util/uthash/tests/test58.ans b/src/util/uthash/tests/test58.ans deleted file mode 100644 index a23ca72..0000000 --- a/src/util/uthash/tests/test58.ans +++ /dev/null @@ -1,18 +0,0 @@ -user 0, cookie 0 -user 1, cookie 1 -user 2, cookie 4 -user 3, cookie 9 -user 4, cookie 16 -user 5, cookie 25 -user 6, cookie 36 -user 7, cookie 49 -user 8, cookie 64 -user 9, cookie 81 -10 users. Deleting odd id's... -user 0, cookie 0 -user 2, cookie 4 -user 4, cookie 16 -user 6, cookie 36 -user 8, cookie 64 -5 users. Deleting remaining id's... -0 users. diff --git a/src/util/uthash/tests/test58.c b/src/util/uthash/tests/test58.c deleted file mode 100644 index 6ec891c..0000000 --- a/src/util/uthash/tests/test58.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i,c; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) - exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - - - c = HASH_COUNT(users); - printf("%d users. Deleting odd id's...\n", c); - /* delete the odd id's */ - HASH_ITER(hh, users, user, tmp) { - if (user->id & 1) HASH_DEL(users,user); - } - - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - - c = HASH_COUNT(users); - printf("%d users. Deleting remaining id's...\n", c); - /* delete all that are left */ - HASH_ITER(hh, users, user, tmp) { - HASH_DEL(users,user); - } - - c = HASH_COUNT(users); - printf("%d users.\n", c); - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test59.ans b/src/util/uthash/tests/test59.ans deleted file mode 100644 index e19f2f6..0000000 --- a/src/util/uthash/tests/test59.ans +++ /dev/null @@ -1 +0,0 @@ -$items{bob}{age} = 37 diff --git a/src/util/uthash/tests/test59.c b/src/util/uthash/tests/test59.c deleted file mode 100644 index 1fab25e..0000000 --- a/src/util/uthash/tests/test59.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include "uthash.h" - -/* hash of hashes */ -typedef struct item { - char name[10]; - struct item *sub; - int val; - UT_hash_handle hh; -} item_t; - -item_t *items=NULL; - -int main(int argc, char *argvp[]) { - item_t *item1, *item2, *tmp1, *tmp2; - - /* make initial element */ - item_t *i = malloc(sizeof(*i)); - strcpy(i->name, "bob"); - i->sub = NULL; - i->val = 0; - HASH_ADD_STR(items, name, i); - - /* add a sub hash table off this element */ - item_t *s = malloc(sizeof(*s)); - strcpy(s->name, "age"); - s->sub = NULL; - s->val = 37; - HASH_ADD_STR(i->sub, name, s); - - /* iterate over hash elements */ - HASH_ITER(hh, items, item1, tmp1) { - HASH_ITER(hh, item1->sub, item2, tmp2) { - printf("$items{%s}{%s} = %d\n", item1->name, item2->name, item2->val); - } - } - - /* clean up both hash tables */ - HASH_ITER(hh, items, item1, tmp1) { - HASH_ITER(hh, item1->sub, item2, tmp2) { - HASH_DEL(item1->sub, item2); - free(item2); - } - HASH_DEL(items, item1); - free(item1); - } - - return 0; -} diff --git a/src/util/uthash/tests/test6.ans b/src/util/uthash/tests/test6.ans deleted file mode 100644 index 5c95811..0000000 --- a/src/util/uthash/tests/test6.ans +++ /dev/null @@ -1 +0,0 @@ -alt malloc table diff --git a/src/util/uthash/tests/test6.c b/src/util/uthash/tests/test6.c deleted file mode 100644 index 40fc2aa..0000000 --- a/src/util/uthash/tests/test6.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -/* Set up macros for alternative malloc/free functions */ -#undef uthash_malloc -#undef uthash_free -#define uthash_malloc(sz) alt_malloc(sz) -#define uthash_free(ptr,sz) alt_free(ptr) - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -void *alt_malloc(size_t sz) { - if (sz == sizeof(UT_hash_table)) printf("%s\n", "alt malloc table"); - return malloc(sz); -} -void alt_free(void *ptr) { - /* printf("%s\n", "alt_free"); */ - free(ptr); -} - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* delete each ID */ - for(i=0;i<10;i++) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - HASH_DEL(users,tmp); - free(tmp); - } else printf("user id %d not found\n", i); - } - - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test60.ans b/src/util/uthash/tests/test60.ans deleted file mode 100644 index e19f2f6..0000000 --- a/src/util/uthash/tests/test60.ans +++ /dev/null @@ -1 +0,0 @@ -$items{bob}{age} = 37 diff --git a/src/util/uthash/tests/test60.c b/src/util/uthash/tests/test60.c deleted file mode 100644 index a1c1486..0000000 --- a/src/util/uthash/tests/test60.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include -#include "uthash.h" - -/* hash of hashes */ -typedef struct item { - char name[10]; - struct item *sub; - int val; - UT_hash_handle hh; -} item_t; - -item_t *items=NULL; - -int main(int argc, char *argvp[]) { - item_t *item1, *item2, *tmp1, *tmp2; - - /* make initial element */ - item_t *i = malloc(sizeof(*i)); - strcpy(i->name, "bob"); - i->sub = NULL; - i->val = 0; - HASH_ADD_STR(items, name, i); - - /* add a sub hash table off this element */ - item_t *s = malloc(sizeof(*s)); - strcpy(s->name, "age"); - s->sub = NULL; - s->val = 37; - HASH_ADD_STR(i->sub, name, s); - - /* iterate over hash elements, printing and freeing them */ - 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); - HASH_DEL(item1->sub, item2); - free(item2); - } - HASH_DEL(items, item1); - free(item1); - } - - return 0; -} diff --git a/src/util/uthash/tests/test61.ans b/src/util/uthash/tests/test61.ans deleted file mode 100644 index 39c63b4..0000000 --- a/src/util/uthash/tests/test61.ans +++ /dev/null @@ -1,16 +0,0 @@ -hello -world -one -two -three -sorting -finding hello - hello -finding one - one -finding three - three -finding two - two -finding world - world diff --git a/src/util/uthash/tests/test61.c b/src/util/uthash/tests/test61.c deleted file mode 100644 index b569957..0000000 --- a/src/util/uthash/tests/test61.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include "utarray.h" - -int strsort(const void *_a, const void *_b) { - char *a = *(char**)_a; - char *b = *(char**)_b; - return strcmp(a,b); -} - -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); - s = "one"; utarray_push_back(strs, &s); - s = "two"; utarray_push_back(strs, &s); - s = "three"; utarray_push_back(strs, &s); - - p = NULL; - while ( (p=(char**)utarray_next(strs,p))) { - s = *p; - printf("%s\n",s); - } - - printf("sorting\n"); - utarray_sort(strs,strsort); - - p = NULL; - while ( (p=(char**)utarray_next(strs,p))) { - s = *p; - printf("finding %s\n",s); - p = utarray_find(strs,&s,strsort); - printf(" %s\n", p ? (*p) : "failed"); - } - - utarray_free(strs); - - return 0; -} diff --git a/src/util/uthash/tests/test62.ans b/src/util/uthash/tests/test62.ans deleted file mode 100644 index 1b71740..0000000 --- a/src/util/uthash/tests/test62.ans +++ /dev/null @@ -1,20 +0,0 @@ -al aligned (y): y -u1 aligned (n): n -u2 aligned (n): n -u3 aligned (n): n - -al plus1 (n): n -u1 plus1 (y): y -u2 plus1 (n): n -u3 plus1 (n): n - -al plus2 (n): n -u1 plus2 (n): n -u2 plus2 (y): y -u3 plus2 (n): n - -al plus3 (n): n -u1 plus3 (n): n -u2 plus3 (n): n -u3 plus3 (y): y - diff --git a/src/util/uthash/tests/test62.c b/src/util/uthash/tests/test62.c deleted file mode 100644 index ae80b9e..0000000 --- a/src/util/uthash/tests/test62.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include "uthash.h" - -#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 yn(rc) (rc?"y":"n") -int main(int argc,char*argv[]) { - unsigned rc; - char *c = malloc(8); - *(c+0) = 0x00; unsigned *al = (unsigned*)(c+0); - *(c+1) = 0x01; unsigned *u1 = (unsigned*)(c+1); - *(c+2) = 0x02; unsigned *u2 = (unsigned*)(c+2); - *(c+3) = 0x03; unsigned *u3 = (unsigned*)(c+3); - *(c+4) = 0x04; - *(c+5) = 0x05; - *(c+6) = 0x06; - *(c+7) = 0x07; - - /* ---------------------------------------- */ - /* test whether alignment is detected properly */ - - rc = MUR_PLUS0_ALIGNED(al); printf("al aligned (y): %s\n", yn(rc)); - rc = MUR_PLUS0_ALIGNED(u1); printf("u1 aligned (n): %s\n", yn(rc)); - rc = MUR_PLUS0_ALIGNED(u2); printf("u2 aligned (n): %s\n", yn(rc)); - rc = MUR_PLUS0_ALIGNED(u3); printf("u3 aligned (n): %s\n", yn(rc)); - printf("\n"); - - rc = MUR_PLUS1_ALIGNED(al); printf("al plus1 (n): %s\n", yn(rc)); - rc = MUR_PLUS1_ALIGNED(u1); printf("u1 plus1 (y): %s\n", yn(rc)); - rc = MUR_PLUS1_ALIGNED(u2); printf("u2 plus1 (n): %s\n", yn(rc)); - rc = MUR_PLUS1_ALIGNED(u3); printf("u3 plus1 (n): %s\n", yn(rc)); - printf("\n"); - - rc = MUR_PLUS2_ALIGNED(al); printf("al plus2 (n): %s\n", yn(rc)); - rc = MUR_PLUS2_ALIGNED(u1); printf("u1 plus2 (n): %s\n", yn(rc)); - rc = MUR_PLUS2_ALIGNED(u2); printf("u2 plus2 (y): %s\n", yn(rc)); - rc = MUR_PLUS2_ALIGNED(u3); printf("u3 plus2 (n): %s\n", yn(rc)); - printf("\n"); - - rc = MUR_PLUS3_ALIGNED(al); printf("al plus3 (n): %s\n", yn(rc)); - rc = MUR_PLUS3_ALIGNED(u1); printf("u1 plus3 (n): %s\n", yn(rc)); - rc = MUR_PLUS3_ALIGNED(u2); printf("u2 plus3 (n): %s\n", yn(rc)); - rc = MUR_PLUS3_ALIGNED(u3); printf("u3 plus3 (y): %s\n", yn(rc)); - printf("\n"); - - /* ---------------------------------------- */ - /* test careful reassembly of an unaligned integer */ -#if 0 /* commented out since result is endian dependent */ - rc = MUR_GETBLOCK(al,0); printf("%x\n", rc); - rc = MUR_GETBLOCK(u1,0); printf("%x\n", rc); - rc = MUR_GETBLOCK(u2,0); printf("%x\n", rc); - rc = MUR_GETBLOCK(u3,0); printf("%x\n", rc); -#endif - - return 0; -} diff --git a/src/util/uthash/tests/test63.ans b/src/util/uthash/tests/test63.ans deleted file mode 100644 index c570c50..0000000 --- a/src/util/uthash/tests/test63.ans +++ /dev/null @@ -1,7 +0,0 @@ -LL macros -a b c -d e f -a b c d e f -d e f -d e f -a b diff --git a/src/util/uthash/tests/test63.c b/src/util/uthash/tests/test63.c deleted file mode 100644 index 488f20b..0000000 --- a/src/util/uthash/tests/test63.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA = NULL, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test LL macros */ - printf("LL macros\n"); - LL_APPEND(headA,&els[0]); - LL_APPEND(headA,&els[1]); - LL_APPEND(headA,&els[2]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - LL_APPEND(headB,&els[3]); - LL_APPEND(headB,&els[4]); - LL_APPEND(headB,&els[5]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - LL_CONCAT(headA,headB); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* other variations */ - headA = NULL; - LL_CONCAT(headA,headB); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - headB = NULL; - LL_CONCAT(headA,headB); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - headA=NULL; - headB=NULL; - LL_APPEND(headA,&els[0]); - LL_APPEND(headB,&els[1]); - LL_CONCAT(headA,headB); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test64.ans b/src/util/uthash/tests/test64.ans deleted file mode 100644 index 1640241..0000000 --- a/src/util/uthash/tests/test64.ans +++ /dev/null @@ -1,7 +0,0 @@ -DL macros -a b c -d e f -a b c d e f -d e f -d e f -a b diff --git a/src/util/uthash/tests/test64.c b/src/util/uthash/tests/test64.c deleted file mode 100644 index 9d49e2d..0000000 --- a/src/util/uthash/tests/test64.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA = NULL, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test DL macros */ - printf("DL macros\n"); - DL_APPEND(headA,&els[0]); - DL_APPEND(headA,&els[1]); - DL_APPEND(headA,&els[2]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - DL_APPEND(headB,&els[3]); - DL_APPEND(headB,&els[4]); - DL_APPEND(headB,&els[5]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - DL_CONCAT(headA,headB); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* other variations */ - headA = NULL; - DL_CONCAT(headA,headB); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - headB = NULL; - DL_CONCAT(headA,headB); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - headA=NULL; - headB=NULL; - DL_APPEND(headA,&els[0]); - DL_APPEND(headB,&els[1]); - DL_CONCAT(headA,headB); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test65.ans b/src/util/uthash/tests/test65.ans deleted file mode 100644 index 5312b22..0000000 --- a/src/util/uthash/tests/test65.ans +++ /dev/null @@ -1,4 +0,0 @@ -LRU deleting JOHN - 0 -LRU deleting WILLIAM - 1 diff --git a/src/util/uthash/tests/test65.c b/src/util/uthash/tests/test65.c deleted file mode 100644 index ac0d4d8..0000000 --- a/src/util/uthash/tests/test65.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include "uthash.h" - -// this is an example of how to do a LRU cache in C using uthash -// http://troydhanson.github.com/uthash/ -// by Jehiah Czebotar 2011 - jehiah@gmail.com -// this code is in the public domain http://unlicense.org/ - -#define MAX_CACHE_SIZE 50 /* a real value would be much larger */ - -struct CacheEntry { - char *key; - char *value; - UT_hash_handle hh; -}; -struct CacheEntry *cache = NULL; - -char * /*value*/ find_in_cache(char *key) -{ - struct CacheEntry *entry; - HASH_FIND_STR(cache, key, entry); - if (entry) { - // remove it (so the subsequent add will throw it on the front of the list) - HASH_DELETE(hh, cache, entry); - HASH_ADD_KEYPTR(hh, cache, entry->key, strlen(entry->key), entry); - return entry->value; - } - return NULL; -} - -void add_to_cache(char *key, char *value) -{ - struct CacheEntry *entry, *tmp_entry; - entry = malloc(sizeof(struct CacheEntry)); - entry->key = strdup(key); - entry->value = strdup(value); - HASH_ADD_KEYPTR(hh, cache, entry->key, strlen(entry->key), entry); - - // prune the cache to MAX_CACHE_SIZE - if (HASH_COUNT(cache) >= MAX_CACHE_SIZE) { - HASH_ITER(hh, cache, entry, tmp_entry) { - // prune the first entry (loop is based on insertion order so this deletes the oldest item) - printf("LRU deleting %s %s\n", entry->key, entry->value); - HASH_DELETE(hh, cache, entry); - free(entry->key); - free(entry->value); - free(entry); - break; - } - } -} - -/* main added by Troy D. Hanson */ -int main(int argc, char *argv[]) { - char linebuf[100], nbuf[10]; - FILE *file; - int i=0; - - if ( (file = fopen( "test65.dat", "r" )) == NULL ) { - perror("can't open: "); - exit(-1); - } - - while (fgets(linebuf,sizeof(linebuf),file) != NULL) { - snprintf(nbuf,sizeof(nbuf),"%u",i++); - add_to_cache(linebuf, nbuf); - } - - fclose(file); - return 0; -} diff --git a/src/util/uthash/tests/test65.dat b/src/util/uthash/tests/test65.dat deleted file mode 100644 index bb6051b..0000000 --- a/src/util/uthash/tests/test65.dat +++ /dev/null @@ -1,51 +0,0 @@ -JOHN -WILLIAM -WALTER -DOUGLAS -GERALD -FREDERICK -WARREN -SHANE -LESTER -RON -HARVEY -ADRIAN -CODY -NELSON -CLIFTON -WILLARD -DOUG -ORLANDO -REX -OMAR -DAMON -LOWELL -IRVING -CARROLL -LAURENCE -ROLANDO -CARY -XAVIER -ISAIAH -GUS -JARVIS -WINFRED -RAYMUNDO -LINCOLN -CORNELL -NIGEL -NORMAND -FRITZ -DONN -TRINIDAD -ODIS -DANNIE -DARIO -KENTON -CHONG -NEVILLE -TONEY -WARNER -WES -COLTON -ARNOLDO diff --git a/src/util/uthash/tests/test66.ans b/src/util/uthash/tests/test66.ans deleted file mode 100644 index 727f397..0000000 --- a/src/util/uthash/tests/test66.ans +++ /dev/null @@ -1,20 +0,0 @@ -added bob (id 0) -added jack (id 1) -added gary (id 2) -added ty (id 3) -added bo (id 4) -added phil (id 5) -added art (id 6) -added gil (id 7) -added buck (id 8) -added ted (id 9) -found bob (id 0) -found jack (id 1) -found gary (id 2) -found ty (id 3) -found bo (id 4) -found phil (id 5) -found art (id 6) -found gil (id 7) -found buck (id 8) -found ted (id 9) diff --git a/src/util/uthash/tests/test66.c b/src/util/uthash/tests/test66.c deleted file mode 100644 index d50deb5..0000000 --- a/src/util/uthash/tests/test66.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "uthash.h" -#include -#include /* malloc */ - -typedef struct person_t { - char first_name[10]; - int id; - UT_hash_handle hh; -} person_t; - -int main(int argc, char*argv[]) { - person_t *people=NULL, *person; - const char **name; - const char * names[] = { "bob", "jack", "gary", "ty", "bo", "phil", "art", - "gil", "buck", "ted", NULL }; - int id=0; - - for(name=names; *name; name++) { - if ( (person = (person_t*)malloc(sizeof(person_t))) == NULL) exit(-1); - strncpy(person->first_name, *name,10); - person->id = id++; - HASH_ADD_STR(people,first_name,person); - printf("added %s (id %d)\n", person->first_name, person->id); - } - - person=NULL; - person_t **p=&person; - - for(name=names; *name; name++) { - HASH_FIND_STR(people,*name,*p); - if (person) - printf("found %s (id %d)\n", person->first_name, person->id); - else - printf("failed to find %s\n", *name); - } - return 0; -} diff --git a/src/util/uthash/tests/test67.ans b/src/util/uthash/tests/test67.ans deleted file mode 100644 index cd70769..0000000 --- a/src/util/uthash/tests/test67.ans +++ /dev/null @@ -1,20 +0,0 @@ -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 diff --git a/src/util/uthash/tests/test67.c b/src/util/uthash/tests/test67.c deleted file mode 100644 index 00dc01a..0000000 --- a/src/util/uthash/tests/test67.c +++ /dev/null @@ -1,27 +0,0 @@ -#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_back(nums); - p!=NULL; - p=(int*)utarray_prev(nums,p)) { - printf("%d\n",*p); - } - - /* the other form of iteration starting from NULL (back) */ - p=NULL; - while ( (p=(int*)utarray_prev(nums,p))) { - printf("%d\n",*p); - } - - - utarray_free(nums); - - return 0; -} diff --git a/src/util/uthash/tests/test68.ans b/src/util/uthash/tests/test68.ans deleted file mode 100644 index 704cdc5..0000000 --- a/src/util/uthash/tests/test68.ans +++ /dev/null @@ -1,10 +0,0 @@ -DL replace elem -a b c d -e b c d -f b c d -f b c g -f b c h -f i j h -k l m n -s -t diff --git a/src/util/uthash/tests/test68.c b/src/util/uthash/tests/test68.c deleted file mode 100644 index 7c5e77d..0000000 --- a/src/util/uthash/tests/test68.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[20], *e, *tmp; - for(i=0;i<20;i++) els[i].id='a'+i; - - /* test DL macros */ - printf("DL replace elem\n"); - DL_APPEND(headA,&els[0]); - DL_APPEND(headA,&els[1]); - DL_APPEND(headA,&els[2]); - DL_APPEND(headA,&els[3]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace head elem */ - DL_REPLACE_ELEM(headA, &els[0], &els[4]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - DL_REPLACE_ELEM(headA, &els[4], &els[5]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace last elem */ - DL_REPLACE_ELEM(headA, &els[3], &els[6]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - DL_REPLACE_ELEM(headA, &els[6], &els[7]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace middle elem */ - DL_REPLACE_ELEM(headA, &els[1], &els[8]); - DL_REPLACE_ELEM(headA, &els[2], &els[9]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace all just to be sure the list is intact... */ - i = 10; - DL_FOREACH_SAFE(headA, e, tmp) { - DL_REPLACE_ELEM(headA, e, &els[i]); - i++; - } - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - DL_APPEND(headB, &els[18]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - DL_REPLACE_ELEM(headB, &els[18], &els[19]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test69.ans b/src/util/uthash/tests/test69.ans deleted file mode 100644 index fba8b64..0000000 --- a/src/util/uthash/tests/test69.ans +++ /dev/null @@ -1,11 +0,0 @@ -DL prepend elem -a b c d -e a b c d -f e a b c d -f e a b c g d -f e a b c h g d -f e a b i j c h g d -k f l e m a n b o i p j q c r h s g t d -u -v u -w v u diff --git a/src/util/uthash/tests/test69.c b/src/util/uthash/tests/test69.c deleted file mode 100644 index 169c222..0000000 --- a/src/util/uthash/tests/test69.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[26], *e, *tmp; - for(i=0;i<25;i++) els[i].id='a'+i; - - /* test DL macros */ - printf("DL prepend elem\n"); - DL_APPEND(headA,&els[0]); - DL_APPEND(headA,&els[1]); - DL_APPEND(headA,&els[2]); - DL_APPEND(headA,&els[3]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend head elem */ - DL_PREPEND_ELEM(headA, &els[0], &els[4]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - DL_PREPEND_ELEM(headA, &els[4], &els[5]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend last elem */ - DL_PREPEND_ELEM(headA, &els[3], &els[6]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - DL_PREPEND_ELEM(headA, &els[6], &els[7]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend middle elem */ - DL_PREPEND_ELEM(headA, &els[2], &els[8]); - DL_PREPEND_ELEM(headA, &els[2], &els[9]); - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend all just to be sure the list is intact... */ - i = 10; - DL_FOREACH_SAFE(headA, e, tmp) { - DL_PREPEND_ELEM(headA, e, &els[i]); - i++; - } - DL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - DL_APPEND(headB, &els[20]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - DL_PREPEND_ELEM(headB, &els[20], &els[21]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - DL_PREPEND_ELEM(headB, &els[21], &els[22]); - DL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test7.ans b/src/util/uthash/tests/test7.ans deleted file mode 100644 index e69de29..0000000 diff --git a/src/util/uthash/tests/test7.c b/src/util/uthash/tests/test7.c deleted file mode 100644 index 3f76c8d..0000000 --- a/src/util/uthash/tests/test7.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<1000;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* delete each ID */ - for(i=0;i<1000;i++) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - HASH_DEL(users,tmp); - free(tmp); - } else printf("user id %d not found\n", i); - } - - /* show the hash */ - for(user=users; user != NULL; user=(example_user_t*)(user->hh.next)) { - printf("user %d, cookie %d\n", user->id, user->cookie); - } - return 0; -} diff --git a/src/util/uthash/tests/test70.ans b/src/util/uthash/tests/test70.ans deleted file mode 100644 index 00298ec..0000000 --- a/src/util/uthash/tests/test70.ans +++ /dev/null @@ -1,10 +0,0 @@ -LL replace elem -a b c d -e b c d -f b c d -f b c g -f b c h -f i j h -k l m n -s -t diff --git a/src/util/uthash/tests/test70.c b/src/util/uthash/tests/test70.c deleted file mode 100644 index c4291be..0000000 --- a/src/util/uthash/tests/test70.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[20], *e, *tmp; - for(i=0;i<20;i++) els[i].id='a'+i; - - /* test LL macros */ - printf("LL replace elem\n"); - LL_APPEND(headA,&els[0]); - LL_APPEND(headA,&els[1]); - LL_APPEND(headA,&els[2]); - LL_APPEND(headA,&els[3]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace head elem */ - LL_REPLACE_ELEM(headA, &els[0], &els[4]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - LL_REPLACE_ELEM(headA, &els[4], &els[5]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace last elem */ - LL_REPLACE_ELEM(headA, &els[3], &els[6]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - LL_REPLACE_ELEM(headA, &els[6], &els[7]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace middle elem */ - LL_REPLACE_ELEM(headA, &els[1], &els[8]); - LL_REPLACE_ELEM(headA, &els[2], &els[9]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace all just to be sure the list is intact... */ - i = 10; - LL_FOREACH_SAFE(headA, e, tmp) { - LL_REPLACE_ELEM(headA, e, &els[i]); - i++; - } - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - LL_APPEND(headB, &els[18]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - LL_REPLACE_ELEM(headB, &els[18], &els[19]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test71.ans b/src/util/uthash/tests/test71.ans deleted file mode 100644 index 81d6b53..0000000 --- a/src/util/uthash/tests/test71.ans +++ /dev/null @@ -1,11 +0,0 @@ -LL prepend elem -a b c d -e a b c d -f e a b c d -f e a b c g d -f e a b c h g d -f e a b i j c h g d -k f l e m a n b o i p j q c r h s g t d -u -v u -w v u diff --git a/src/util/uthash/tests/test71.c b/src/util/uthash/tests/test71.c deleted file mode 100644 index e4126c1..0000000 --- a/src/util/uthash/tests/test71.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[26], *e, *tmp; - for(i=0;i<25;i++) els[i].id='a'+i; - - /* test LL macros */ - printf("LL prepend elem\n"); - LL_APPEND(headA,&els[0]); - LL_APPEND(headA,&els[1]); - LL_APPEND(headA,&els[2]); - LL_APPEND(headA,&els[3]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend head elem */ - LL_PREPEND_ELEM(headA, &els[0], &els[4]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - LL_PREPEND_ELEM(headA, &els[4], &els[5]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend last elem */ - LL_PREPEND_ELEM(headA, &els[3], &els[6]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - LL_PREPEND_ELEM(headA, &els[6], &els[7]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend middle elem */ - LL_PREPEND_ELEM(headA, &els[2], &els[8]); - LL_PREPEND_ELEM(headA, &els[2], &els[9]); - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend all just to be sure the list is intact... */ - i = 10; - LL_FOREACH_SAFE(headA, e, tmp) { - LL_PREPEND_ELEM(headA, e, &els[i]); - i++; - } - LL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - LL_APPEND(headB, &els[20]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - LL_PREPEND_ELEM(headB, &els[20], &els[21]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - LL_PREPEND_ELEM(headB, &els[21], &els[22]); - LL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test72.ans b/src/util/uthash/tests/test72.ans deleted file mode 100644 index b5ccb14..0000000 --- a/src/util/uthash/tests/test72.ans +++ /dev/null @@ -1,10 +0,0 @@ -CDL replace elem -a b c d -e b c d -f b c d -f b c g -f b c h -f i j h -k l m n -s -t diff --git a/src/util/uthash/tests/test72.c b/src/util/uthash/tests/test72.c deleted file mode 100644 index 51a6fc4..0000000 --- a/src/util/uthash/tests/test72.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[20], *e, *tmp, *tmp2; - for(i=0;i<20;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL replace elem\n"); - CDL_PREPEND(headA,&els[3]); - CDL_PREPEND(headA,&els[2]); - CDL_PREPEND(headA,&els[1]); - CDL_PREPEND(headA,&els[0]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace head elem */ - CDL_REPLACE_ELEM(headA, &els[0], &els[4]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - CDL_REPLACE_ELEM(headA, &els[4], &els[5]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace last elem */ - CDL_REPLACE_ELEM(headA, &els[3], &els[6]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - CDL_REPLACE_ELEM(headA, &els[6], &els[7]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace middle elem */ - CDL_REPLACE_ELEM(headA, &els[1], &els[8]); - CDL_REPLACE_ELEM(headA, &els[2], &els[9]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* replace all just to be sure the list is intact... */ - i = 10; - CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { - CDL_REPLACE_ELEM(headA, e, &els[i]); - i++; - } - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - CDL_PREPEND(headB, &els[18]); - CDL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - CDL_REPLACE_ELEM(headB, &els[18], &els[19]); - CDL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test73.ans b/src/util/uthash/tests/test73.ans deleted file mode 100644 index 2aa7bdc..0000000 --- a/src/util/uthash/tests/test73.ans +++ /dev/null @@ -1,11 +0,0 @@ -CDL prepend elem -a b c d -e a b c d -f e a b c d -f e a b c g d -f e a b c h g d -f e a b i j c h g d -k f l e m a n b o i p j q c r h s g t d -u -v u -w v u diff --git a/src/util/uthash/tests/test73.c b/src/util/uthash/tests/test73.c deleted file mode 100644 index f1112ea..0000000 --- a/src/util/uthash/tests/test73.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *next, *prev; -} el; - -el *headA, *headB = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[26], *e, *tmp, *tmp2; - for(i=0;i<25;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL prepend elem\n"); - CDL_PREPEND(headA,&els[3]); - CDL_PREPEND(headA,&els[2]); - CDL_PREPEND(headA,&els[1]); - CDL_PREPEND(headA,&els[0]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend head elem */ - CDL_PREPEND_ELEM(headA, &els[0], &els[4]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - CDL_PREPEND_ELEM(headA, &els[4], &els[5]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend last elem */ - CDL_PREPEND_ELEM(headA, &els[3], &els[6]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - CDL_PREPEND_ELEM(headA, &els[6], &els[7]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend middle elem */ - CDL_PREPEND_ELEM(headA, &els[2], &els[8]); - CDL_PREPEND_ELEM(headA, &els[2], &els[9]); - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* prepend all just to be sure the list is intact... */ - i = 10; - CDL_FOREACH_SAFE(headA, e, tmp, tmp2) { - CDL_PREPEND_ELEM(headA, e, &els[i]); - i++; - } - CDL_FOREACH(headA,e) printf("%c ", e->id); printf("\n"); - - /* single elem */ - CDL_PREPEND(headB, &els[20]); - CDL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - CDL_PREPEND_ELEM(headB, &els[20], &els[21]); - CDL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - CDL_PREPEND_ELEM(headB, &els[21], &els[22]); - CDL_FOREACH(headB,e) printf("%c ", e->id); printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test74.ans b/src/util/uthash/tests/test74.ans deleted file mode 100644 index 79a16ba..0000000 --- a/src/util/uthash/tests/test74.ans +++ /dev/null @@ -1,6 +0,0 @@ -"There are two needle" len=55 -"needle" len=8 -utstring_find()=14 -utstring_find()=46 -utstring_find()=-1 -FindCnt=2 diff --git a/src/util/uthash/tests/test74.c b/src/util/uthash/tests/test74.c deleted file mode 100644 index e11ad55..0000000 --- a/src/util/uthash/tests/test74.c +++ /dev/null @@ -1,41 +0,0 @@ -#include /* printf */ -#include "utstring.h" - -int main() { - UT_string *s,*t; - char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; - char V_NeedleStr[] = "needle\0s"; - long V_FindPos; - size_t V_FindCnt; - - - utstring_new(s); - utstring_new(t); - - utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); - printf("\"%s\" len=%u\n", utstring_body(s), utstring_len(s)); - utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); - printf("\"%s\" len=%u\n", utstring_body(t), utstring_len(t)); - - V_FindCnt = 0; - V_FindPos = 0; - do - { - V_FindPos = utstring_find(s, - V_FindPos, - utstring_body(t), - utstring_len(t)); - printf("utstring_find()=%ld\n", V_FindPos); - if (V_FindPos >= 0) - { - V_FindPos++; - V_FindCnt++; - } - } while (V_FindPos >= 0); - printf("FindCnt=%u\n", (unsigned)V_FindCnt); - - utstring_free(s); - utstring_free(t); - - return 0; -} diff --git a/src/util/uthash/tests/test75.ans b/src/util/uthash/tests/test75.ans deleted file mode 100644 index 8261ba3..0000000 --- a/src/util/uthash/tests/test75.ans +++ /dev/null @@ -1,6 +0,0 @@ -"There are two needle" len=55 -"needle" len=8 -utstring_findR()=46 -utstring_findR()=14 -utstring_findR()=-1 -FindCnt=2 diff --git a/src/util/uthash/tests/test75.c b/src/util/uthash/tests/test75.c deleted file mode 100644 index bb8e8e0..0000000 --- a/src/util/uthash/tests/test75.c +++ /dev/null @@ -1,41 +0,0 @@ -#include /* printf */ -#include "utstring.h" - -int main() { - UT_string *s,*t; - char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; - char V_NeedleStr[] = "needle\0s"; - long V_FindPos; - size_t V_FindCnt; - - - utstring_new(s); - utstring_new(t); - - utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); - printf("\"%s\" len=%u\n", utstring_body(s), utstring_len(s)); - utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); - printf("\"%s\" len=%u\n", utstring_body(t), utstring_len(t)); - - V_FindCnt = 0; - V_FindPos = -1; - do - { - V_FindPos = utstring_findR(s, - V_FindPos, - utstring_body(t), - utstring_len(t)); - printf("utstring_findR()=%ld\n", V_FindPos); - if (V_FindPos >= 0) - { - V_FindPos--; - V_FindCnt++; - } - } while (V_FindPos >= 0); - printf("FindCnt=%u\n", (unsigned)V_FindCnt); - - utstring_free(s); - utstring_free(t); - - return 0; -} diff --git a/src/util/uthash/tests/test76.ans b/src/util/uthash/tests/test76.ans deleted file mode 100644 index 79a16ba..0000000 --- a/src/util/uthash/tests/test76.ans +++ /dev/null @@ -1,6 +0,0 @@ -"There are two needle" len=55 -"needle" len=8 -utstring_find()=14 -utstring_find()=46 -utstring_find()=-1 -FindCnt=2 diff --git a/src/util/uthash/tests/test76.c b/src/util/uthash/tests/test76.c deleted file mode 100644 index 8ead835..0000000 --- a/src/util/uthash/tests/test76.c +++ /dev/null @@ -1,58 +0,0 @@ -#include /* printf */ -#include "utstring.h" - -int main() { - UT_string *s,*t; - char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; - char V_NeedleStr[] = "needle\0s"; - long *V_KMP_Table; - long V_FindPos; - size_t V_StartPos; - size_t V_FindCnt; - - - utstring_new(s); - utstring_new(t); - - utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); - printf("\"%s\" len=%u\n", utstring_body(s), utstring_len(s)); - utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); - printf("\"%s\" len=%u\n", utstring_body(t), utstring_len(t)); - - V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table); - - V_FindCnt = 0; - V_FindPos = 0; - V_StartPos = 0; - do - { - V_FindPos = _utstring_find(utstring_body(s) + V_StartPos, - utstring_len(s) - V_StartPos, - utstring_body(t), - utstring_len(t), - V_KMP_Table); - if (V_FindPos >= 0) - { - V_FindPos += V_StartPos; - V_FindCnt++; - V_StartPos = V_FindPos + 1; - } - printf("utstring_find()=%ld\n", V_FindPos); - } while (V_FindPos >= 0); - printf("FindCnt=%u\n", (unsigned)V_FindCnt); - - free(V_KMP_Table); - } - else - { - printf("malloc() failed...\n"); - } - - utstring_free(s); - utstring_free(t); - - return 0; -} diff --git a/src/util/uthash/tests/test77.ans b/src/util/uthash/tests/test77.ans deleted file mode 100644 index 3b2a109..0000000 --- a/src/util/uthash/tests/test77.ans +++ /dev/null @@ -1,13 +0,0 @@ -"There are two needle" len=55 -"needle" len=8 -utstring_find()=46 -utstring_find()=14 -utstring_find()=-1 -FindCnt=2 -expect 15 15 -expect 4 4 -expect -1 -1 -expect 11 11 -expect 4 4 -expect 11 11 -expect 0 0 diff --git a/src/util/uthash/tests/test77.c b/src/util/uthash/tests/test77.c deleted file mode 100644 index ee90b2a..0000000 --- a/src/util/uthash/tests/test77.c +++ /dev/null @@ -1,71 +0,0 @@ -#include /* printf */ -#include "utstring.h" - -int main() { - UT_string *s,*t; - char V_TestStr[] = "There are two needle\0s in this \0haystack with needle\0s."; - char V_NeedleStr[] = "needle\0s"; - long *V_KMP_Table; - long V_FindPos; - size_t V_StartPos; - size_t V_FindCnt; - - - utstring_new(s); - utstring_new(t); - - utstring_bincpy(s, V_TestStr, sizeof(V_TestStr)-1); - printf("\"%s\" len=%u\n", utstring_body(s), utstring_len(s)); - utstring_bincpy(t, V_NeedleStr, sizeof(V_NeedleStr)-1); - printf("\"%s\" len=%u\n", utstring_body(t), utstring_len(t)); - - V_KMP_Table = (long *)malloc(sizeof(long) * (utstring_len(t) + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table); - - V_FindCnt = 0; - V_FindPos = 0; - V_StartPos = utstring_len(s) - 1; - do - { - V_FindPos = _utstring_findR(utstring_body(s), - V_StartPos + 1, - utstring_body(t), - utstring_len(t), - V_KMP_Table); - if (V_FindPos >= 0) - { - V_FindCnt++; - V_StartPos = V_FindPos - 1; - } - printf("utstring_find()=%ld\n", V_FindPos); - } while (V_FindPos >= 0); - printf("FindCnt=%u\n", (unsigned)V_FindCnt); - - free(V_KMP_Table); - } - else - { - printf("malloc() failed...\n"); - } - - utstring_free(t); - utstring_clear(s); - utstring_printf(s,"ABC ABCDAB ABCDABCDABDE"); - int o; - - o=utstring_find( s, -9, "ABC", 3 ) ; printf("expect 15 %d\n",o); - o=utstring_find( s, 3, "ABC", 3 ) ; printf("expect 4 %d\n",o); - o=utstring_find( s, 16, "ABC", 3 ) ; printf("expect -1 %d\n",o); - o=utstring_findR( s, -9, "ABC", 3 ) ; printf("expect 11 %d\n",o); - o=utstring_findR( s, 12, "ABC", 3 ) ; printf("expect 4 %d\n",o); - o=utstring_findR( s, 13, "ABC", 3 ) ; printf("expect 11 %d\n",o); - o=utstring_findR( s, 2, "ABC", 3 ) ; printf("expect 0 %d\n",o); - - - - utstring_free(s); - - return 0; -} diff --git a/src/util/uthash/tests/test78.ans b/src/util/uthash/tests/test78.ans deleted file mode 100644 index 5c71cdf..0000000 --- a/src/util/uthash/tests/test78.ans +++ /dev/null @@ -1,28 +0,0 @@ -CDL macros -c b a -advancing head pointer -b a c -b a c b a c b a c b -b c a b c a b c a b -deleting b -a c -deleting (a) -c -deleting (c) - -DL macros -a b c -deleting tail c -a b -deleting head a -b -deleting head b - -LL macros -a b c -deleting tail c -a b -deleting head a -b -deleting head b - diff --git a/src/util/uthash/tests/test78.c b/src/util/uthash/tests/test78.c deleted file mode 100644 index f73e029..0000000 --- a/src/util/uthash/tests/test78.c +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include "utlist.h" - -typedef struct el { - int id; - struct el *Next, *Prev; -} el; - -el *head = NULL; - -int main(int argc, char *argv[]) { - int i; - el els[10], *e; - for(i=0;i<10;i++) els[i].id='a'+i; - - /* test CDL macros */ - printf("CDL macros\n"); - CDL_PREPEND2(head,&els[0],Prev,Next); - CDL_PREPEND2(head,&els[1],Prev,Next); - CDL_PREPEND2(head,&els[2],Prev,Next); - CDL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - /* point head to head->next */ - printf("advancing head pointer\n"); - head = head->Next; - CDL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop a few times */ - for(i=0,e=head;e && i<10;i++,e=e->Next) - printf("%c ", e->id); - printf("\n"); - - /* follow circular loop backwards a few times */ - for(i=0,e=head;e && i<10;i++,e=e->Prev) - printf("%c ", e->id); - printf("\n"); - - printf("deleting b\n"); - CDL_DELETE2(head,&els[1],Prev,Next); - CDL_FOREACH2(head,e,Next) printf("%c ", e->id); - printf("\n"); - printf("deleting (a)\n"); - CDL_DELETE2(head,&els[0],Prev,Next); - CDL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - printf("deleting (c)\n"); - CDL_DELETE2(head,&els[2],Prev,Next); - CDL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - /* test DL macros */ - printf("DL macros\n"); - DL_APPEND2(head,&els[0],Prev,Next); - DL_APPEND2(head,&els[1],Prev,Next); - DL_APPEND2(head,&els[2],Prev,Next); - DL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting tail c\n"); - DL_DELETE2(head,&els[2],Prev,Next); - DL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head a\n"); - DL_DELETE2(head,&els[0],Prev,Next); - DL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head b\n"); - DL_DELETE2(head,&els[1],Prev,Next); - DL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - /* test LL macros */ - printf("LL macros\n"); - LL_APPEND2(head,&els[0],Next); - LL_APPEND2(head,&els[1],Next); - LL_APPEND2(head,&els[2],Next); - LL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting tail c\n"); - LL_DELETE2(head,&els[2],Next); - LL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head a\n"); - LL_DELETE2(head,&els[0],Next); - LL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - printf("deleting head b\n"); - LL_DELETE2(head,&els[1],Next); - LL_FOREACH2(head,e,Next) - printf("%c ", e->id); - printf("\n"); - - return 0; -} diff --git a/src/util/uthash/tests/test79.ans b/src/util/uthash/tests/test79.ans deleted file mode 100644 index c8737e4..0000000 --- a/src/util/uthash/tests/test79.ans +++ /dev/null @@ -1,8 +0,0 @@ -added 10 100 -id 10, tag 100 -added 11 101 -id 10, tag 100 -id 11, tag 101 -replaced 11 that had tag 101 with tag 102 -id 10, tag 100 -id 11, tag 102 diff --git a/src/util/uthash/tests/test79.c b/src/util/uthash/tests/test79.c deleted file mode 100644 index f4ad83b..0000000 --- a/src/util/uthash/tests/test79.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include "uthash.h" - -typedef struct hs_t { - int id; - int tag; - UT_hash_handle hh; -} hs_t; - - -static void pr(hs_t **hdpp){ - hs_t *el, *tmp, *hdp = *hdpp; - HASH_ITER(hh, hdp, el, tmp){ - printf("id %d, tag %d\n",el->id,el->tag); - } -} - -int main(int argc, char *argv[]) { - - hs_t *hs_head=NULL, *tmp, *replaced=NULL; - - tmp = (hs_t*)malloc(sizeof(hs_t)); - tmp->id = 10; - tmp->tag = 100; - HASH_REPLACE_INT(hs_head,id,tmp,replaced); - if(replaced == NULL) - printf("added %d %d\n",tmp->id,tmp->tag); - else - printf("ERROR, ended up replacing a value, replaced: %p\n",replaced); - - pr(&hs_head); - - tmp = (hs_t*)malloc(sizeof(hs_t)); - tmp->id=11; - tmp->tag = 101; - HASH_REPLACE_INT(hs_head,id,tmp,replaced); - if(replaced == NULL) - printf("added %d %d\n",tmp->id,tmp->tag); - else - printf("ERROR, ended up replacing a value, replaced: %p\n",replaced); - - pr(&hs_head); - - tmp = (hs_t*)malloc(sizeof(hs_t)); - tmp->id=11; - tmp->tag = 102; - HASH_REPLACE_INT(hs_head,id,tmp,replaced); - if(replaced == NULL) - printf("ERROR, exected to replace a value with key: %d\n",tmp->id); - else - printf("replaced %d that had tag %d with tag %d\n",tmp->id,replaced->tag,tmp->tag); - - pr(&hs_head); - - return 0; -} diff --git a/src/util/uthash/tests/test8.ans b/src/util/uthash/tests/test8.ans deleted file mode 100644 index 9d28857..0000000 --- a/src/util/uthash/tests/test8.ans +++ /dev/null @@ -1,15 +0,0 @@ -num_items in hash: 1 -num_items in hash: 2 -num_items in hash: 3 -num_items in hash: 4 -num_items in hash: 5 -num_items in hash: 6 -num_items in hash: 7 -num_items in hash: 8 -num_items in hash: 9 -num_items in hash: 10 -deleted; num_items in hash: 9 -deleted; num_items in hash: 8 -deleted; num_items in hash: 7 -deleted; num_items in hash: 6 -deleted; num_items in hash: 5 diff --git a/src/util/uthash/tests/test8.c b/src/util/uthash/tests/test8.c deleted file mode 100644 index f7c7c8d..0000000 --- a/src/util/uthash/tests/test8.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<10;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - printf("num_items in hash: %d\n", user->hh.tbl->num_items); - } - - /* delete each even ID */ - for(i=0;i<10;i+=2) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - HASH_DEL(users,tmp); - free(tmp); - printf("deleted; num_items in hash: %d\n", user->hh.tbl->num_items); - } else printf("user id %d not found\n", i); - } - return 0; -} diff --git a/src/util/uthash/tests/test80.ans b/src/util/uthash/tests/test80.ans deleted file mode 100644 index 763f637..0000000 --- a/src/util/uthash/tests/test80.ans +++ /dev/null @@ -1,6 +0,0 @@ -0 1 2 3 4 5 6 7 8 9 -len: 10 - -0 1 2 3 4 5 6 7 8 9 0 11 -len: 12 - diff --git a/src/util/uthash/tests/test80.c b/src/util/uthash/tests/test80.c deleted file mode 100644 index 9a415b4..0000000 --- a/src/util/uthash/tests/test80.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include "utarray.h" - -int main() { - UT_array *a; - int i, *p; - utarray_new(a, &ut_int_icd); - for(i=0;i<10;i++) utarray_push_back(a,&i); - for(p=(int*)utarray_front(a); p; p=(int*)utarray_next(a,p)) printf("%d ",*p); - printf("\n"); - printf("len: %u\n\n", utarray_len(a)); - - i=11; utarray_insert(a, &i, 11); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); printf("\n"); - printf("len: %u\n\n", utarray_len(a)); - - utarray_free(a); - return 0; -} - diff --git a/src/util/uthash/tests/test81.ans b/src/util/uthash/tests/test81.ans deleted file mode 100644 index 24adbd9..0000000 --- a/src/util/uthash/tests/test81.ans +++ /dev/null @@ -1,6 +0,0 @@ -0 1 2 3 4 5 6 7 8 9 -len: 10 - -0 1 2 3 4 5 6 7 8 9 10 -len: 11 - diff --git a/src/util/uthash/tests/test81.c b/src/util/uthash/tests/test81.c deleted file mode 100644 index 022d42e..0000000 --- a/src/util/uthash/tests/test81.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include "utarray.h" - -int main() { - UT_array *a; - int i, *p; - utarray_new(a, &ut_int_icd); - for(i=0;i<10;i++) utarray_push_back(a,&i); - for(p=(int*)utarray_front(a); p; p=(int*)utarray_next(a,p)) printf("%d ",*p); - printf("\n"); - printf("len: %u\n\n", utarray_len(a)); - - i=10; utarray_insert(a, &i, 10); - while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); printf("\n"); - printf("len: %u\n\n", utarray_len(a)); - - utarray_free(a); - return 0; -} - diff --git a/src/util/uthash/tests/test82.ans b/src/util/uthash/tests/test82.ans deleted file mode 100644 index ce8f5b5..0000000 --- a/src/util/uthash/tests/test82.ans +++ /dev/null @@ -1,9 +0,0 @@ -0 1 2 3 4 5 6 7 8 9 -len: 10 - -0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 len: 20 - -0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 len: 30 - -0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 0 1 2 3 4 5 6 7 8 9 5 6 7 8 9 len: 40 - diff --git a/src/util/uthash/tests/test82.c b/src/util/uthash/tests/test82.c deleted file mode 100644 index 8860554..0000000 --- a/src/util/uthash/tests/test82.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "utarray.h" - -int main() { - UT_array *a,*b; - int i, *p; - utarray_new(a, &ut_int_icd); - utarray_new(b, &ut_int_icd); - - for(i=0;i<10;i++) utarray_push_back(a,&i); - for(p=(int*)utarray_front(a); p; p=(int*)utarray_next(a,p)) printf("%d ",*p); - printf("\n"); - printf("len: %u\n\n", utarray_len(a)); - - utarray_inserta(b,a,10); - for(p=(int*)utarray_front(b); p; p=(int*)utarray_next(b,p)) printf("%d ",*p); - printf("len: %u\n\n", utarray_len(b)); - - utarray_inserta(b,a,0); - for(p=(int*)utarray_front(b); p; p=(int*)utarray_next(b,p)) printf("%d ",*p); - printf("len: %u\n\n", utarray_len(b)); - - utarray_inserta(b,a,25); - for(p=(int*)utarray_front(b); p; p=(int*)utarray_next(b,p)) printf("%d ",*p); - printf("len: %u\n\n", utarray_len(b)); - - utarray_free(a); - utarray_free(b); - return 0; -} - diff --git a/src/util/uthash/tests/test9.ans b/src/util/uthash/tests/test9.ans deleted file mode 100644 index 13a9402..0000000 --- a/src/util/uthash/tests/test9.ans +++ /dev/null @@ -1,500 +0,0 @@ -user 0, cookie 0 -user 2, cookie 4 -user 4, cookie 16 -user 6, cookie 36 -user 8, cookie 64 -user 10, cookie 100 -user 12, cookie 144 -user 14, cookie 196 -user 16, cookie 256 -user 18, cookie 324 -user 20, cookie 400 -user 22, cookie 484 -user 24, cookie 576 -user 26, cookie 676 -user 28, cookie 784 -user 30, cookie 900 -user 32, cookie 1024 -user 34, cookie 1156 -user 36, cookie 1296 -user 38, cookie 1444 -user 40, cookie 1600 -user 42, cookie 1764 -user 44, cookie 1936 -user 46, cookie 2116 -user 48, cookie 2304 -user 50, cookie 2500 -user 52, cookie 2704 -user 54, cookie 2916 -user 56, cookie 3136 -user 58, cookie 3364 -user 60, cookie 3600 -user 62, cookie 3844 -user 64, cookie 4096 -user 66, cookie 4356 -user 68, cookie 4624 -user 70, cookie 4900 -user 72, cookie 5184 -user 74, cookie 5476 -user 76, cookie 5776 -user 78, cookie 6084 -user 80, cookie 6400 -user 82, cookie 6724 -user 84, cookie 7056 -user 86, cookie 7396 -user 88, cookie 7744 -user 90, cookie 8100 -user 92, cookie 8464 -user 94, cookie 8836 -user 96, cookie 9216 -user 98, cookie 9604 -user 100, cookie 10000 -user 102, cookie 10404 -user 104, cookie 10816 -user 106, cookie 11236 -user 108, cookie 11664 -user 110, cookie 12100 -user 112, cookie 12544 -user 114, cookie 12996 -user 116, cookie 13456 -user 118, cookie 13924 -user 120, cookie 14400 -user 122, cookie 14884 -user 124, cookie 15376 -user 126, cookie 15876 -user 128, cookie 16384 -user 130, cookie 16900 -user 132, cookie 17424 -user 134, cookie 17956 -user 136, cookie 18496 -user 138, cookie 19044 -user 140, cookie 19600 -user 142, cookie 20164 -user 144, cookie 20736 -user 146, cookie 21316 -user 148, cookie 21904 -user 150, cookie 22500 -user 152, cookie 23104 -user 154, cookie 23716 -user 156, cookie 24336 -user 158, cookie 24964 -user 160, cookie 25600 -user 162, cookie 26244 -user 164, cookie 26896 -user 166, cookie 27556 -user 168, cookie 28224 -user 170, cookie 28900 -user 172, cookie 29584 -user 174, cookie 30276 -user 176, cookie 30976 -user 178, cookie 31684 -user 180, cookie 32400 -user 182, cookie 33124 -user 184, cookie 33856 -user 186, cookie 34596 -user 188, cookie 35344 -user 190, cookie 36100 -user 192, cookie 36864 -user 194, cookie 37636 -user 196, cookie 38416 -user 198, cookie 39204 -user 200, cookie 40000 -user 202, cookie 40804 -user 204, cookie 41616 -user 206, cookie 42436 -user 208, cookie 43264 -user 210, cookie 44100 -user 212, cookie 44944 -user 214, cookie 45796 -user 216, cookie 46656 -user 218, cookie 47524 -user 220, cookie 48400 -user 222, cookie 49284 -user 224, cookie 50176 -user 226, cookie 51076 -user 228, cookie 51984 -user 230, cookie 52900 -user 232, cookie 53824 -user 234, cookie 54756 -user 236, cookie 55696 -user 238, cookie 56644 -user 240, cookie 57600 -user 242, cookie 58564 -user 244, cookie 59536 -user 246, cookie 60516 -user 248, cookie 61504 -user 250, cookie 62500 -user 252, cookie 63504 -user 254, cookie 64516 -user 256, cookie 65536 -user 258, cookie 66564 -user 260, cookie 67600 -user 262, cookie 68644 -user 264, cookie 69696 -user 266, cookie 70756 -user 268, cookie 71824 -user 270, cookie 72900 -user 272, cookie 73984 -user 274, cookie 75076 -user 276, cookie 76176 -user 278, cookie 77284 -user 280, cookie 78400 -user 282, cookie 79524 -user 284, cookie 80656 -user 286, cookie 81796 -user 288, cookie 82944 -user 290, cookie 84100 -user 292, cookie 85264 -user 294, cookie 86436 -user 296, cookie 87616 -user 298, cookie 88804 -user 300, cookie 90000 -user 302, cookie 91204 -user 304, cookie 92416 -user 306, cookie 93636 -user 308, cookie 94864 -user 310, cookie 96100 -user 312, cookie 97344 -user 314, cookie 98596 -user 316, cookie 99856 -user 318, cookie 101124 -user 320, cookie 102400 -user 322, cookie 103684 -user 324, cookie 104976 -user 326, cookie 106276 -user 328, cookie 107584 -user 330, cookie 108900 -user 332, cookie 110224 -user 334, cookie 111556 -user 336, cookie 112896 -user 338, cookie 114244 -user 340, cookie 115600 -user 342, cookie 116964 -user 344, cookie 118336 -user 346, cookie 119716 -user 348, cookie 121104 -user 350, cookie 122500 -user 352, cookie 123904 -user 354, cookie 125316 -user 356, cookie 126736 -user 358, cookie 128164 -user 360, cookie 129600 -user 362, cookie 131044 -user 364, cookie 132496 -user 366, cookie 133956 -user 368, cookie 135424 -user 370, cookie 136900 -user 372, cookie 138384 -user 374, cookie 139876 -user 376, cookie 141376 -user 378, cookie 142884 -user 380, cookie 144400 -user 382, cookie 145924 -user 384, cookie 147456 -user 386, cookie 148996 -user 388, cookie 150544 -user 390, cookie 152100 -user 392, cookie 153664 -user 394, cookie 155236 -user 396, cookie 156816 -user 398, cookie 158404 -user 400, cookie 160000 -user 402, cookie 161604 -user 404, cookie 163216 -user 406, cookie 164836 -user 408, cookie 166464 -user 410, cookie 168100 -user 412, cookie 169744 -user 414, cookie 171396 -user 416, cookie 173056 -user 418, cookie 174724 -user 420, cookie 176400 -user 422, cookie 178084 -user 424, cookie 179776 -user 426, cookie 181476 -user 428, cookie 183184 -user 430, cookie 184900 -user 432, cookie 186624 -user 434, cookie 188356 -user 436, cookie 190096 -user 438, cookie 191844 -user 440, cookie 193600 -user 442, cookie 195364 -user 444, cookie 197136 -user 446, cookie 198916 -user 448, cookie 200704 -user 450, cookie 202500 -user 452, cookie 204304 -user 454, cookie 206116 -user 456, cookie 207936 -user 458, cookie 209764 -user 460, cookie 211600 -user 462, cookie 213444 -user 464, cookie 215296 -user 466, cookie 217156 -user 468, cookie 219024 -user 470, cookie 220900 -user 472, cookie 222784 -user 474, cookie 224676 -user 476, cookie 226576 -user 478, cookie 228484 -user 480, cookie 230400 -user 482, cookie 232324 -user 484, cookie 234256 -user 486, cookie 236196 -user 488, cookie 238144 -user 490, cookie 240100 -user 492, cookie 242064 -user 494, cookie 244036 -user 496, cookie 246016 -user 498, cookie 248004 -user 500, cookie 250000 -user 502, cookie 252004 -user 504, cookie 254016 -user 506, cookie 256036 -user 508, cookie 258064 -user 510, cookie 260100 -user 512, cookie 262144 -user 514, cookie 264196 -user 516, cookie 266256 -user 518, cookie 268324 -user 520, cookie 270400 -user 522, cookie 272484 -user 524, cookie 274576 -user 526, cookie 276676 -user 528, cookie 278784 -user 530, cookie 280900 -user 532, cookie 283024 -user 534, cookie 285156 -user 536, cookie 287296 -user 538, cookie 289444 -user 540, cookie 291600 -user 542, cookie 293764 -user 544, cookie 295936 -user 546, cookie 298116 -user 548, cookie 300304 -user 550, cookie 302500 -user 552, cookie 304704 -user 554, cookie 306916 -user 556, cookie 309136 -user 558, cookie 311364 -user 560, cookie 313600 -user 562, cookie 315844 -user 564, cookie 318096 -user 566, cookie 320356 -user 568, cookie 322624 -user 570, cookie 324900 -user 572, cookie 327184 -user 574, cookie 329476 -user 576, cookie 331776 -user 578, cookie 334084 -user 580, cookie 336400 -user 582, cookie 338724 -user 584, cookie 341056 -user 586, cookie 343396 -user 588, cookie 345744 -user 590, cookie 348100 -user 592, cookie 350464 -user 594, cookie 352836 -user 596, cookie 355216 -user 598, cookie 357604 -user 600, cookie 360000 -user 602, cookie 362404 -user 604, cookie 364816 -user 606, cookie 367236 -user 608, cookie 369664 -user 610, cookie 372100 -user 612, cookie 374544 -user 614, cookie 376996 -user 616, cookie 379456 -user 618, cookie 381924 -user 620, cookie 384400 -user 622, cookie 386884 -user 624, cookie 389376 -user 626, cookie 391876 -user 628, cookie 394384 -user 630, cookie 396900 -user 632, cookie 399424 -user 634, cookie 401956 -user 636, cookie 404496 -user 638, cookie 407044 -user 640, cookie 409600 -user 642, cookie 412164 -user 644, cookie 414736 -user 646, cookie 417316 -user 648, cookie 419904 -user 650, cookie 422500 -user 652, cookie 425104 -user 654, cookie 427716 -user 656, cookie 430336 -user 658, cookie 432964 -user 660, cookie 435600 -user 662, cookie 438244 -user 664, cookie 440896 -user 666, cookie 443556 -user 668, cookie 446224 -user 670, cookie 448900 -user 672, cookie 451584 -user 674, cookie 454276 -user 676, cookie 456976 -user 678, cookie 459684 -user 680, cookie 462400 -user 682, cookie 465124 -user 684, cookie 467856 -user 686, cookie 470596 -user 688, cookie 473344 -user 690, cookie 476100 -user 692, cookie 478864 -user 694, cookie 481636 -user 696, cookie 484416 -user 698, cookie 487204 -user 700, cookie 490000 -user 702, cookie 492804 -user 704, cookie 495616 -user 706, cookie 498436 -user 708, cookie 501264 -user 710, cookie 504100 -user 712, cookie 506944 -user 714, cookie 509796 -user 716, cookie 512656 -user 718, cookie 515524 -user 720, cookie 518400 -user 722, cookie 521284 -user 724, cookie 524176 -user 726, cookie 527076 -user 728, cookie 529984 -user 730, cookie 532900 -user 732, cookie 535824 -user 734, cookie 538756 -user 736, cookie 541696 -user 738, cookie 544644 -user 740, cookie 547600 -user 742, cookie 550564 -user 744, cookie 553536 -user 746, cookie 556516 -user 748, cookie 559504 -user 750, cookie 562500 -user 752, cookie 565504 -user 754, cookie 568516 -user 756, cookie 571536 -user 758, cookie 574564 -user 760, cookie 577600 -user 762, cookie 580644 -user 764, cookie 583696 -user 766, cookie 586756 -user 768, cookie 589824 -user 770, cookie 592900 -user 772, cookie 595984 -user 774, cookie 599076 -user 776, cookie 602176 -user 778, cookie 605284 -user 780, cookie 608400 -user 782, cookie 611524 -user 784, cookie 614656 -user 786, cookie 617796 -user 788, cookie 620944 -user 790, cookie 624100 -user 792, cookie 627264 -user 794, cookie 630436 -user 796, cookie 633616 -user 798, cookie 636804 -user 800, cookie 640000 -user 802, cookie 643204 -user 804, cookie 646416 -user 806, cookie 649636 -user 808, cookie 652864 -user 810, cookie 656100 -user 812, cookie 659344 -user 814, cookie 662596 -user 816, cookie 665856 -user 818, cookie 669124 -user 820, cookie 672400 -user 822, cookie 675684 -user 824, cookie 678976 -user 826, cookie 682276 -user 828, cookie 685584 -user 830, cookie 688900 -user 832, cookie 692224 -user 834, cookie 695556 -user 836, cookie 698896 -user 838, cookie 702244 -user 840, cookie 705600 -user 842, cookie 708964 -user 844, cookie 712336 -user 846, cookie 715716 -user 848, cookie 719104 -user 850, cookie 722500 -user 852, cookie 725904 -user 854, cookie 729316 -user 856, cookie 732736 -user 858, cookie 736164 -user 860, cookie 739600 -user 862, cookie 743044 -user 864, cookie 746496 -user 866, cookie 749956 -user 868, cookie 753424 -user 870, cookie 756900 -user 872, cookie 760384 -user 874, cookie 763876 -user 876, cookie 767376 -user 878, cookie 770884 -user 880, cookie 774400 -user 882, cookie 777924 -user 884, cookie 781456 -user 886, cookie 784996 -user 888, cookie 788544 -user 890, cookie 792100 -user 892, cookie 795664 -user 894, cookie 799236 -user 896, cookie 802816 -user 898, cookie 806404 -user 900, cookie 810000 -user 902, cookie 813604 -user 904, cookie 817216 -user 906, cookie 820836 -user 908, cookie 824464 -user 910, cookie 828100 -user 912, cookie 831744 -user 914, cookie 835396 -user 916, cookie 839056 -user 918, cookie 842724 -user 920, cookie 846400 -user 922, cookie 850084 -user 924, cookie 853776 -user 926, cookie 857476 -user 928, cookie 861184 -user 930, cookie 864900 -user 932, cookie 868624 -user 934, cookie 872356 -user 936, cookie 876096 -user 938, cookie 879844 -user 940, cookie 883600 -user 942, cookie 887364 -user 944, cookie 891136 -user 946, cookie 894916 -user 948, cookie 898704 -user 950, cookie 902500 -user 952, cookie 906304 -user 954, cookie 910116 -user 956, cookie 913936 -user 958, cookie 917764 -user 960, cookie 921600 -user 962, cookie 925444 -user 964, cookie 929296 -user 966, cookie 933156 -user 968, cookie 937024 -user 970, cookie 940900 -user 972, cookie 944784 -user 974, cookie 948676 -user 976, cookie 952576 -user 978, cookie 956484 -user 980, cookie 960400 -user 982, cookie 964324 -user 984, cookie 968256 -user 986, cookie 972196 -user 988, cookie 976144 -user 990, cookie 980100 -user 992, cookie 984064 -user 994, cookie 988036 -user 996, cookie 992016 -user 998, cookie 996004 diff --git a/src/util/uthash/tests/test9.c b/src/util/uthash/tests/test9.c deleted file mode 100644 index a8a16dd..0000000 --- a/src/util/uthash/tests/test9.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "uthash.h" -#include /* malloc */ -#include /* printf */ - -typedef struct example_user_t { - int id; - int cookie; - UT_hash_handle hh; -} example_user_t; - -int main(int argc,char *argv[]) { - int i; - example_user_t *user, *tmp, *users=NULL; - - /* create elements */ - for(i=0;i<1000;i++) { - if ( (user = (example_user_t*)malloc(sizeof(example_user_t))) == NULL) exit(-1); - user->id = i; - user->cookie = i*i; - HASH_ADD_INT(users,id,user); - } - - /* delete each ID */ - for(i=0;i<1000;i+=2) { - HASH_FIND_INT(users,&i,tmp); - if (tmp) { - printf("user %d, cookie %d\n", tmp->id, tmp->cookie); - } else printf("user id %d not found\n", i); - } - return 0; -} diff --git a/src/util/uthash/tests/threads/README b/src/util/uthash/tests/threads/README deleted file mode 100644 index e49a62e..0000000 --- a/src/util/uthash/tests/threads/README +++ /dev/null @@ -1,2 +0,0 @@ -test1: exercise a two-reader, one-writer, rwlock-protected hash. -test2: a template for a nthread, nloop kind of program diff --git a/src/util/uthash/tests/threads/do_tests b/src/util/uthash/tests/threads/do_tests deleted file mode 100755 index e6809a1..0000000 --- a/src/util/uthash/tests/threads/do_tests +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -my @tests; -for (glob "test*[0-9]") { - push @tests, $_ if -e "$_.ans"; -} - -my $num_failed=0; - -for my $test (@tests) { - `./$test > $test.out 2> $test.err`; - `diff $test.out $test.ans`; - print "$test failed\n" if $?; - $num_failed++ if $?; - unlink "$test.err" if -z "$test.err"; -} - -print scalar @tests . " tests conducted, $num_failed failed.\n"; -exit $num_failed; diff --git a/src/util/uthash/tests/threads/test1.c b/src/util/uthash/tests/threads/test1.c deleted file mode 100644 index 1045086..0000000 --- a/src/util/uthash/tests/threads/test1.c +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "uthash.h" - -#undef uthash_noexpand_fyi -#define uthash_noexpand_fyi fprintf(stderr,"warning: bucket expansion inhibited\n"); - -#define LOOPS 100000 - -typedef struct { - int i; - UT_hash_handle hh; -} elt; - -elt *elts=NULL; /* this is our hash table which two threads will use */ -pthread_rwlock_t lock; - -void *thread_routine_r( void *arg ) { - int i; - long num_found=0; - elt *e; - - for(i=0;ii = i; - HASH_ADD_INT(elts, i, e); - } - pthread_rwlock_unlock(&lock); - } - return (void*)num_deld; -} - -int main() { - unsigned i; - long num_added=0; - int status; - pthread_t thread_r1,thread_r2,thread_w1,thread_w2; - void *thread_result; - elt tmp, *e; - - if (pthread_rwlock_init(&lock,NULL) != 0) { - fprintf(stderr,"lock init failed\n"); - exit(-1); - } - - if ( status = pthread_create( &thread_r1, NULL, thread_routine_r, NULL )) { - printf("failure: status %d\n", status); - exit(-1); - } - if ( status = pthread_create( &thread_r2, NULL, thread_routine_r, NULL )) { - printf("failure: status %d\n", status); - exit(-1); - } - if ( status = pthread_create( &thread_w1, NULL, thread_routine_w, NULL )) { - printf("failure: status %d\n", status); - exit(-1); - } - if ( status = pthread_create( &thread_w2, NULL, thread_routine_w, NULL )) { - printf("failure: status %d\n", status); - exit(-1); - } - - status = pthread_join( thread_r1, &thread_result ); - printf("thread result: %d %ld\n", status, (long)thread_result); - - status = pthread_join( thread_r2, &thread_result ); - printf("thread result: %d %ld\n", status, (long)thread_result); - - status = pthread_join( thread_w1, &thread_result ); - printf("thread result: %d %ld\n", status, (long)thread_result); - - status = pthread_join( thread_w2, &thread_result ); - printf("thread result: %d %ld\n", status, (long)thread_result); - - i = HASH_COUNT(elts); - printf("final count of items in hash: %u\n", i); -} diff --git a/src/util/uthash/tests/threads/test2.c b/src/util/uthash/tests/threads/test2.c deleted file mode 100644 index 20d984f..0000000 --- a/src/util/uthash/tests/threads/test2.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "uthash.h" - -#undef uthash_noexpand_fyi -#define uthash_noexpand_fyi fprintf(stderr,"warning: bucket expansion inhibited\n"); - -#define LOOPS 100000 -#define NTHREADS 2 - -typedef struct { - int i; - int v; - UT_hash_handle hh; -} elt; - -elt *elts=NULL; /* this is our hash table which two threads will use */ -pthread_rwlock_t lock; - -void *thread_routine( void *arg ) { - int keepgoing=0; - /* TODO write me */ - return NULL; -} - -int main() { - unsigned i; - long num_added=0; - int status; - pthread_t thread[NTHREADS]; - void *thread_result; - elt tmp, *e; - - if (pthread_rwlock_init(&lock,NULL) != 0) { - fprintf(stderr,"lock init failed\n"); - exit(-1); - } - - /* populate it to start */ - for(i=0; ii = i; - e->v = 0; - HASH_ADD_INT(elts, i, e); - } - - for(i=0; i