├── .editorconfig ├── .gitignore ├── COPYING ├── Makefile.am ├── README ├── autogen.sh ├── configure.ac ├── fnv_hash.c ├── fnv_hash.h ├── hash_table.c ├── hash_table.h ├── int-set.c ├── int-set.h ├── meson.build ├── set.c ├── set.h └── tests ├── .gitignore ├── Makefile.am ├── collision.c ├── collision_replacement.c ├── delete_and_lookup.c ├── delete_management.c ├── deleted_key.c ├── destroy_callback.c ├── insert_and_lookup.c ├── insert_many.c ├── int-set ├── .gitignore ├── Makefile.am ├── collision_replacement.c ├── delete_and_lookup.c ├── delete_management.c ├── insert_and_lookup.c ├── insert_many.c ├── null_destroy.c ├── null_remove.c ├── random_entry.c ├── replace_deleted.c └── replacement.c ├── null_destroy.c ├── random_entry.c ├── remove_null.c ├── replacement.c └── set ├── .gitignore ├── Makefile.am ├── collision_replacement.c ├── delete_and_lookup.c ├── delete_management.c ├── deleted_key.c ├── destroy_callback.c ├── insert_and_lookup.c ├── insert_many.c ├── null_destroy.c ├── null_remove.c ├── random_entry.c └── replacement.c /.editorconfig: -------------------------------------------------------------------------------- 1 | # To use this config on you editor, follow the instructions at: 2 | # http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | insert_final_newline = true 9 | tab_width = 8 10 | indent_style = tab 11 | 12 | [meson.build,meson_options.txt] 13 | indent_style = space 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | .libs 3 | Makefile 4 | Makefile.in 5 | *.la 6 | *.lo 7 | *.o 8 | *~ 9 | aclocal.m4 10 | autom4te.cache 11 | compile 12 | config.guess 13 | config.log 14 | config.status 15 | config.sub 16 | configure 17 | configure.lineno 18 | depcomp 19 | install-sh 20 | libtool 21 | ltmain.sh 22 | missing 23 | stamp-h1 24 | cscope.* 25 | test-driver 26 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright © 1988-2004 Keith Packard and Bart Massey. All Rights Reserved. 2 | Copyright © 2009 Intel Corporation 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, 9 | sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall 14 | be included in all copies or substantial portions of the 15 | Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 18 | KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 19 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 20 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 21 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | Except as contained in this notice, the names of the authors 27 | or their institutions shall not be used in advertising or 28 | otherwise to promote the sale, use or other dealings in this 29 | Software without prior written authorization from the 30 | authors. 31 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright © 2009 Intel Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | 22 | AUTOMAKE_OPTIONS = foreign 23 | 24 | SUBDIRS = . tests 25 | 26 | AM_CFLAGS = $(WARN_CFLAGS) 27 | 28 | noinst_LTLIBRARIES = \ 29 | libhash_table.la \ 30 | libint-set.la \ 31 | libset.la 32 | 33 | libhash_table_la_SOURCES = \ 34 | fnv_hash.c \ 35 | fnv_hash.h \ 36 | hash_table.c \ 37 | hash_table.h 38 | 39 | libint_set_la_SOURCES = \ 40 | int-set.c \ 41 | int-set.h 42 | 43 | libset_la_SOURCES = \ 44 | fnv_hash.c \ 45 | fnv_hash.h \ 46 | set.c \ 47 | set.h 48 | 49 | EXTRA_DIST = \ 50 | COPYING \ 51 | README 52 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a simple hash table implementation written in plain old C. The goal 2 | is for this code to be reusable in many of the projects I've worked on that 3 | could use something better than a poorly-tuned chaining implementation. 4 | 5 | A variant is included which is just a set -- hash and key, not hash, key, and 6 | data. 7 | 8 | The intention is that users of this code copy it directly into their 9 | repositories, as it's quite small and should see very little development. 10 | 11 | The summary of this implementation would be that it uses open addressing 12 | with rehashing. The table stores for each entry: 13 | 14 | * uint32_t hash of the key. 15 | * pointer to the key. 16 | * pointer to the data. 17 | 18 | Inserts occur at key->hash % hash->size. When an insert collides, the insert 19 | steps through the table using the reprobe stride until a free or dead entry is 20 | found. When an insert occurs with a key matching a key already in the table, 21 | the new data is associated with the key. Note that old key/data is not freed, 22 | so if memory management is required, do a search before insert. 23 | 24 | When searching, the search starts at key % hash_size and continues at 25 | increments of reprobe as with inserts, until the matching entry or an 26 | unallocated entry is found. 27 | 28 | When deleting an entry, the entry is marked deleted. 29 | 30 | Performance considerations: 31 | 32 | * Only an extra 10% free entries is given at any table size. 33 | 34 | This means that as entries are added, the performance of insertion and 35 | lookups will degrade as one approaches maximum entries until the table 36 | gets resized. Unless an outside entry manager results in a maximum 37 | number of entries close to the hash table's current size limit, this 38 | shouldn't be a concern. 39 | 40 | * Repeated deletions fill the table with deleted entry markers. 41 | 42 | This means that a table that was filled, then emptied, will have 43 | performance for unsuccessful searches in O(hash->size) 44 | 45 | This is worked around in practice by later inserts into a hash table 46 | with many deletes in it triggering a rehash at the current size. 47 | 48 | In addition to the core hash_table implementation, a sample of the FNV-1a 49 | 32-bit hash function is included for convenience for those that don't wish 50 | to analyze hash functions on their own. 51 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | srcdir=`dirname $0` 4 | test -z "$srcdir" && srcdir=. 5 | 6 | ORIGDIR=`pwd` 7 | cd $srcdir 8 | 9 | autoreconf -v --install || exit 1 10 | cd $ORIGDIR || exit $? 11 | 12 | $srcdir/configure "$@" 13 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # Copyright © 2009 Intel Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | # 22 | # Authors: 23 | # Eric Anholt 24 | 25 | AC_PREREQ(2.57) 26 | AC_INIT([hash_table], 27 | 1.0, 28 | [https://freedesktop.org/~anholt/hash_table], 29 | hash_table) 30 | 31 | AC_CONFIG_SRCDIR([Makefile.am]) 32 | 33 | AM_INIT_AUTOMAKE([dist-bzip2]) 34 | AC_PROG_LIBTOOL 35 | AC_PROG_CC 36 | 37 | # Enable quiet compiles on automake 1.11. 38 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 39 | 40 | WARN_CFLAGS="" 41 | 42 | if test "x$GCC" = "xyes"; then 43 | WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \ 44 | -Wmissing-prototypes -Wmissing-declarations \ 45 | -Wnested-externs -fno-strict-aliasing" 46 | fi 47 | 48 | AC_SUBST([WARN_CFLAGS]) 49 | 50 | AC_OUTPUT([ 51 | Makefile 52 | tests/Makefile 53 | tests/set/Makefile 54 | tests/int-set/Makefile 55 | ]) 56 | -------------------------------------------------------------------------------- /fnv_hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | /* Quick FNV-1a hash implementation based on: 28 | * http://www.isthe.com/chongo/tech/comp/fnv/ 29 | * 30 | * FNV-1a may not be the best hash out there -- Jenkins's lookup3 is supposed 31 | * to be quite good, and it may beat FNV. But FNV has the advantage that it 32 | * involves almost no code. 33 | */ 34 | 35 | #include 36 | #include "fnv_hash.h" 37 | 38 | uint32_t 39 | fnv1_hash_string(const char *key) 40 | { 41 | uint32_t hash = 2166136261ul; 42 | const uint8_t *bytes = (uint8_t *)key; 43 | 44 | while (*bytes != 0) { 45 | hash ^= *bytes; 46 | hash = hash * 0x01000193; 47 | bytes++; 48 | } 49 | 50 | return hash; 51 | } 52 | 53 | uint32_t 54 | fnv1_hash_data(const void *data, size_t size) 55 | { 56 | uint32_t hash = 2166136261ul; 57 | const uint8_t *bytes = (uint8_t *)data; 58 | 59 | while (size-- != 0) { 60 | hash ^= *bytes; 61 | hash = hash * 0x01000193; 62 | bytes++; 63 | } 64 | 65 | return hash; 66 | } 67 | 68 | int 69 | string_key_equals(const void *a, const void *b) 70 | { 71 | return strcmp(a, b) == 0; 72 | } 73 | -------------------------------------------------------------------------------- /fnv_hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 2014 Broadcom 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | * 24 | * Authors: 25 | * Eric Anholt 26 | */ 27 | 28 | /* Quick FNV-1 hash implementation based on: 29 | * http://www.isthe.com/chongo/tech/comp/fnv/ 30 | */ 31 | 32 | #include 33 | 34 | uint32_t fnv1_hash_string(const char *key); 35 | uint32_t fnv1_hash_data(const void *data, size_t size); 36 | 37 | int string_key_equals(const void *a, const void *b); 38 | 39 | #define hash_table_create_for_string() \ 40 | hash_table_create((uint32_t (*)(const void *key))fnv1_hash_string, \ 41 | string_key_equals) 42 | 43 | #define set_create_for_string() \ 44 | set_create((uint32_t (*)(const void *key))fnv1_hash_string, \ 45 | string_key_equals) 46 | -------------------------------------------------------------------------------- /hash_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 1988-2004 Keith Packard and Bart Massey. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | * 24 | * Except as contained in this notice, the names of the authors 25 | * or their institutions shall not be used in advertising or 26 | * otherwise to promote the sale, use or other dealings in this 27 | * Software without prior written authorization from the 28 | * authors. 29 | * 30 | * Authors: 31 | * Eric Anholt 32 | * Keith Packard 33 | */ 34 | 35 | #include 36 | #include 37 | 38 | #include "hash_table.h" 39 | 40 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 41 | 42 | /* 43 | * From Knuth -- a good choice for hash/rehash values is p, p-2 where 44 | * p and p-2 are both prime. These tables are sized to have an extra 10% 45 | * free to avoid exponential performance degradation as the hash table fills 46 | */ 47 | 48 | static const uint32_t deleted_key_value; 49 | static const void *deleted_key = &deleted_key_value; 50 | 51 | static const struct { 52 | uint32_t max_entries, size, rehash; 53 | } hash_sizes[] = { 54 | { 2, 5, 3 }, 55 | { 4, 7, 5 }, 56 | { 8, 13, 11 }, 57 | { 16, 19, 17 }, 58 | { 32, 43, 41 }, 59 | { 64, 73, 71 }, 60 | { 128, 151, 149 }, 61 | { 256, 283, 281 }, 62 | { 512, 571, 569 }, 63 | { 1024, 1153, 1151 }, 64 | { 2048, 2269, 2267 }, 65 | { 4096, 4519, 4517 }, 66 | { 8192, 9013, 9011 }, 67 | { 16384, 18043, 18041 }, 68 | { 32768, 36109, 36107 }, 69 | { 65536, 72091, 72089 }, 70 | { 131072, 144409, 144407 }, 71 | { 262144, 288361, 288359 }, 72 | { 524288, 576883, 576881 }, 73 | { 1048576, 1153459, 1153457 }, 74 | { 2097152, 2307163, 2307161 }, 75 | { 4194304, 4613893, 4613891 }, 76 | { 8388608, 9227641, 9227639 }, 77 | { 16777216, 18455029, 18455027 }, 78 | { 33554432, 36911011, 36911009 }, 79 | { 67108864, 73819861, 73819859 }, 80 | { 134217728, 147639589, 147639587 }, 81 | { 268435456, 295279081, 295279079 }, 82 | { 536870912, 590559793, 590559791 }, 83 | { 1073741824, 1181116273, 1181116271}, 84 | { 2147483648ul, 2362232233ul, 2362232231ul} 85 | }; 86 | 87 | static int 88 | entry_is_free(const struct hash_entry *entry) 89 | { 90 | return entry->key == NULL; 91 | } 92 | 93 | static int 94 | entry_is_deleted(const struct hash_entry *entry) 95 | { 96 | return entry->key == deleted_key; 97 | } 98 | 99 | static int 100 | entry_is_present(const struct hash_entry *entry) 101 | { 102 | return entry->key != NULL && entry->key != deleted_key; 103 | } 104 | 105 | struct hash_table * 106 | hash_table_create(uint32_t (*hash_function)(const void *key), 107 | int (*key_equals_function)(const void *a, 108 | const void *b)) 109 | { 110 | struct hash_table *ht; 111 | 112 | ht = malloc(sizeof(*ht)); 113 | if (ht == NULL) 114 | return NULL; 115 | 116 | ht->size_index = 0; 117 | ht->size = hash_sizes[ht->size_index].size; 118 | ht->rehash = hash_sizes[ht->size_index].rehash; 119 | ht->max_entries = hash_sizes[ht->size_index].max_entries; 120 | ht->hash_function = hash_function; 121 | ht->key_equals_function = key_equals_function; 122 | ht->table = calloc(ht->size, sizeof(*ht->table)); 123 | ht->entries = 0; 124 | ht->deleted_entries = 0; 125 | 126 | if (ht->table == NULL) { 127 | free(ht); 128 | return NULL; 129 | } 130 | 131 | return ht; 132 | } 133 | 134 | /** 135 | * Frees the given hash table. 136 | * 137 | * If delete_function is passed, it gets called on each entry present before 138 | * freeing. 139 | */ 140 | void 141 | hash_table_destroy(struct hash_table *ht, 142 | void (*delete_function)(struct hash_entry *entry)) 143 | { 144 | if (!ht) 145 | return; 146 | 147 | if (delete_function) { 148 | struct hash_entry *entry; 149 | 150 | hash_table_foreach(ht, entry) { 151 | delete_function(entry); 152 | } 153 | } 154 | free(ht->table); 155 | free(ht); 156 | } 157 | 158 | /** 159 | * Finds a hash table entry with the given key. 160 | * 161 | * Returns NULL if no entry is found. Note that the data pointer may be 162 | * modified by the user. 163 | */ 164 | struct hash_entry * 165 | hash_table_search(struct hash_table *ht, const void *key) 166 | { 167 | uint32_t hash = ht->hash_function(key); 168 | 169 | return hash_table_search_pre_hashed(ht, hash, key); 170 | } 171 | 172 | /** 173 | * Finds a hash table entry with the given key and hash of that key. 174 | * 175 | * Returns NULL if no entry is found. Note that the data pointer may be 176 | * modified by the user. 177 | */ 178 | struct hash_entry * 179 | hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash, 180 | const void *key) 181 | { 182 | uint32_t start_hash_address = hash % ht->size; 183 | uint32_t hash_address = start_hash_address; 184 | 185 | do { 186 | uint32_t double_hash; 187 | 188 | struct hash_entry *entry = ht->table + hash_address; 189 | 190 | if (entry_is_free(entry)) { 191 | return NULL; 192 | } else if (entry_is_present(entry) && entry->hash == hash) { 193 | if (ht->key_equals_function(key, entry->key)) { 194 | return entry; 195 | } 196 | } 197 | 198 | double_hash = 1 + hash % ht->rehash; 199 | 200 | hash_address = (hash_address + double_hash) % ht->size; 201 | } while (hash_address != start_hash_address); 202 | 203 | return NULL; 204 | } 205 | 206 | static void 207 | hash_table_rehash(struct hash_table *ht, int new_size_index) 208 | { 209 | struct hash_table old_ht; 210 | struct hash_entry *table, *entry; 211 | 212 | if (new_size_index >= ARRAY_SIZE(hash_sizes)) 213 | return; 214 | 215 | table = calloc(hash_sizes[new_size_index].size, sizeof(*ht->table)); 216 | if (table == NULL) 217 | return; 218 | 219 | old_ht = *ht; 220 | 221 | ht->table = table; 222 | ht->size_index = new_size_index; 223 | ht->size = hash_sizes[ht->size_index].size; 224 | ht->rehash = hash_sizes[ht->size_index].rehash; 225 | ht->max_entries = hash_sizes[ht->size_index].max_entries; 226 | ht->entries = 0; 227 | ht->deleted_entries = 0; 228 | 229 | hash_table_foreach(&old_ht, entry) { 230 | hash_table_insert_pre_hashed(ht, entry->hash, 231 | entry->key, entry->data); 232 | } 233 | 234 | free(old_ht.table); 235 | } 236 | 237 | /** 238 | * Inserts the key into the table. 239 | * 240 | * Note that insertion may rearrange the table on a resize or rehash, 241 | * so previously found hash_entries are no longer valid after this function. 242 | */ 243 | struct hash_entry * 244 | hash_table_insert(struct hash_table *ht, const void *key, void *data) 245 | { 246 | uint32_t hash = ht->hash_function(key); 247 | 248 | /* Make sure nobody tries to add one of the magic values as a 249 | * key. If you need to do so, either do so in a wrapper, or 250 | * store keys with the magic values separately in the struct 251 | * hash_table. 252 | */ 253 | assert(key != NULL); 254 | 255 | return hash_table_insert_pre_hashed(ht, hash, key, data); 256 | } 257 | 258 | /** 259 | * Inserts the key with the given hash into the table. 260 | * 261 | * Note that insertion may rearrange the table on a resize or rehash, 262 | * so previously found hash_entries are no longer valid after this function. 263 | */ 264 | struct hash_entry * 265 | hash_table_insert_pre_hashed(struct hash_table *ht, uint32_t hash, 266 | const void *key, void *data) 267 | { 268 | uint32_t start_hash_address, hash_address; 269 | struct hash_entry *available_entry = NULL; 270 | 271 | if (ht->entries >= ht->max_entries) { 272 | hash_table_rehash(ht, ht->size_index + 1); 273 | } else if (ht->deleted_entries + ht->entries >= ht->max_entries) { 274 | hash_table_rehash(ht, ht->size_index); 275 | } 276 | 277 | start_hash_address = hash % ht->size; 278 | hash_address = start_hash_address; 279 | do { 280 | struct hash_entry *entry = ht->table + hash_address; 281 | uint32_t double_hash; 282 | 283 | if (!entry_is_present(entry)) { 284 | /* Stash the first available entry we find */ 285 | if (available_entry == NULL) 286 | available_entry = entry; 287 | if (entry_is_free(entry)) 288 | break; 289 | } 290 | 291 | /* Implement replacement when another insert happens 292 | * with a matching key. This is a relatively common 293 | * feature of hash tables, with the alternative 294 | * generally being "insert the new value as well, and 295 | * return it first when the key is searched for". 296 | * 297 | * Note that the hash table doesn't have a delete 298 | * callback. If freeing of old data pointers is 299 | * required to avoid memory leaks, perform a search 300 | * before inserting. 301 | */ 302 | if (!entry_is_deleted(entry) && 303 | entry->hash == hash && 304 | ht->key_equals_function(key, entry->key)) { 305 | entry->key = key; 306 | entry->data = data; 307 | return entry; 308 | } 309 | 310 | 311 | double_hash = 1 + hash % ht->rehash; 312 | 313 | hash_address = (hash_address + double_hash) % ht->size; 314 | } while (hash_address != start_hash_address); 315 | 316 | if (available_entry) { 317 | if (entry_is_deleted(available_entry)) 318 | ht->deleted_entries--; 319 | available_entry->hash = hash; 320 | available_entry->key = key; 321 | available_entry->data = data; 322 | ht->entries++; 323 | return available_entry; 324 | } 325 | 326 | /* We could hit here if a required resize failed. An unchecked-malloc 327 | * application could ignore this result. 328 | */ 329 | return NULL; 330 | } 331 | 332 | /** 333 | * This function searches for, and removes an entry from the hash table. 334 | * 335 | * If the caller has previously found a struct hash_entry pointer, 336 | * (from calling hash_table_search or remembering it from 337 | * hash_table_insert), then hash_table_remove_entry can be called 338 | * instead to avoid an extra search. 339 | */ 340 | void 341 | hash_table_remove(struct hash_table *ht, const void *key) 342 | { 343 | struct hash_entry *entry; 344 | 345 | entry = hash_table_search(ht, key); 346 | 347 | hash_table_remove_entry(ht, entry); 348 | } 349 | 350 | /** 351 | * This function deletes the given hash table entry. 352 | * 353 | * Note that deletion doesn't otherwise modify the table, so an iteration over 354 | * the table deleting entries is safe. 355 | */ 356 | void 357 | hash_table_remove_entry(struct hash_table *ht, struct hash_entry *entry) 358 | { 359 | if (!entry) 360 | return; 361 | 362 | entry->key = deleted_key; 363 | ht->entries--; 364 | ht->deleted_entries++; 365 | } 366 | 367 | /** 368 | * This function is an iterator over the hash table. 369 | * 370 | * Pass in NULL for the first entry, as in the start of a for loop. Note that 371 | * an iteration over the table is O(table_size) not O(entries). 372 | */ 373 | struct hash_entry * 374 | hash_table_next_entry(struct hash_table *ht, struct hash_entry *entry) 375 | { 376 | if (entry == NULL) 377 | entry = ht->table; 378 | else 379 | entry = entry + 1; 380 | 381 | for (; entry != ht->table + ht->size; entry++) { 382 | if (entry_is_present(entry)) { 383 | return entry; 384 | } 385 | } 386 | 387 | return NULL; 388 | } 389 | 390 | /** 391 | * Returns a random entry from the hash table. 392 | * 393 | * This may be useful in implementing random replacement (as opposed 394 | * to just removing everything) in caches based on this hash table 395 | * implementation. @predicate may be used to filter entries, or may 396 | * be set to NULL for no filtering. 397 | */ 398 | struct hash_entry * 399 | hash_table_random_entry(struct hash_table *ht, 400 | int (*predicate)(struct hash_entry *entry)) 401 | { 402 | struct hash_entry *entry; 403 | uint32_t i = random() % ht->size; 404 | 405 | if (ht->entries == 0) 406 | return NULL; 407 | 408 | for (entry = ht->table + i; entry != ht->table + ht->size; entry++) { 409 | if (entry_is_present(entry) && 410 | (!predicate || predicate(entry))) { 411 | return entry; 412 | } 413 | } 414 | 415 | for (entry = ht->table; entry != ht->table + i; entry++) { 416 | if (entry_is_present(entry) && 417 | (!predicate || predicate(entry))) { 418 | return entry; 419 | } 420 | } 421 | 422 | return NULL; 423 | } 424 | -------------------------------------------------------------------------------- /hash_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | * 26 | */ 27 | 28 | #ifndef HASH_TABLE_H 29 | #define HASH_TABLE_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | #include 36 | 37 | struct hash_entry { 38 | uint32_t hash; 39 | const void *key; 40 | void *data; 41 | }; 42 | 43 | struct hash_table { 44 | struct hash_entry *table; 45 | uint32_t (*hash_function)(const void *key); 46 | int (*key_equals_function)(const void *a, const void *b); 47 | uint32_t size; 48 | uint32_t rehash; 49 | uint32_t max_entries; 50 | uint32_t size_index; 51 | uint32_t entries; 52 | uint32_t deleted_entries; 53 | }; 54 | 55 | struct hash_table * 56 | hash_table_create(uint32_t (*hash_function)(const void *key), 57 | int (*key_equals_function)(const void *a, 58 | const void *b)); 59 | void 60 | hash_table_destroy(struct hash_table *ht, 61 | void (*delete_function)(struct hash_entry *entry)); 62 | 63 | struct hash_entry * 64 | hash_table_insert(struct hash_table *ht, const void *key, void *data); 65 | 66 | struct hash_entry * 67 | hash_table_search(struct hash_table *ht, const void *key); 68 | 69 | void 70 | hash_table_remove(struct hash_table *ht, const void *key); 71 | 72 | void 73 | hash_table_remove_entry(struct hash_table *ht, struct hash_entry *entry); 74 | 75 | struct hash_entry * 76 | hash_table_next_entry(struct hash_table *ht, 77 | struct hash_entry *entry); 78 | 79 | struct hash_entry * 80 | hash_table_random_entry(struct hash_table *ht, 81 | int (*predicate)(struct hash_entry *entry)); 82 | 83 | /** 84 | * This foreach function is safe against deletion (which just replaces 85 | * an entry's data with the deleted marker), but not against insertion 86 | * (which may rehash the table, making entry a dangling pointer). 87 | */ 88 | #define hash_table_foreach(ht, entry) \ 89 | for (entry = hash_table_next_entry(ht, NULL); \ 90 | entry != NULL; \ 91 | entry = hash_table_next_entry(ht, entry)) 92 | 93 | /* Alternate interfaces to reduce repeated calls to hash function. */ 94 | struct hash_entry * 95 | hash_table_search_pre_hashed(struct hash_table *ht, 96 | uint32_t hash, 97 | const void *key); 98 | 99 | struct hash_entry * 100 | hash_table_insert_pre_hashed(struct hash_table *ht, 101 | uint32_t hash, 102 | const void *key, void *data); 103 | 104 | 105 | #ifdef __cplusplus 106 | } /* extern C */ 107 | #endif 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /int-set.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009,2013 Intel Corporation 3 | * Copyright © 1988-2004 Keith Packard and Bart Massey. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | * 24 | * Except as contained in this notice, the names of the authors 25 | * or their institutions shall not be used in advertising or 26 | * otherwise to promote the sale, use or other dealings in this 27 | * Software without prior written authorization from the 28 | * authors. 29 | * 30 | * Authors: 31 | * Eric Anholt 32 | * Keith Packard 33 | * Carl Worth 34 | */ 35 | 36 | #include 37 | 38 | #include "int-set.h" 39 | 40 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 41 | 42 | /* 43 | * From Knuth -- a good choice for hash/rehash values is p, p-2 where 44 | * p and p-2 are both prime. These tables are sized to have an extra 10% 45 | * free to avoid exponential performance degradation as the hash table fills 46 | */ 47 | 48 | static const struct { 49 | uint32_t max_entries, size, rehash; 50 | } hash_sizes[] = { 51 | { 2, 5, 3 }, 52 | { 4, 7, 5 }, 53 | { 8, 13, 11 }, 54 | { 16, 19, 17 }, 55 | { 32, 43, 41 }, 56 | { 64, 73, 71 }, 57 | { 128, 151, 149 }, 58 | { 256, 283, 281 }, 59 | { 512, 571, 569 }, 60 | { 1024, 1153, 1151 }, 61 | { 2048, 2269, 2267 }, 62 | { 4096, 4519, 4517 }, 63 | { 8192, 9013, 9011 }, 64 | { 16384, 18043, 18041 }, 65 | { 32768, 36109, 36107 }, 66 | { 65536, 72091, 72089 }, 67 | { 131072, 144409, 144407 }, 68 | { 262144, 288361, 288359 }, 69 | { 524288, 576883, 576881 }, 70 | { 1048576, 1153459, 1153457 }, 71 | { 2097152, 2307163, 2307161 }, 72 | { 4194304, 4613893, 4613891 }, 73 | { 8388608, 9227641, 9227639 }, 74 | { 16777216, 18455029, 18455027 }, 75 | { 33554432, 36911011, 36911009 }, 76 | { 67108864, 73819861, 73819859 }, 77 | { 134217728, 147639589, 147639587 }, 78 | { 268435456, 295279081, 295279079 }, 79 | { 536870912, 590559793, 590559791 }, 80 | { 1073741824, 1181116273, 1181116271}, 81 | { 2147483648ul, 2362232233ul, 2362232231ul} 82 | }; 83 | 84 | static int 85 | entry_is_free(struct int_set_entry *entry) 86 | { 87 | return ! entry->occupied; 88 | } 89 | 90 | static int 91 | entry_is_deleted(struct int_set_entry *entry) 92 | { 93 | return entry->deleted; 94 | } 95 | 96 | static int 97 | entry_is_present(struct int_set_entry *entry) 98 | { 99 | return entry->occupied && ! entry->deleted; 100 | } 101 | 102 | struct int_set * 103 | int_set_create(void) 104 | { 105 | struct int_set *set; 106 | 107 | set = malloc(sizeof(*set)); 108 | if (set == NULL) 109 | return NULL; 110 | 111 | set->size_index = 0; 112 | set->size = hash_sizes[set->size_index].size; 113 | set->rehash = hash_sizes[set->size_index].rehash; 114 | set->max_entries = hash_sizes[set->size_index].max_entries; 115 | set->table = calloc(set->size, sizeof(*set->table)); 116 | set->entries = 0; 117 | set->deleted_entries = 0; 118 | 119 | if (set->table == NULL) { 120 | free(set); 121 | return NULL; 122 | } 123 | 124 | return set; 125 | } 126 | 127 | /** 128 | * Frees the given set. 129 | */ 130 | void 131 | int_set_destroy(struct int_set *set) 132 | { 133 | if (!set) 134 | return; 135 | 136 | free(set->table); 137 | free(set); 138 | } 139 | 140 | /* Does the set contain an entry with the given value. 141 | */ 142 | bool 143 | int_set_contains(struct int_set *set, uint32_t value) 144 | { 145 | struct int_set_entry *entry; 146 | 147 | entry = int_set_search(set, value); 148 | 149 | return entry != NULL; 150 | } 151 | 152 | /** 153 | * Finds a set entry with the given value 154 | * 155 | * Returns NULL if no entry is found. 156 | */ 157 | struct int_set_entry * 158 | int_set_search(struct int_set *set, uint32_t value) 159 | { 160 | uint32_t hash_address; 161 | 162 | hash_address = value % set->size; 163 | do { 164 | uint32_t double_hash; 165 | 166 | struct int_set_entry *entry = set->table + hash_address; 167 | 168 | if (entry_is_free(entry)) { 169 | return NULL; 170 | } else if (entry_is_present(entry) && entry->value == value) { 171 | return entry; 172 | } 173 | 174 | double_hash = 1 + value % set->rehash; 175 | 176 | hash_address = (hash_address + double_hash) % set->size; 177 | } while (hash_address != value % set->size); 178 | 179 | return NULL; 180 | } 181 | 182 | static void 183 | int_set_rehash(struct int_set *set, int new_size_index) 184 | { 185 | struct int_set old_set; 186 | struct int_set_entry *table, *entry; 187 | 188 | if (new_size_index >= ARRAY_SIZE(hash_sizes)) 189 | return; 190 | 191 | table = calloc(hash_sizes[new_size_index].size, sizeof(*set->table)); 192 | if (table == NULL) 193 | return; 194 | 195 | old_set = *set; 196 | 197 | set->table = table; 198 | set->size_index = new_size_index; 199 | set->size = hash_sizes[set->size_index].size; 200 | set->rehash = hash_sizes[set->size_index].rehash; 201 | set->max_entries = hash_sizes[set->size_index].max_entries; 202 | set->entries = 0; 203 | set->deleted_entries = 0; 204 | 205 | for (entry = old_set.table; 206 | entry != old_set.table + old_set.size; 207 | entry++) { 208 | if (entry_is_present(entry)) { 209 | int_set_add(set, entry->value); 210 | } 211 | } 212 | 213 | free(old_set.table); 214 | } 215 | 216 | /** 217 | * Inserts the given value into the set. 218 | * 219 | * Note that insertion may rearrange the table on a resize or rehash, 220 | * so previously found int_set_entry pointers are no longer valid 221 | * after this function. 222 | */ 223 | struct int_set_entry * 224 | int_set_add(struct int_set *set, uint32_t value) 225 | { 226 | uint32_t hash_address; 227 | struct int_set_entry *available_entry = NULL; 228 | 229 | if (set->entries >= set->max_entries) { 230 | int_set_rehash(set, set->size_index + 1); 231 | } else if (set->deleted_entries + set->entries >= set->max_entries) { 232 | int_set_rehash(set, set->size_index); 233 | } 234 | 235 | hash_address = value % set->size; 236 | do { 237 | struct int_set_entry *entry = set->table + hash_address; 238 | uint32_t double_hash; 239 | 240 | if (!entry_is_present(entry)) { 241 | if (available_entry == NULL) 242 | available_entry = entry; 243 | if (entry_is_free(entry)) 244 | break; 245 | if (entry_is_deleted(entry)) { 246 | set->deleted_entries--; 247 | entry->deleted = 0; 248 | } 249 | } 250 | 251 | if (entry->value == value) { 252 | return entry; 253 | } 254 | 255 | double_hash = 1 + value % set->rehash; 256 | 257 | hash_address = (hash_address + double_hash) % set->size; 258 | } while (hash_address != value % set->size); 259 | 260 | if (available_entry) { 261 | available_entry->value = value; 262 | available_entry->occupied = 1; 263 | set->entries++; 264 | return available_entry; 265 | } 266 | 267 | /* We could hit here if a required resize failed. An unchecked-malloc 268 | * application could ignore this result. 269 | */ 270 | return NULL; 271 | } 272 | 273 | /** 274 | * This function searches for, and removes an entry from the set. 275 | * 276 | * If the caller has previously found a struct int_set_entry pointer, 277 | * (from calling int_set_search or remembering it from int_set_add), 278 | * then int_set_remove_entry can be called instead to avoid an extra 279 | * search. 280 | */ 281 | void 282 | int_set_remove(struct int_set *set, uint32_t value) 283 | { 284 | struct int_set_entry *entry; 285 | 286 | entry = int_set_search(set, value); 287 | 288 | int_set_remove_entry(set, entry); 289 | } 290 | 291 | /** 292 | * This function deletes the given set entry. 293 | * 294 | * Note that deletion doesn't otherwise modify the table, so an iteration over 295 | * the table deleting entries is safe. 296 | */ 297 | void 298 | int_set_remove_entry(struct int_set *set, struct int_set_entry *entry) 299 | { 300 | if (!entry) 301 | return; 302 | 303 | entry->deleted = 1; 304 | set->entries--; 305 | set->deleted_entries++; 306 | } 307 | 308 | /** 309 | * This function is an iterator over the set. 310 | * 311 | * Pass in NULL for the first entry, as in the start of a for loop. Note that 312 | * an iteration over the table is O(table_size) not O(entries). 313 | */ 314 | struct int_set_entry * 315 | int_set_next_entry(struct int_set *set, struct int_set_entry *entry) 316 | { 317 | if (entry == NULL) 318 | entry = set->table; 319 | else 320 | entry = entry + 1; 321 | 322 | for (; entry != set->table + set->size; entry++) { 323 | if (entry_is_present(entry)) { 324 | return entry; 325 | } 326 | } 327 | 328 | return NULL; 329 | } 330 | 331 | struct int_set_entry * 332 | int_set_random_entry(struct int_set *set, 333 | int (*predicate)(struct int_set_entry *entry)) 334 | { 335 | struct int_set_entry *entry; 336 | uint32_t i = random() % set->size; 337 | 338 | if (set->entries == 0) 339 | return NULL; 340 | 341 | for (entry = set->table + i; entry != set->table + set->size; entry++) { 342 | if (entry_is_present(entry) && 343 | (!predicate || predicate(entry))) { 344 | return entry; 345 | } 346 | } 347 | 348 | for (entry = set->table; entry != set->table + i; entry++) { 349 | if (entry_is_present(entry) && 350 | (!predicate || predicate(entry))) { 351 | return entry; 352 | } 353 | } 354 | 355 | return NULL; 356 | } 357 | -------------------------------------------------------------------------------- /int-set.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009,2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | * 26 | */ 27 | 28 | #ifndef SET_H 29 | #define SET_H 30 | 31 | #include 32 | #include 33 | 34 | struct int_set_entry { 35 | uint32_t value; 36 | unsigned int occupied : 1; 37 | unsigned int deleted : 1; 38 | }; 39 | 40 | struct int_set { 41 | struct int_set_entry *table; 42 | uint32_t size; 43 | uint32_t rehash; 44 | uint32_t max_entries; 45 | uint32_t size_index; 46 | uint32_t entries; 47 | uint32_t deleted_entries; 48 | }; 49 | 50 | struct int_set * 51 | int_set_create(void); 52 | 53 | void 54 | int_set_destroy(struct int_set *set); 55 | 56 | struct int_set_entry * 57 | int_set_add(struct int_set *set, uint32_t value); 58 | 59 | bool 60 | int_set_contains(struct int_set *set, uint32_t value); 61 | 62 | void 63 | int_set_remove(struct int_set *set, uint32_t value); 64 | 65 | struct int_set_entry * 66 | int_set_search(struct int_set *set, uint32_t value); 67 | 68 | void 69 | int_set_remove_entry(struct int_set *set, struct int_set_entry *entry); 70 | 71 | struct int_set_entry * 72 | int_set_next_entry(struct int_set *set, struct int_set_entry *entry); 73 | 74 | /* Return a random entry in the set that satisfies predicate. 75 | * 76 | * The 'predicate' function pointer may be NULL in which any random 77 | * entry will be returned. */ 78 | struct int_set_entry * 79 | int_set_random_entry(struct int_set *set, 80 | int (*predicate)(struct int_set_entry *entry)); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # Copyright © 2017 Broadcom 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | 22 | project( 23 | 'hash_table', 24 | 'c', 25 | version : '1.0', 26 | license : 'MIT', 27 | ) 28 | 29 | libhash_table = shared_library( 30 | 'hash_table', 31 | [ 32 | 'hash_table.c', 33 | 'fnv_hash.c', 34 | ], 35 | install: true, 36 | ) 37 | 38 | libset = shared_library( 39 | 'set', 40 | [ 41 | 'set.c', 42 | 'fnv_hash.c', 43 | ], 44 | install: true, 45 | ) 46 | 47 | libhash_table_dep = declare_dependency( 48 | include_directories: include_directories('.'), 49 | link_with: libhash_table, 50 | ) 51 | 52 | libset_dep = declare_dependency( 53 | include_directories: include_directories('.'), 54 | link_with: libset, 55 | ) 56 | 57 | hash_tests = [ 58 | 'collision', 59 | 'collision_replacement', 60 | 'delete_and_lookup', 61 | 'delete_management', 62 | 'deleted_key', 63 | 'destroy_callback', 64 | 'insert_and_lookup', 65 | 'insert_many', 66 | 'null_destroy', 67 | 'random_entry', 68 | 'remove_null', 69 | 'replacement', 70 | ] 71 | 72 | foreach t: hash_tests 73 | test( 74 | 'hash_table-' + t, 75 | executable( 76 | 'hash_table-' + t + '-prog', 77 | join_paths('tests', t + '.c'), 78 | link_with: libhash_table 79 | ) 80 | ) 81 | endforeach 82 | 83 | set_tests = [ 84 | 'collision_replacement', 85 | 'delete_and_lookup', 86 | 'delete_management', 87 | 'deleted_key', 88 | 'destroy_callback', 89 | 'insert_and_lookup', 90 | 'insert_many', 91 | 'null_destroy', 92 | 'null_remove', 93 | 'random_entry', 94 | 'replacement', 95 | ] 96 | 97 | foreach t: set_tests 98 | test( 99 | 'set-' + t, 100 | executable( 101 | 'set-' + t + '-prog', 102 | join_paths('tests', 'set', t + '.c'), 103 | link_with: libset 104 | ) 105 | ) 106 | endforeach 107 | -------------------------------------------------------------------------------- /set.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 1988-2004 Keith Packard and Bart Massey. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | * 24 | * Except as contained in this notice, the names of the authors 25 | * or their institutions shall not be used in advertising or 26 | * otherwise to promote the sale, use or other dealings in this 27 | * Software without prior written authorization from the 28 | * authors. 29 | * 30 | * Authors: 31 | * Eric Anholt 32 | * Keith Packard 33 | */ 34 | 35 | #include 36 | #include 37 | 38 | #include "set.h" 39 | 40 | #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 41 | 42 | /* 43 | * From Knuth -- a good choice for hash/rehash values is p, p-2 where 44 | * p and p-2 are both prime. These tables are sized to have an extra 10% 45 | * free to avoid exponential performance degradation as the hash table fills 46 | */ 47 | 48 | static const uint32_t deleted_key_value; 49 | static const void *deleted_key = &deleted_key_value; 50 | 51 | static const struct { 52 | uint32_t max_entries, size, rehash; 53 | } hash_sizes[] = { 54 | { 2, 5, 3 }, 55 | { 4, 7, 5 }, 56 | { 8, 13, 11 }, 57 | { 16, 19, 17 }, 58 | { 32, 43, 41 }, 59 | { 64, 73, 71 }, 60 | { 128, 151, 149 }, 61 | { 256, 283, 281 }, 62 | { 512, 571, 569 }, 63 | { 1024, 1153, 1151 }, 64 | { 2048, 2269, 2267 }, 65 | { 4096, 4519, 4517 }, 66 | { 8192, 9013, 9011 }, 67 | { 16384, 18043, 18041 }, 68 | { 32768, 36109, 36107 }, 69 | { 65536, 72091, 72089 }, 70 | { 131072, 144409, 144407 }, 71 | { 262144, 288361, 288359 }, 72 | { 524288, 576883, 576881 }, 73 | { 1048576, 1153459, 1153457 }, 74 | { 2097152, 2307163, 2307161 }, 75 | { 4194304, 4613893, 4613891 }, 76 | { 8388608, 9227641, 9227639 }, 77 | { 16777216, 18455029, 18455027 }, 78 | { 33554432, 36911011, 36911009 }, 79 | { 67108864, 73819861, 73819859 }, 80 | { 134217728, 147639589, 147639587 }, 81 | { 268435456, 295279081, 295279079 }, 82 | { 536870912, 590559793, 590559791 }, 83 | { 1073741824, 1181116273, 1181116271}, 84 | { 2147483648ul, 2362232233ul, 2362232231ul} 85 | }; 86 | 87 | static int 88 | entry_is_free(const struct set_entry *entry) 89 | { 90 | return entry->key == NULL; 91 | } 92 | 93 | static int 94 | entry_is_deleted(const struct set_entry *entry) 95 | { 96 | return entry->key == deleted_key; 97 | } 98 | 99 | static int 100 | entry_is_present(const struct set_entry *entry) 101 | { 102 | return entry->key != NULL && entry->key != deleted_key; 103 | } 104 | 105 | struct set * 106 | set_create(uint32_t (*hash_function)(const void *key), 107 | int key_equals_function(const void *a, 108 | const void *b)) 109 | { 110 | struct set *set; 111 | 112 | set = malloc(sizeof(*set)); 113 | if (set == NULL) 114 | return NULL; 115 | 116 | set->size_index = 0; 117 | set->size = hash_sizes[set->size_index].size; 118 | set->rehash = hash_sizes[set->size_index].rehash; 119 | set->max_entries = hash_sizes[set->size_index].max_entries; 120 | set->hash_function = hash_function; 121 | set->key_equals_function = key_equals_function; 122 | set->table = calloc(set->size, sizeof(*set->table)); 123 | set->entries = 0; 124 | set->deleted_entries = 0; 125 | 126 | if (set->table == NULL) { 127 | free(set); 128 | return NULL; 129 | } 130 | 131 | return set; 132 | } 133 | 134 | /** 135 | * Frees the given set. 136 | * 137 | * If delete_function is passed, it gets called on each entry present before 138 | * freeing. 139 | */ 140 | void 141 | set_destroy(struct set *set, void (*delete_function)(struct set_entry *entry)) 142 | { 143 | if (!set) 144 | return; 145 | 146 | if (delete_function) { 147 | struct set_entry *entry; 148 | 149 | set_foreach(set, entry) { 150 | delete_function(entry); 151 | } 152 | } 153 | free(set->table); 154 | free(set); 155 | } 156 | 157 | /* Does the set contain an entry with the given key. 158 | */ 159 | bool 160 | set_contains(struct set *set, const void *key) 161 | { 162 | struct set_entry *entry; 163 | 164 | entry = set_search(set, key); 165 | 166 | return entry != NULL; 167 | } 168 | 169 | /** 170 | * Finds a set entry with the given key. 171 | * 172 | * Returns NULL if no entry is found. 173 | */ 174 | struct set_entry * 175 | set_search(struct set *set, const void *key) 176 | { 177 | uint32_t hash = set->hash_function(key); 178 | 179 | return set_search_pre_hashed (set, hash, key); 180 | } 181 | 182 | /** 183 | * Finds a set entry with the given key and hash of that key. 184 | * 185 | * Returns NULL if no entry is found. 186 | */ 187 | struct set_entry * 188 | set_search_pre_hashed(struct set *set, uint32_t hash, const void *key) 189 | { 190 | uint32_t hash_address; 191 | 192 | hash_address = hash % set->size; 193 | do { 194 | uint32_t double_hash; 195 | 196 | struct set_entry *entry = set->table + hash_address; 197 | 198 | if (entry_is_free(entry)) { 199 | return NULL; 200 | } else if (entry_is_present(entry) && entry->hash == hash) { 201 | if (set->key_equals_function(key, entry->key)) { 202 | return entry; 203 | } 204 | } 205 | 206 | double_hash = 1 + hash % set->rehash; 207 | 208 | hash_address = (hash_address + double_hash) % set->size; 209 | } while (hash_address != hash % set->size); 210 | 211 | return NULL; 212 | } 213 | 214 | static void 215 | set_rehash(struct set *set, int new_size_index) 216 | { 217 | struct set old_set; 218 | struct set_entry *table, *entry; 219 | 220 | if (new_size_index >= ARRAY_SIZE(hash_sizes)) 221 | return; 222 | 223 | table = calloc(hash_sizes[new_size_index].size, sizeof(*set->table)); 224 | if (table == NULL) 225 | return; 226 | 227 | old_set = *set; 228 | 229 | set->table = table; 230 | set->size_index = new_size_index; 231 | set->size = hash_sizes[set->size_index].size; 232 | set->rehash = hash_sizes[set->size_index].rehash; 233 | set->max_entries = hash_sizes[set->size_index].max_entries; 234 | set->entries = 0; 235 | set->deleted_entries = 0; 236 | 237 | set_foreach(&old_set, entry) { 238 | set_add_pre_hashed(set, entry->hash, entry->key); 239 | } 240 | 241 | free(old_set.table); 242 | } 243 | 244 | /** 245 | * Inserts the key into the set. 246 | * 247 | * Note that insertion may rearrange the set on a resize or rehash, so 248 | * previously found set_entry pointers are no longer valid after this 249 | * function. 250 | */ 251 | struct set_entry * 252 | set_add(struct set *set, const void *key) 253 | { 254 | uint32_t hash = set->hash_function(key); 255 | 256 | /* Make sure nobody tries to add one of the magic values as a 257 | * key. If you need to do so, either do so in a wrapper, or 258 | * store keys with the magic values separately in the struct 259 | * set. 260 | */ 261 | assert(key != NULL); 262 | 263 | return set_add_pre_hashed(set, hash, key); 264 | } 265 | 266 | /** 267 | * Inserts the key with the given hash into the set. 268 | * 269 | * Note that insertion may rearrange the set on a resize or rehash, so 270 | * previously found set_entry pointers are no longer valid after this 271 | * function. 272 | */ 273 | struct set_entry * 274 | set_add_pre_hashed(struct set *set, uint32_t hash, const void *key) 275 | { 276 | uint32_t hash_address; 277 | struct set_entry *available_entry = NULL; 278 | 279 | if (set->entries >= set->max_entries) { 280 | set_rehash(set, set->size_index + 1); 281 | } else if (set->deleted_entries + set->entries >= set->max_entries) { 282 | set_rehash(set, set->size_index); 283 | } 284 | 285 | hash_address = hash % set->size; 286 | do { 287 | struct set_entry *entry = set->table + hash_address; 288 | uint32_t double_hash; 289 | 290 | if (!entry_is_present(entry)) { 291 | /* Stash the first available entry we find */ 292 | if (available_entry == NULL) 293 | available_entry = entry; 294 | if (entry_is_free(entry)) 295 | break; 296 | } 297 | 298 | /* Implement replacement when another insert happens 299 | * with a matching key. This is a relatively common 300 | * feature of hash tables, with the alternative 301 | * generally being "insert the new value as well, and 302 | * return it first when the key is searched for". 303 | * 304 | * Note that the set doesn't have a delete callback. 305 | * If freeing of old keys is required to avoid memory leaks, 306 | * perform a search before inserting. 307 | */ 308 | if (!entry_is_deleted(entry) && 309 | entry->hash == hash && 310 | set->key_equals_function(key, entry->key)) { 311 | entry->key = key; 312 | return entry; 313 | } 314 | 315 | double_hash = 1 + hash % set->rehash; 316 | 317 | hash_address = (hash_address + double_hash) % set->size; 318 | } while (hash_address != hash % set->size); 319 | 320 | if (available_entry) { 321 | if (entry_is_deleted(available_entry)) 322 | set->deleted_entries--; 323 | available_entry->hash = hash; 324 | available_entry->key = key; 325 | set->entries++; 326 | return available_entry; 327 | } 328 | 329 | /* We could hit here if a required resize failed. An unchecked-malloc 330 | * application could ignore this result. 331 | */ 332 | return NULL; 333 | } 334 | 335 | /** 336 | * This function searches for, and removes an entry from the set. 337 | * 338 | * If the caller has previously found a struct set_entry pointer, 339 | * (from calling set_search or remembering it from set_add), then 340 | * set_remove_entry can be called instead to avoid an extra search. 341 | */ 342 | void 343 | set_remove(struct set *set, const void *key) 344 | { 345 | struct set_entry *entry; 346 | 347 | entry = set_search(set, key); 348 | 349 | set_remove_entry(set, entry); 350 | } 351 | 352 | /** 353 | * This function deletes the set given set entry. 354 | * 355 | * Note that deletion doesn't otherwise modify the set, so an 356 | * iteration over the set deleting entries is safe. 357 | */ 358 | void 359 | set_remove_entry(struct set *set, struct set_entry *entry) 360 | { 361 | if (!entry) 362 | return; 363 | 364 | entry->key = deleted_key; 365 | set->entries--; 366 | set->deleted_entries++; 367 | } 368 | 369 | /** 370 | * This function is an iterator over the set. 371 | * 372 | * Pass in NULL for the first entry, as in the start of a for loop. 373 | * Note that an iteration over the set is O(table_size) not 374 | * O(entries). 375 | */ 376 | struct set_entry * 377 | set_next_entry(struct set *set, struct set_entry *entry) 378 | { 379 | if (entry == NULL) 380 | entry = set->table; 381 | else 382 | entry = entry + 1; 383 | 384 | for (; entry != set->table + set->size; entry++) { 385 | if (entry_is_present(entry)) { 386 | return entry; 387 | } 388 | } 389 | 390 | return NULL; 391 | } 392 | 393 | struct set_entry * 394 | set_random_entry(struct set *set, 395 | int (*predicate)(struct set_entry *entry)) 396 | { 397 | struct set_entry *entry; 398 | uint32_t i = random() % set->size; 399 | 400 | if (set->entries == 0) 401 | return NULL; 402 | 403 | for (entry = set->table + i; entry != set->table + set->size; entry++) { 404 | if (entry_is_present(entry) && 405 | (!predicate || predicate(entry))) { 406 | return entry; 407 | } 408 | } 409 | 410 | for (entry = set->table; entry != set->table + i; entry++) { 411 | if (entry_is_present(entry) && 412 | (!predicate || predicate(entry))) { 413 | return entry; 414 | } 415 | } 416 | 417 | return NULL; 418 | } 419 | -------------------------------------------------------------------------------- /set.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | * 26 | */ 27 | 28 | #ifndef SET_H 29 | #define SET_H 30 | 31 | #include 32 | #include 33 | 34 | struct set_entry { 35 | uint32_t hash; 36 | const void *key; 37 | }; 38 | 39 | struct set { 40 | struct set_entry *table; 41 | uint32_t (*hash_function)(const void *key); 42 | int (*key_equals_function)(const void *a, const void *b); 43 | uint32_t size; 44 | uint32_t rehash; 45 | uint32_t max_entries; 46 | uint32_t size_index; 47 | uint32_t entries; 48 | uint32_t deleted_entries; 49 | }; 50 | 51 | struct set * 52 | set_create(uint32_t (*hash_function)(const void *key), 53 | int (*key_equals_function)(const void *a, 54 | const void *b)); 55 | void 56 | set_destroy(struct set *set, 57 | void (*delete_function)(struct set_entry *entry)); 58 | 59 | struct set_entry * 60 | set_add(struct set *set, const void *key); 61 | 62 | bool 63 | set_contains(struct set *set, const void *key); 64 | 65 | void 66 | set_remove(struct set *set, const void *key); 67 | 68 | struct set_entry * 69 | set_search(struct set *set, const void *key); 70 | 71 | void 72 | set_remove_entry(struct set *set, struct set_entry *entry); 73 | 74 | struct set_entry * 75 | set_next_entry(struct set *set, struct set_entry *entry); 76 | 77 | struct set_entry * 78 | set_random_entry(struct set *set, 79 | int (*predicate)(struct set_entry *entry)); 80 | 81 | /** 82 | * This foreach function is safe against deletion (which just replaces 83 | * an entry's data with the deleted marker), but not against insertion 84 | * (which may rehash the table, making entry a dangling pointer). 85 | */ 86 | #define set_foreach(ht, entry) \ 87 | for (entry = set_next_entry(ht, NULL); \ 88 | entry != NULL; \ 89 | entry = set_next_entry(ht, entry)) 90 | 91 | /* Alternate interfaces to reduce repeated calls to hash function. */ 92 | struct set_entry * 93 | set_search_pre_hashed(struct set *set, uint32_t hash, const void *key); 94 | 95 | struct set_entry * 96 | set_add_pre_hashed(struct set *set, uint32_t hash, const void *key); 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.trs 3 | collision 4 | collision_replacement 5 | delete_and_lookup 6 | delete_management 7 | deleted_key 8 | destroy_callback 9 | insert_and_lookup 10 | insert_many 11 | null_destroy 12 | random_entry 13 | remove_null 14 | replacement 15 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright © 2009 Intel Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | 22 | SUBDIRS = set int-set 23 | 24 | AM_CFLAGS = $(WARN_CFLAGS) -I$(top_srcdir) 25 | LDADD = ../libhash_table.la 26 | 27 | TESTS = \ 28 | collision \ 29 | collision_replacement \ 30 | delete_and_lookup \ 31 | delete_management \ 32 | deleted_key \ 33 | destroy_callback \ 34 | insert_and_lookup \ 35 | insert_many \ 36 | null_destroy \ 37 | random_entry \ 38 | remove_null \ 39 | replacement \ 40 | $() 41 | 42 | EXTRA_PROGRAMS = $(TESTS) 43 | -------------------------------------------------------------------------------- /tests/collision.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct hash_table *ht; 38 | const char *str1 = "test1"; 39 | const char *str2 = "test2"; 40 | struct hash_entry *entry1, *entry2; 41 | uint32_t bad_hash = 5; 42 | int i; 43 | 44 | ht = hash_table_create_for_string(); 45 | 46 | /* Add #1 and verify search. */ 47 | hash_table_insert_pre_hashed(ht, bad_hash, str1, NULL); 48 | 49 | entry1 = hash_table_search_pre_hashed(ht, bad_hash, str1); 50 | assert(entry1->key == str1); 51 | 52 | /* Add #2 and verify search. */ 53 | hash_table_insert_pre_hashed(ht, bad_hash, str2, NULL); 54 | 55 | entry2 = hash_table_search_pre_hashed(ht, bad_hash, str2); 56 | assert(entry2->key == str2); 57 | 58 | /* Check that we can still find #1 after inserting #2 */ 59 | entry1 = hash_table_search_pre_hashed(ht, bad_hash, str1); 60 | assert(entry1->key == str1); 61 | 62 | /* Remove the collided entry and look again. */ 63 | hash_table_remove_entry(ht, entry1); 64 | entry2 = hash_table_search_pre_hashed(ht, bad_hash, str2); 65 | assert(entry2->key == str2); 66 | 67 | /* Put str1 back, then spam junk into the table to force a 68 | * resize and make sure we can still find them both. 69 | */ 70 | hash_table_insert_pre_hashed(ht, bad_hash, str1, NULL); 71 | for (i = 0; i < 100; i++) { 72 | char *key = malloc(10); 73 | sprintf(key, "spam%d", i); 74 | hash_table_insert(ht, key, NULL); 75 | } 76 | entry1 = hash_table_search_pre_hashed(ht, bad_hash, str1); 77 | assert(entry1->key == str1); 78 | entry2 = hash_table_search_pre_hashed(ht, bad_hash, str2); 79 | assert(entry2->key == str2); 80 | 81 | hash_table_destroy(ht, NULL); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tests/collision_replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 2016 Broadcom Limited 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "hash_table.h" 30 | #include "fnv_hash.h" 31 | 32 | /* Return collisions, so we can test the deletion behavior for chained 33 | * objects. 34 | */ 35 | static uint32_t 36 | badhash(const void *key) 37 | { 38 | return 1; 39 | } 40 | 41 | int 42 | main(int argc, char **argv) 43 | { 44 | struct hash_table *ht; 45 | const char *str1 = "test1"; 46 | const char *str2 = "test2"; 47 | uint8_t data = 0; 48 | struct hash_entry *entry; 49 | 50 | ht = hash_table_create(badhash, string_key_equals); 51 | 52 | hash_table_insert(ht, str1, NULL); 53 | hash_table_insert(ht, str2, NULL); 54 | hash_table_remove(ht, str1); 55 | hash_table_insert(ht, str2, &data); 56 | 57 | /* Make sure that we actually replaced our str2's data, even 58 | * though it was chained off of str1. 59 | */ 60 | entry = hash_table_search(ht, str2); 61 | assert(entry->data == &data); 62 | 63 | /* Make sure that if we remove str2, it wasn't just occupying 64 | * str1's old slot with the old str2 still present. 65 | */ 66 | hash_table_remove(ht, str2); 67 | entry = hash_table_search(ht, str2); 68 | assert(entry == NULL); 69 | 70 | hash_table_destroy(ht, NULL); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /tests/delete_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | /* Return collisions, so we can test the deletion behavior for chained 35 | * objects. 36 | */ 37 | static uint32_t 38 | badhash(const void *key) 39 | { 40 | return 1; 41 | } 42 | 43 | int 44 | main(int argc, char **argv) 45 | { 46 | struct hash_table *ht; 47 | const char *str1 = "test1"; 48 | const char *str2 = "test2"; 49 | const char *str3 = "test3"; 50 | uint32_t hash_str1 = badhash(str1); 51 | uint32_t hash_str2 = badhash(str2); 52 | struct hash_entry *entry; 53 | 54 | ht = hash_table_create(badhash, string_key_equals); 55 | 56 | hash_table_insert_pre_hashed(ht, hash_str1, str1, NULL); 57 | hash_table_insert_pre_hashed(ht, hash_str2, str2, NULL); 58 | hash_table_insert(ht, str3, NULL); 59 | 60 | entry = hash_table_search(ht, str3); 61 | assert(strcmp(entry->key, str3) == 0); 62 | 63 | entry = hash_table_search_pre_hashed(ht, hash_str2, str2); 64 | assert(strcmp(entry->key, str2) == 0); 65 | 66 | entry = hash_table_search_pre_hashed(ht, hash_str1, str1); 67 | assert(strcmp(entry->key, str1) == 0); 68 | 69 | hash_table_remove_entry(ht, entry); 70 | hash_table_remove(ht, str2); 71 | 72 | entry = hash_table_search_pre_hashed(ht, hash_str1, str1); 73 | assert(entry == NULL); 74 | 75 | entry = hash_table_search(ht, str2); 76 | assert(entry == NULL); 77 | 78 | entry = hash_table_search(ht, str3); 79 | assert(strcmp(entry->key, str3) == 0); 80 | 81 | hash_table_destroy(ht, NULL); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tests/delete_management.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | 33 | /* Also doubles as hash function. */ 34 | static uint32_t 35 | key_value(const void *key) 36 | { 37 | return *(const uint32_t *)key; 38 | } 39 | 40 | static int 41 | uint32_t_key_equals(const void *a, const void *b) 42 | { 43 | return key_value(a) == key_value(b); 44 | } 45 | 46 | int 47 | main(int argc, char **argv) 48 | { 49 | struct hash_table *ht; 50 | struct hash_entry *entry; 51 | int size = 10000; 52 | uint32_t keys[size]; 53 | uint32_t i; 54 | 55 | ht = hash_table_create(key_value, uint32_t_key_equals); 56 | 57 | for (i = 0; i < size; i++) { 58 | keys[i] = i; 59 | 60 | hash_table_insert_pre_hashed(ht, i, keys + i, NULL); 61 | 62 | if (i >= 100) { 63 | uint32_t delete_value = i - 100; 64 | hash_table_remove(ht, &delete_value); 65 | } 66 | } 67 | 68 | /* Make sure that all our entries were present at the end. */ 69 | for (i = size - 100; i < size; i++) { 70 | entry = hash_table_search(ht, keys + i); 71 | assert(entry); 72 | assert(key_value(entry->key) == i); 73 | } 74 | 75 | /* Make sure that no extra entries got in */ 76 | for (entry = hash_table_next_entry(ht, NULL); 77 | entry != NULL; 78 | entry = hash_table_next_entry(ht, entry)) { 79 | assert(key_value(entry->key) >= size - 100 && 80 | key_value(entry->key) < size); 81 | } 82 | assert(ht->entries == 100); 83 | 84 | hash_table_destroy(ht, NULL); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /tests/deleted_key.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Broadcom Limited 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "hash_table.h" 30 | #include "fnv_hash.h" 31 | 32 | static bool deleted = false; 33 | 34 | static int 35 | key_equals(const void *a, const void *b) 36 | { 37 | /* The comparison function shouldn't be called if our entry had 38 | * been deleted. 39 | */ 40 | assert(!deleted); 41 | 42 | return strcmp(a, b) == 0; 43 | } 44 | 45 | int 46 | main(int argc, char **argv) 47 | { 48 | struct hash_table *ht; 49 | const char *str = "test1"; 50 | struct hash_entry *entry; 51 | 52 | ht = hash_table_create((uint32_t (*)(const void *key))fnv1_hash_string, 53 | key_equals); 54 | 55 | hash_table_insert(ht, str, NULL); 56 | hash_table_remove(ht, str); 57 | deleted = true; 58 | hash_table_insert(ht, str, NULL); 59 | assert(!entry); 60 | 61 | hash_table_destroy(ht, NULL); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /tests/destroy_callback.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | static const char *str1 = "test1"; 35 | static const char *str2 = "test2"; 36 | static int delete_str1 = 0; 37 | static int delete_str2 = 0; 38 | 39 | static void 40 | delete_callback(struct hash_entry *entry) 41 | { 42 | if (strcmp(entry->key, str1) == 0) 43 | delete_str1 = 1; 44 | else if (strcmp(entry->key, str2) == 0) 45 | delete_str2 = 1; 46 | else 47 | abort(); 48 | } 49 | 50 | int 51 | main(int argc, char **argv) 52 | { 53 | struct hash_table *ht; 54 | uint32_t hash_str1 = fnv1_hash_string(str1); 55 | 56 | ht = hash_table_create_for_string(); 57 | 58 | hash_table_insert_pre_hashed(ht, hash_str1, str1, NULL); 59 | hash_table_insert(ht, str2, NULL); 60 | 61 | hash_table_destroy(ht, delete_callback); 62 | 63 | assert(delete_str1 && delete_str2); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tests/insert_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct hash_table *ht; 38 | const char *str1 = "test1"; 39 | const char *str2 = "test2"; 40 | uint32_t hash_str1 = fnv1_hash_string(str1); 41 | struct hash_entry *entry; 42 | 43 | ht = hash_table_create_for_string(); 44 | 45 | hash_table_insert_pre_hashed(ht, hash_str1, str1, NULL); 46 | hash_table_insert(ht, str2, NULL); 47 | 48 | entry = hash_table_search_pre_hashed(ht, hash_str1, str1); 49 | assert(strcmp(entry->key, str1) == 0); 50 | 51 | entry = hash_table_search(ht, str2); 52 | assert(strcmp(entry->key, str2) == 0); 53 | 54 | hash_table_destroy(ht, NULL); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /tests/insert_many.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | 33 | /* Also doubles as hash function. */ 34 | static uint32_t 35 | key_value(const void *key) 36 | { 37 | return *(const uint32_t *)key; 38 | } 39 | 40 | static int 41 | uint32_t_key_equals(const void *a, const void *b) 42 | { 43 | return key_value(a) == key_value(b); 44 | } 45 | 46 | int 47 | main(int argc, char **argv) 48 | { 49 | struct hash_table *ht; 50 | struct hash_entry *entry; 51 | int size = 10000; 52 | uint32_t keys[size]; 53 | uint32_t i; 54 | 55 | ht = hash_table_create(key_value, uint32_t_key_equals); 56 | 57 | for (i = 0; i < size; i++) { 58 | keys[i] = i; 59 | 60 | hash_table_insert(ht, keys + i, NULL); 61 | } 62 | 63 | for (i = 0; i < size; i++) { 64 | entry = hash_table_search_pre_hashed(ht, i, keys + i); 65 | assert(entry); 66 | assert(key_value(entry->key) == i); 67 | } 68 | assert(ht->entries == size); 69 | 70 | hash_table_destroy(ht, NULL); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /tests/int-set/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.trs 3 | collision_replacement 4 | delete_and_lookup 5 | delete_management 6 | destroy_callback 7 | insert_and_lookup 8 | insert_many 9 | null_destroy 10 | null_remove 11 | random_entry 12 | replace_deleted 13 | replacement 14 | -------------------------------------------------------------------------------- /tests/int-set/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright © 2009 Intel Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | 22 | AM_CFLAGS = $(WARN_CFLAGS) -I$(top_srcdir) 23 | LDADD = ../../libint-set.la 24 | 25 | TESTS = \ 26 | collision_replacement \ 27 | delete_and_lookup \ 28 | delete_management \ 29 | insert_and_lookup \ 30 | insert_many \ 31 | null_destroy \ 32 | null_remove \ 33 | random_entry \ 34 | replace_deleted \ 35 | replacement \ 36 | $() 37 | 38 | EXTRA_PROGRAMS = $(TESTS) 39 | -------------------------------------------------------------------------------- /tests/int-set/collision_replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 2016 Broadcom Limited 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "int-set.h" 30 | #include "fnv_hash.h" 31 | 32 | int 33 | main(int argc, char **argv) 34 | { 35 | struct int_set *set = int_set_create(); 36 | 37 | /* Unlike the hash table equivalent of this test, use an extra 38 | * number so that the rehash happens at the right time. 39 | * Values are chosen to make sure that we chain on the third 40 | * number against the second. 41 | */ 42 | int_set_add(set, 1); 43 | int_set_add(set, 2); 44 | int_set_add(set, 15); 45 | int_set_remove(set, 2); 46 | int_set_add(set, 15); 47 | int_set_remove(set, 15); 48 | assert(!int_set_contains(set, 15)); 49 | 50 | int_set_destroy(set); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /tests/int-set/delete_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009,2013 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | * Carl Worth 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "int-set.h" 34 | 35 | int 36 | main(int argc, char **argv) 37 | { 38 | struct int_set *set; 39 | 40 | /* Use two values with the lowest bits in common so they will 41 | * hash to the same initial entry, so we can test the deletion 42 | * behavior for chained objects. */ 43 | uint32_t value1 = 0x00000123; 44 | uint32_t value2 = 0x10000123; 45 | uint32_t value3 = 0x20000123; 46 | struct int_set_entry *entry; 47 | 48 | set = int_set_create(); 49 | 50 | int_set_add(set, value1); 51 | int_set_add(set, value2); 52 | int_set_add(set, value3); 53 | 54 | assert(int_set_contains(set, value3)); 55 | entry = int_set_search(set, value3); 56 | assert(entry->value == value3); 57 | 58 | assert(int_set_contains(set, value2)); 59 | entry = int_set_search(set, value2); 60 | assert(entry->value == value2); 61 | 62 | assert(int_set_contains(set, value1)); 63 | entry = int_set_search(set, value1); 64 | assert(entry->value == value1); 65 | 66 | int_set_remove_entry(set, entry); 67 | int_set_remove(set, value2); 68 | 69 | assert(!int_set_contains(set, value1)); 70 | entry = int_set_search(set, value1); 71 | assert(entry == NULL); 72 | 73 | assert(!int_set_contains(set, value2)); 74 | entry = int_set_search(set, value2); 75 | assert(entry == NULL); 76 | 77 | assert(int_set_contains(set, value3)); 78 | entry = int_set_search(set, value3); 79 | assert(entry->value == value3); 80 | 81 | int_set_destroy(set); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tests/int-set/delete_management.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct int_set *set; 38 | struct int_set_entry *entry; 39 | int size = 10000; 40 | uint32_t i; 41 | 42 | set = int_set_create(); 43 | 44 | for (i = 0; i < size; i++) { 45 | int_set_add(set, i); 46 | 47 | if (i >= 100) { 48 | int_set_remove(set, i - 100); 49 | } 50 | } 51 | 52 | /* Make sure that all our entries were present at the end. */ 53 | for (i = size - 100; i < size; i++) { 54 | assert(int_set_contains(set, i)); 55 | entry = int_set_search(set, i); 56 | assert(entry); 57 | assert(entry->value == i); 58 | } 59 | 60 | /* Make sure that no extra entries got in */ 61 | for (entry = int_set_next_entry(set, NULL); 62 | entry != NULL; 63 | entry = int_set_next_entry(set, entry)) { 64 | assert(entry->value >= size - 100 && 65 | entry->value < size); 66 | } 67 | assert(set->entries == 100); 68 | 69 | int_set_destroy(set); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /tests/int-set/insert_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct int_set *set; 38 | uint32_t value1 = 0x14b5fbc8; 39 | uint32_t value2 = 0x5303d1ff; 40 | struct int_set_entry *entry; 41 | 42 | set = int_set_create(); 43 | 44 | int_set_add(set, value1); 45 | int_set_add(set, value2); 46 | 47 | assert(int_set_contains(set, value1)); 48 | entry = int_set_search(set, value1); 49 | assert(entry->value == value1); 50 | 51 | assert(int_set_contains(set, value2)); 52 | entry = int_set_search(set, value2); 53 | assert(entry->value == value2); 54 | 55 | int_set_destroy(set); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /tests/int-set/insert_many.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct int_set *set; 38 | struct int_set_entry *entry; 39 | int size = 1; 40 | uint32_t i; 41 | 42 | set = int_set_create(); 43 | 44 | for (i = 0; i < size; i++) { 45 | int_set_add(set, i); 46 | } 47 | 48 | for (i = 0; i < size; i++) { 49 | assert(int_set_contains(set, i)); 50 | entry = int_set_search(set, i); 51 | assert(entry); 52 | assert(entry->value == i); 53 | } 54 | assert(set->entries == size); 55 | 56 | int_set_destroy(set); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/int-set/null_destroy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "int-set.h" 31 | 32 | int 33 | main(int argc, char **argv) 34 | { 35 | int_set_destroy(NULL); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/int-set/null_remove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct int_set *set; 38 | 39 | set = int_set_create(); 40 | 41 | int_set_remove_entry(set, NULL); 42 | 43 | int_set_destroy(set); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tests/int-set/random_entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyrigset © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rigsets to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyrigset notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGSET HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | static int 35 | uint32_t_key_is_even(struct int_set_entry *entry) 36 | { 37 | return (entry->value & 1) == 0; 38 | } 39 | 40 | int 41 | main(int argc, char **argv) 42 | { 43 | struct int_set *set; 44 | struct int_set_entry *entry; 45 | int size = 10000; 46 | uint32_t i, random_value = 0; 47 | 48 | set = int_set_create(); 49 | 50 | for (i = 0; i < size; i++) { 51 | int_set_add(set, i); 52 | } 53 | 54 | /* Test the no-predicate case. */ 55 | entry = int_set_random_entry(set, NULL); 56 | assert(entry); 57 | 58 | /* Check that we're getting different entries and that the predicate 59 | * works. 60 | */ 61 | for (i = 0; i < 100; i++) { 62 | entry = int_set_random_entry(set, uint32_t_key_is_even); 63 | assert(entry); 64 | assert((entry->value & 1)== 0); 65 | if (i == 0 || entry->value != random_value) 66 | break; 67 | random_value = entry->value; 68 | } 69 | assert(i != 100); 70 | 71 | int_set_destroy(set); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/int-set/replace_deleted.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Broadcom Limited 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "int-set.h" 29 | #include "fnv_hash.h" 30 | 31 | int 32 | main(int argc, char **argv) 33 | { 34 | struct int_set *set; 35 | struct int_set_entry *entry_1, *entry_6; 36 | 37 | set = int_set_create(); 38 | 39 | /* Create a deleted entry. */ 40 | entry_1 = int_set_add(set, 1); 41 | int_set_remove(set, 1); 42 | 43 | /* Add an entry that hits the same slot. This assertion is 44 | * just to make sure that our test is triggering the bug 45 | * correctly and we're hitting the same table entry, in case 46 | * implementation changes. 47 | */ 48 | entry_6 = int_set_add(set, 6); 49 | assert(entry_6 == entry_1); 50 | 51 | /* Make sure that we think that the value we just added is 52 | * really present. This catches the actual bug. 53 | */ 54 | assert(int_set_contains(set, 6)); 55 | 56 | int_set_destroy(set); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/int-set/replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "int-set.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct int_set *set; 38 | uint32_t value = 0x11f9feca; 39 | struct int_set_entry *entry; 40 | 41 | set = int_set_create(); 42 | 43 | int_set_add(set, value); 44 | int_set_add(set, value); 45 | 46 | assert(int_set_contains(set, value)); 47 | entry = int_set_search(set, value); 48 | assert(entry); 49 | assert(entry->value == value); 50 | 51 | int_set_remove_entry(set, entry); 52 | 53 | assert(!int_set_contains(set, value)); 54 | entry = int_set_search(set, value); 55 | assert(!entry); 56 | 57 | int_set_destroy(set); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/null_destroy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include "hash_table.h" 30 | #include "fnv_hash.h" 31 | 32 | int 33 | main(int argc, char **argv) 34 | { 35 | hash_table_destroy(NULL, NULL); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tests/random_entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | 33 | /* Also doubles as hash function. */ 34 | static uint32_t 35 | key_value(const void *key) 36 | { 37 | return *(const uint32_t *)key; 38 | } 39 | 40 | static int 41 | uint32_t_key_equals(const void *a, const void *b) 42 | { 43 | return key_value(a) == key_value(b); 44 | } 45 | 46 | static int 47 | uint32_t_key_is_even(struct hash_entry *entry) 48 | { 49 | return (key_value(entry->key) & 1) == 0; 50 | } 51 | 52 | int 53 | main(int argc, char **argv) 54 | { 55 | struct hash_table *ht; 56 | struct hash_entry *entry; 57 | int size = 10000; 58 | uint32_t keys[size]; 59 | uint32_t i, random_value; 60 | 61 | ht = hash_table_create(key_value, uint32_t_key_equals); 62 | 63 | for (i = 0; i < size; i++) { 64 | keys[i] = i; 65 | 66 | hash_table_insert(ht, keys + i, NULL); 67 | } 68 | 69 | /* Test the no-predicate case. */ 70 | entry = hash_table_random_entry(ht, NULL); 71 | assert(entry); 72 | 73 | /* Check that we're getting different entries and that the predicate 74 | * works. 75 | */ 76 | for (i = 0; i < 100; i++) { 77 | entry = hash_table_random_entry(ht, uint32_t_key_is_even); 78 | assert(entry); 79 | assert((key_value(entry->key) & 1) == 0); 80 | if (i == 0 || key_value(entry->key) != random_value) 81 | break; 82 | random_value = key_value(entry->key); 83 | } 84 | assert(i != 100); 85 | 86 | hash_table_destroy(ht, NULL); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/remove_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct hash_table *ht; 38 | 39 | ht = hash_table_create_for_string(); 40 | 41 | hash_table_remove_entry(ht, NULL); 42 | 43 | hash_table_destroy(ht, NULL); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tests/replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "hash_table.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct hash_table *ht; 38 | char *str1 = strdup("test1"); 39 | char *str2 = strdup("test1"); 40 | uint32_t hash_str1 = fnv1_hash_string(str1); 41 | struct hash_entry *entry; 42 | 43 | ht = hash_table_create_for_string(); 44 | 45 | hash_table_insert_pre_hashed(ht, hash_str1, str1, str1); 46 | hash_table_insert(ht, str2, str2); 47 | 48 | entry = hash_table_search_pre_hashed(ht, hash_str1, str1); 49 | assert(entry); 50 | assert(entry->data == str2); 51 | 52 | entry = hash_table_search(ht, str1); 53 | assert(entry); 54 | assert(entry->data == str2); 55 | 56 | hash_table_remove_entry(ht, entry); 57 | 58 | entry = hash_table_search_pre_hashed(ht, hash_str1, str1); 59 | assert(!entry); 60 | 61 | entry = hash_table_search(ht, str1); 62 | assert(!entry); 63 | 64 | hash_table_destroy(ht, NULL); 65 | free(str1); 66 | free(str2); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /tests/set/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.trs 3 | collision_replacement 4 | delete_and_lookup 5 | delete_management 6 | deleted_key 7 | destroy_callback 8 | insert_and_lookup 9 | insert_many 10 | null_destroy 11 | null_remove 12 | random_entry 13 | replacement 14 | -------------------------------------------------------------------------------- /tests/set/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright © 2009 Intel Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice (including the next 11 | # paragraph) shall be included in all copies or substantial portions of the 12 | # Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | # IN THE SOFTWARE. 21 | 22 | AM_CFLAGS = $(WARN_CFLAGS) -I$(srcdir)/../.. 23 | LDADD = ../../libset.la 24 | 25 | TESTS = \ 26 | collision_replacement \ 27 | delete_and_lookup \ 28 | delete_management \ 29 | deleted_key \ 30 | destroy_callback \ 31 | insert_and_lookup \ 32 | insert_many \ 33 | null_destroy \ 34 | null_remove \ 35 | random_entry \ 36 | replacement \ 37 | $() 38 | 39 | EXTRA_PROGRAMS = $(TESTS) 40 | -------------------------------------------------------------------------------- /tests/set/collision_replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * Copyright © 2016 Broadcom Limited 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 | * IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "set.h" 30 | #include "fnv_hash.h" 31 | 32 | /* Return collisions, so we can test the deletion behavior for chained 33 | * objects. 34 | */ 35 | static uint32_t 36 | badhash(const void *key) 37 | { 38 | return 1; 39 | } 40 | 41 | int 42 | main(int argc, char **argv) 43 | { 44 | struct set *set; 45 | const char *str1 = "test1"; 46 | const char *str2 = "test2"; 47 | const char *str3 = "test3"; 48 | 49 | set = set_create(badhash, string_key_equals); 50 | 51 | /* Unlike the hash table equivalent of this test, use an extra 52 | * string so that the rehash happens at the right time. 53 | */ 54 | set_add(set, str1); 55 | set_add(set, str2); 56 | set_add(set, str3); 57 | set_remove(set, str2); 58 | set_add(set, str3); 59 | set_remove(set, str3); 60 | assert(!set_contains(set, str3)); 61 | 62 | set_destroy(set, NULL); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /tests/set/delete_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | /* Return collisions, so we can test the deletion behavior for chained 35 | * objects. 36 | */ 37 | static uint32_t 38 | badhash(const void *key) 39 | { 40 | return 1; 41 | } 42 | 43 | int 44 | main(int argc, char **argv) 45 | { 46 | struct set *set; 47 | const char *str1 = "test1"; 48 | const char *str2 = "test2"; 49 | const char *str3 = "test3"; 50 | uint32_t hash_str1 = badhash(str1); 51 | struct set_entry *entry; 52 | 53 | set = set_create(badhash, string_key_equals); 54 | 55 | set_add_pre_hashed(set, hash_str1, str1); 56 | set_add(set, str2); 57 | set_add(set, str3); 58 | 59 | assert(set_contains(set, str3)); 60 | entry = set_search(set, str3); 61 | assert(strcmp(entry->key, str3) == 0); 62 | 63 | assert(set_contains(set, str2)); 64 | entry = set_search(set, str2); 65 | assert(strcmp(entry->key, str2) == 0); 66 | 67 | assert(set_contains(set, str1)); 68 | entry = set_search_pre_hashed(set, hash_str1, str1); 69 | assert(strcmp(entry->key, str1) == 0); 70 | 71 | set_remove_entry(set, entry); 72 | set_remove(set, str2); 73 | 74 | assert(!set_contains(set, str1)); 75 | entry = set_search_pre_hashed(set, hash_str1, str1); 76 | assert(entry == NULL); 77 | 78 | assert(!set_contains(set, str2)); 79 | entry = set_search(set, str2); 80 | assert(entry == NULL); 81 | 82 | assert(set_contains(set, str3)); 83 | entry = set_search(set, str3); 84 | assert(strcmp(entry->key, str3) == 0); 85 | 86 | set_destroy(set, NULL); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/set/delete_management.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | /* Also doubles as the hash function. */ 35 | static uint32_t 36 | key_value(const void *key) 37 | { 38 | return *(const uint32_t *)key; 39 | } 40 | 41 | static int 42 | uint32_t_key_equals(const void *a, const void *b) 43 | { 44 | return key_value(a) == key_value(b); 45 | } 46 | 47 | int 48 | main(int argc, char **argv) 49 | { 50 | struct set *set; 51 | struct set_entry *entry; 52 | int size = 10000; 53 | uint32_t keys[size]; 54 | uint32_t i; 55 | 56 | set = set_create(key_value, uint32_t_key_equals); 57 | 58 | for (i = 0; i < size; i++) { 59 | keys[i] = i; 60 | 61 | set_add(set, &keys[i]); 62 | 63 | if (i >= 100) { 64 | uint32_t delete_value = i - 100; 65 | set_remove(set, &delete_value); 66 | } 67 | } 68 | 69 | /* Make sure that all our entries were present at the end. */ 70 | for (i = size - 100; i < size; i++) { 71 | assert(set_contains(set, &keys[i])); 72 | entry = set_search(set, &keys[i]); 73 | assert(entry); 74 | assert(key_value(entry->key) == i); 75 | } 76 | 77 | /* Make sure that no extra entries got in */ 78 | for (entry = set_next_entry(set, NULL); 79 | entry != NULL; 80 | entry = set_next_entry(set, entry)) { 81 | assert(key_value(entry->key) >= size - 100 && 82 | key_value(entry->key) < size); 83 | } 84 | assert(set->entries == 100); 85 | 86 | set_destroy(set, NULL); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/set/deleted_key.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2016 Broadcom Limited 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "set.h" 30 | #include "fnv_hash.h" 31 | 32 | static bool deleted = false; 33 | 34 | static int 35 | key_equals(const void *a, const void *b) 36 | { 37 | /* The comparison function shouldn't be called if our entry had 38 | * been deleted. 39 | */ 40 | assert(!deleted); 41 | 42 | return strcmp(a, b) == 0; 43 | } 44 | 45 | int 46 | main(int argc, char **argv) 47 | { 48 | struct set *ht; 49 | const char *str = "test1"; 50 | struct hash_entry *entry; 51 | 52 | ht = set_create((uint32_t (*)(const void *key))fnv1_hash_string, 53 | key_equals); 54 | 55 | set_add(ht, str); 56 | set_remove(ht, str); 57 | deleted = true; 58 | set_add(ht, str); 59 | assert(!entry); 60 | 61 | set_destroy(ht, NULL); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /tests/set/destroy_callback.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | static const char *str1 = "test1"; 35 | static const char *str2 = "test2"; 36 | static int delete_str1 = 0; 37 | static int delete_str2 = 0; 38 | 39 | static void 40 | delete_callback(struct set_entry *entry) 41 | { 42 | if (strcmp(entry->key, str1) == 0) 43 | delete_str1 = 1; 44 | else if (strcmp(entry->key, str2) == 0) 45 | delete_str2 = 1; 46 | else 47 | abort(); 48 | } 49 | 50 | int 51 | main(int argc, char **argv) 52 | { 53 | struct set *set; 54 | uint32_t hash_str1 = fnv1_hash_string(str1); 55 | 56 | set = set_create_for_string(); 57 | 58 | set_add_pre_hashed(set, hash_str1, str1); 59 | set_add(set, str2); 60 | 61 | set_destroy(set, delete_callback); 62 | 63 | assert(delete_str1 && delete_str2); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tests/set/insert_and_lookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct set *set; 38 | const char *str1 = "test1"; 39 | const char *str2 = "test2"; 40 | uint32_t hash_str1 = fnv1_hash_string(str1); 41 | struct set_entry *entry; 42 | 43 | set = set_create_for_string(); 44 | 45 | set_add_pre_hashed(set, hash_str1, str1); 46 | set_add(set, str2); 47 | 48 | assert(set_contains(set, str1)); 49 | entry = set_search_pre_hashed(set, hash_str1, str1); 50 | assert(strcmp(entry->key, str1) == 0); 51 | 52 | assert(set_contains(set, str2)); 53 | entry = set_search(set, str2); 54 | assert(strcmp(entry->key, str2) == 0); 55 | 56 | set_destroy(set, NULL); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/set/insert_many.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | 33 | /* Also double as hash function. */ 34 | static uint32_t 35 | key_value(const void *key) 36 | { 37 | return *(const uint32_t *)key; 38 | } 39 | 40 | static int 41 | uint32_t_key_equals(const void *a, const void *b) 42 | { 43 | return key_value(a) == key_value(b); 44 | } 45 | 46 | int 47 | main(int argc, char **argv) 48 | { 49 | struct set *set; 50 | struct set_entry *entry; 51 | int size = 10000; 52 | uint32_t keys[size]; 53 | uint32_t i; 54 | 55 | set = set_create(key_value, uint32_t_key_equals); 56 | 57 | for (i = 0; i < size; i++) { 58 | keys[i] = i; 59 | 60 | set_add_pre_hashed(set, i, keys + i); 61 | } 62 | 63 | for (i = 0; i < size; i++) { 64 | assert(set_contains(set, keys + i)); 65 | entry = set_search_pre_hashed(set, i, keys + i); 66 | assert(entry); 67 | assert(key_value(entry->key) == i); 68 | } 69 | assert(set->entries == size); 70 | 71 | set_destroy(set, NULL); 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tests/set/null_destroy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include "set.h" 30 | 31 | int 32 | main(int argc, char **argv) 33 | { 34 | set_destroy(NULL, NULL); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /tests/set/null_remove.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct set *set; 38 | 39 | set = set_create_for_string(); 40 | 41 | set_remove_entry(set, NULL); 42 | 43 | set_destroy(set, NULL); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /tests/set/random_entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyrigset © 2009 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rigsets to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyrigset notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGSET HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | 33 | /* Also doubles as hash function. */ 34 | static uint32_t 35 | key_value(const void *key) 36 | { 37 | return *(const uint32_t *)key; 38 | } 39 | 40 | static int 41 | uint32_t_key_equals(const void *a, const void *b) 42 | { 43 | return key_value(a) == key_value(b); 44 | } 45 | 46 | static int 47 | uint32_t_key_is_even(struct set_entry *entry) 48 | { 49 | return (key_value(entry->key) & 1) == 0; 50 | } 51 | 52 | int 53 | main(int argc, char **argv) 54 | { 55 | struct set *set; 56 | struct set_entry *entry; 57 | int size = 10000; 58 | uint32_t keys[size]; 59 | uint32_t i, random_value; 60 | 61 | set = set_create(key_value, uint32_t_key_equals); 62 | 63 | for (i = 0; i < size; i++) { 64 | keys[i] = i; 65 | 66 | set_add(set, keys + i); 67 | } 68 | 69 | /* Test the no-predicate case. */ 70 | entry = set_random_entry(set, NULL); 71 | assert(entry); 72 | 73 | /* Check that we're getting different entries and that the predicate 74 | * works. 75 | */ 76 | for (i = 0; i < 100; i++) { 77 | entry = set_random_entry(set, uint32_t_key_is_even); 78 | assert(entry); 79 | assert((key_value(entry->key) & 1) == 0); 80 | if (i == 0 || key_value(entry->key) != random_value) 81 | break; 82 | random_value = key_value(entry->key); 83 | } 84 | assert(i != 100); 85 | 86 | set_destroy(set, NULL); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tests/set/replacement.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2011 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | * IN THE SOFTWARE. 22 | * 23 | * Authors: 24 | * Eric Anholt 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "set.h" 32 | #include "fnv_hash.h" 33 | 34 | int 35 | main(int argc, char **argv) 36 | { 37 | struct set *set; 38 | char *str1 = strdup("test1"); 39 | char *str2 = strdup("test1"); 40 | uint32_t hash_str1 = fnv1_hash_string(str1); 41 | struct set_entry *entry; 42 | 43 | set = set_create_for_string(); 44 | 45 | set_add_pre_hashed(set, hash_str1, str1); 46 | set_add(set, str2); 47 | 48 | assert(set_contains(set, str1)); 49 | entry = set_search_pre_hashed(set, hash_str1, str1); 50 | assert(entry); 51 | assert(entry->key == str2); 52 | 53 | set_remove_entry(set, entry); 54 | 55 | assert(!set_contains(set, str1)); 56 | entry = set_search(set, str1); 57 | assert(!entry); 58 | 59 | set_destroy(set, NULL); 60 | free(str1); 61 | free(str2); 62 | 63 | return 0; 64 | } 65 | --------------------------------------------------------------------------------