├── LICENSE ├── Makefile ├── debug.h ├── hashtable.c ├── hashtable.h └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | A Simple hash table implementation 2 | Copyright (C) 2011 Ankur Shrivastava 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc -fPIC 2 | LDFLAGS = -lm 3 | 4 | # set DEBUG options 5 | ifdef DEBUG 6 | CFLAGS = -Wall -Wextra -ggdb -pg -DDEBUG 7 | else 8 | CFLAGS = -Wall -O2 9 | endif 10 | 11 | #name all the object files 12 | OBJS = main.o hashtable.o 13 | 14 | all : hashtable 15 | 16 | hashtable : $(OBJS) 17 | $(CC) $(LDFLAGS) -o main $^ 18 | 19 | debug : 20 | make all DEBUG=1 21 | 22 | %.o : %.c 23 | $(CC) $(CFLAGS) -o $@ -c $^ 24 | 25 | doxy : 26 | doxygen Doxyfile 27 | 28 | clean : 29 | rm -rf $(OBJS) main 30 | 31 | -------------------------------------------------------------------------------- /debug.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEBUG_H 2 | #define _DEBUG_H 3 | 4 | #ifdef DEBUG 5 | 6 | #include 7 | 8 | #define INFO(format) fprintf(stderr,"%s:%d:%s -> " format "\n", __FILE__, __LINE__, __func__) 9 | #define LOG(format, ...) fprintf(stderr,"%s:%d:%s -> " format "\n", __FILE__, __LINE__, __func__, __VA_ARGS__) 10 | 11 | #else 12 | 13 | #define LOG(...) 14 | #define INFO(...) 15 | 16 | #endif // debug 17 | 18 | #endif // debug.h 19 | -------------------------------------------------------------------------------- /hashtable.c: -------------------------------------------------------------------------------- 1 | /** 2 | * License GPLv3+ 3 | * @file hashtable.c 4 | * @brief a simple hash table implementation 5 | * @author Ankur Shrivastava 6 | */ 7 | #include "hashtable.h" 8 | #include "debug.h" 9 | 10 | #include 11 | #include 12 | 13 | // element operations 14 | /** 15 | * Function to create a now hash_table element 16 | * @returns hash_table_element_t object when success 17 | * @returns NULL when no memory 18 | */ 19 | hash_table_element_t * hash_table_element_new() 20 | { 21 | INFO("creating a new hash table element"); 22 | return calloc(1, hash_table_element_s); 23 | } 24 | 25 | /** 26 | * Function to delete an hash table element 27 | * @param table table from which element has to be deleted 28 | * @param element hash table element to be deleted 29 | */ 30 | void hash_table_element_delete(hash_table_t * table, hash_table_element_t * element) 31 | { 32 | INFO("Deleting an hash table element"); 33 | if (table->mode == MODE_COPY) 34 | { 35 | free(element->value); 36 | free(element->key); 37 | } 38 | else if (table->mode == MODE_VALUEREF) 39 | { 40 | free(element->key); 41 | } 42 | free(element); 43 | } 44 | 45 | // hash table operations 46 | /** 47 | * Fuction to create a new hash table 48 | * @param mode hash_table_mode which the hash table should follow 49 | * @returns hash_table_t object which references the hash table 50 | * @returns NULL when no memory 51 | */ 52 | hash_table_t * hash_table_new(hash_table_mode_t mode) 53 | { 54 | INFO("Creating a new hash table"); 55 | hash_table_t *table = calloc(1, hash_table_s); 56 | if (!table) 57 | { 58 | INFO("No Memory while allocating hash_table"); 59 | return NULL; 60 | } 61 | table->mode = mode; 62 | table->key_num = 128; 63 | table->key_ratio = 4; 64 | table->store_house = (hash_table_element_t **) calloc(table->key_num, sizeof(hash_table_element_t *)); 65 | if (!table->store_house) 66 | { 67 | INFO("No Memory while allocating hash_table store house"); 68 | free(table); 69 | return NULL; 70 | } 71 | return table; 72 | } 73 | 74 | /** 75 | * Function to delete the hash table 76 | * @param table hash table to be deleted 77 | */ 78 | void hash_table_delete(hash_table_t * table) 79 | { 80 | INFO("Deleating a hash table"); 81 | size_t i=0; 82 | for (;istore_house[i]) 85 | { 86 | hash_table_element_t * temp = table->store_house[i]; 87 | table->store_house[i] = table->store_house[i]->next; 88 | hash_table_element_delete(table, temp); 89 | } 90 | } 91 | free(table->store_house); 92 | free(table); 93 | } 94 | 95 | /** 96 | * Function to add a key - value pair to the hash table, use HT_ADD macro 97 | * @param table hash table to add element to 98 | * @param key pointer to the key for the hash table 99 | * @param key_len length of the key in bytes 100 | * @param value pointer to the value to be added against the key 101 | * @param value_len length of the value in bytes 102 | * @returns 0 on sucess 103 | * @returns -1 when no memory 104 | */ 105 | int hash_table_add(hash_table_t * table, void * key, size_t key_len, void * value, size_t value_len) 106 | { 107 | if ((table->key_count / table->key_num) >= table->key_ratio) 108 | { 109 | LOG("Ratio(%d) reached the set limit %d\nExpanding hash_table", (table->key_count / table->key_num), table->key_ratio); 110 | hash_table_resize(table, table->key_num*2); 111 | //exit(0); 112 | } 113 | size_t hash = HASH(key, key_len); 114 | hash_table_element_t * element = hash_table_element_new(); 115 | if (!element) 116 | { 117 | INFO("Cannot allocate memory for element"); 118 | return -1; // No Memory 119 | } 120 | if (table->mode == MODE_COPY) 121 | { 122 | LOG("Adding a key-value pair to the hash table with hash -> %d, in COPY MODE", (int)hash); 123 | element->key = malloc(key_len); 124 | element->value = malloc(value_len); 125 | if (element->key && element->value) 126 | { 127 | memcpy(element->key, key, key_len); 128 | memcpy(element->value, value, value_len); 129 | } 130 | else 131 | { 132 | if (element->key) 133 | { 134 | free(element->key); 135 | INFO("Cannot allocate memory for value"); 136 | } 137 | if (element->value) 138 | { 139 | free(element->value); 140 | INFO("Cannot allocate memory for key"); 141 | } 142 | free(element); 143 | return -1; //No Memory 144 | } 145 | } 146 | else if (table->mode == MODE_VALUEREF) 147 | { 148 | LOG("Adding a key-value pair to the hash table with hash -> %d, in VALUEREF MODE", (int)hash); 149 | element->key = malloc(key_len); 150 | if (element->key) 151 | { 152 | memcpy(element->key, key, key_len); 153 | } 154 | else 155 | { 156 | INFO("Cannot allocate memory for key"); 157 | free(element); 158 | return -1; //No Memory 159 | } 160 | element->value = value; 161 | } 162 | else if (table->mode == MODE_ALLREF) 163 | { 164 | LOG("Adding a key-value pair to the hash table with hash -> %d, in ALLREF MODE", (int)hash); 165 | element->key = key; 166 | element->value = value; 167 | } 168 | element->key_len = key_len; 169 | element->value_len = value_len; 170 | element->next = NULL; 171 | // find the key position for chaining 172 | if (!table->store_house[hash]) 173 | { 174 | LOG("No Conflicts adding the first element at %d", (int)hash); 175 | table->store_house[hash] = element; 176 | table->key_count++; 177 | } 178 | else 179 | { 180 | LOG("Conflicts adding element at %d", (int)hash); 181 | hash_table_element_t * temp = table->store_house[hash]; 182 | while(temp->next) 183 | { 184 | while(temp->next && temp->next->key_len!=key_len) 185 | { 186 | temp = temp->next; 187 | } 188 | if(temp->next) 189 | { 190 | if (!memcmp(temp->next->key, key, key_len)) 191 | { 192 | LOG("Found Key at hash -> %d", (int)hash); 193 | hash_table_element_t *to_delete = temp->next; 194 | temp->next = element; 195 | element->next = to_delete->next; 196 | hash_table_element_delete(table, to_delete); 197 | // since we are replacing values no need to change key_count 198 | return 0; 199 | } 200 | else 201 | { 202 | temp = temp->next; 203 | } 204 | } 205 | } 206 | temp->next = element; 207 | table->key_count++; 208 | } 209 | return 0; 210 | } 211 | 212 | /** 213 | * Function to remove an hash table element (for a given key) from a given hash table 214 | * @param table hash table from which element has to be removed 215 | * @param key pointer to the key which has to be removed 216 | * @param key_len size of the key in bytes 217 | * @returns 0 on sucess 218 | * @returns -1 when key is not found 219 | */ 220 | int hash_table_remove(hash_table_t * table, void * key, size_t key_len) 221 | { 222 | INFO("Deleting a key-value pair from the hash table"); 223 | if ((table->key_num/ table->key_count) >= table->key_ratio) 224 | { 225 | LOG("Ratio(%d) reached the set limit %d\nContracting hash_table", (table->key_num / table->key_count), table->key_ratio); 226 | hash_table_resize(table, table->key_num/2); 227 | //exit(0); 228 | } 229 | size_t hash = HASH(key, key_len); 230 | if (!table->store_house[hash]) 231 | { 232 | LOG("Key Not Found -> No element at %d", (int)hash); 233 | return -1; // key not found 234 | } 235 | hash_table_element_t *temp = table->store_house[hash]; 236 | hash_table_element_t *prev = temp; 237 | while(temp) 238 | { 239 | while(temp && temp->key_len!=key_len) 240 | { 241 | prev = temp; 242 | temp = temp->next; 243 | } 244 | if(temp) 245 | { 246 | if (!memcmp(temp->key, key, key_len)) 247 | { 248 | if (prev == table->store_house[hash]) 249 | { 250 | table->store_house[hash] = temp->next; 251 | } 252 | else 253 | { 254 | prev->next = temp->next; 255 | } 256 | hash_table_element_delete(table, temp); 257 | INFO("Deleted a key-value pair from the hash table"); 258 | table->key_count--; 259 | return 0; 260 | } 261 | prev=temp; 262 | temp=temp->next; 263 | } 264 | } 265 | INFO("Key Not Found"); 266 | return -1; // key not found 267 | } 268 | 269 | /** 270 | * Function to lookup a key in a particular table 271 | * @param table table to look key in 272 | * @param key pointer to key to be looked for 273 | * @param key_len size of the key to be searched 274 | * @returns NULL when key is not found in the hash table 275 | * @returns void* pointer to the value in the table 276 | */ 277 | void * hash_table_lookup(hash_table_t * table, void * key, size_t key_len) 278 | { 279 | size_t hash = HASH(key, key_len); 280 | LOG("Looking up a key-value pair for hash -> %d", (int)hash); 281 | if (!table->store_house[hash]) 282 | { 283 | LOG("Key not found at hash %d, no entries", (int)hash); 284 | return NULL; // key not found 285 | } 286 | hash_table_element_t *temp = table->store_house[hash]; 287 | while(temp) 288 | { 289 | while(temp && temp->key_len!=key_len) 290 | { 291 | temp = temp->next; 292 | } 293 | if(temp) 294 | { 295 | if (!memcmp(temp->key, key, key_len)) 296 | { 297 | LOG("Found Key at hash -> %d", (int)hash); 298 | return temp->value; 299 | } 300 | else 301 | { 302 | temp = temp->next; 303 | } 304 | } 305 | } 306 | LOG("Key not found at hash %d", (int)hash); 307 | return NULL; // key not found 308 | } 309 | 310 | /** 311 | * Function to look if the exists in the hash table 312 | * @param key pointer to key to be looked for 313 | * @param key_len size of the key to be searched 314 | * @returns 0 when key is not found 315 | * @returns 1 when key is found 316 | */ 317 | int hash_table_has_key(hash_table_t * table, void * key, size_t key_len) 318 | { 319 | size_t hash = HASH(key, key_len); 320 | LOG("Searching for key with hash -> %d", (int)hash); 321 | if (!table->store_house[hash]) 322 | { 323 | LOG("Key not found with hash -> %d, no entries", (int)hash); 324 | return 0; // key not found 325 | } 326 | hash_table_element_t *temp = table->store_house[hash]; 327 | while(temp) 328 | { 329 | while(temp && temp->key_len!=key_len) 330 | { 331 | temp = temp->next; 332 | } 333 | if(temp) 334 | { 335 | if (!memcmp(temp->key, key, key_len)) 336 | { 337 | LOG("Key Found with hash -> %d", (int)hash); 338 | return 1; // key found 339 | } 340 | temp=temp->next; 341 | } 342 | } 343 | LOG("Key not found with hash -> %d", (int)hash); 344 | return 0; // key not found 345 | } 346 | 347 | /** 348 | * Function to return all the keys in a given hash table 349 | * @param table hash table from which key are to be reterived 350 | * @param keys a void** pointer where keys are filled in (memory allocated internally and must be freed) 351 | * @return total number of keys filled in keys 352 | */ 353 | size_t hash_table_get_keys(hash_table_t * table, void ** keys) 354 | { 355 | size_t i = 0; 356 | size_t count = 0; 357 | keys = calloc(table->key_count, sizeof(void *)); 358 | for(i=0;istore_house[i]) 361 | { 362 | keys[count++] = table->store_house[i]; 363 | hash_table_element_t *temp = table->store_house[i]; 364 | #ifdef DEBUG 365 | size_t num = 1; 366 | #endif 367 | while(temp->next) 368 | { 369 | keys[count++] = temp->next; 370 | temp = temp->next; 371 | #ifdef DEBUG 372 | num++; 373 | #endif 374 | } 375 | #ifdef DEBUG 376 | LOG("found %d key(s) at hash -> %d", (int)num, (int)i); 377 | #endif 378 | } 379 | } 380 | return count; 381 | } 382 | 383 | /** 384 | * Function to get all elements (key - value pairs) from the given hash table 385 | * @param table hash table from which elements have to be retrieved 386 | * @param elements a pointer to an array of hash_table_element_t pointer (malloced by function) 387 | * @returns 1 when no memory 388 | * @returns count of elements 389 | */ 390 | size_t hash_table_get_elements(hash_table_t * table, hash_table_element_t *** elements) 391 | { 392 | size_t i = 0; 393 | size_t count = 0; 394 | (*elements) = (hash_table_element_t **) calloc(table->key_count, sizeof(hash_table_element_t *)); 395 | if (!*elements) 396 | { 397 | INFO("No Memory to allocate elements array"); 398 | return 1; 399 | } 400 | for(i=0;istore_house[i]) 403 | { 404 | (*elements)[count++] = table->store_house[i]; 405 | hash_table_element_t *temp = table->store_house[i]; 406 | #ifdef DEBUG 407 | size_t num = 1; 408 | #endif 409 | while(temp->next) 410 | { 411 | (*elements)[count++] = temp->next; 412 | temp = temp->next; 413 | #ifdef DEBUG 414 | num++; 415 | #endif 416 | } 417 | #ifdef DEBUG 418 | LOG("found %d key(s) at hash -> %d", (int)num, (int)i); 419 | #endif 420 | } 421 | } 422 | return count; 423 | } 424 | 425 | /** 426 | * Function that returns a hash value for a given key and key_len 427 | * @param key pointer to the key 428 | * @param key_len length of the key 429 | * @param max_key max value of the hash to be returned by the function 430 | * @returns hash value belonging to [0, max_key) 431 | */ 432 | uint16_t hash_table_do_hash(void * key, size_t key_len, uint16_t max_key) 433 | { 434 | uint16_t *ptr = (uint16_t *) key; 435 | uint16_t hash = 0xbabe; // WHY NOT 436 | size_t i = 0; 437 | for(;i<(key_len/2);i++) 438 | { 439 | hash^=(i<<4 ^ *ptr<<8 ^ *ptr); 440 | ptr++; 441 | } 442 | hash = hash % max_key; 443 | return hash; 444 | } 445 | 446 | /** 447 | * Function to resize the hash table store house 448 | * @param table hash table to be resized 449 | * @param len new length of the hash table 450 | * @returns -1 when no elements in hash table 451 | * @returns -2 when no emmory for new store house 452 | * @returns 0 when sucess 453 | */ 454 | int hash_table_resize(hash_table_t *table, size_t len) 455 | { 456 | LOG("resizing hash table from %d to %d", table->key_num, len); 457 | hash_table_element_t ** elements; 458 | size_t count; 459 | // FIXME traversing the elements twice, change it some time soon 460 | count = hash_table_get_elements(table, &elements); 461 | if (!count) 462 | { 463 | INFO("Got No Elements from the hash table"); 464 | return -1; 465 | } 466 | // keep the current store house in case we dont get more memory 467 | hash_table_element_t ** temp = table->store_house; 468 | table->store_house = calloc(len, sizeof(hash_table_element_t *)); 469 | if (!table->store_house) 470 | { 471 | table->store_house = temp; 472 | INFO("No Memory for new store house"); 473 | return -2; 474 | } 475 | table->key_num = len; 476 | // fool the new hash table so if refers even previously copied values 477 | int mode = table->mode; 478 | table->mode = MODE_ALLREF; 479 | // the new table starts from scratch 480 | table->key_count = 0; 481 | while(count>0) 482 | { 483 | hash_table_element_t *elem = elements[--count]; 484 | hash_table_add(table, elem->key, elem->key_len, elem->value, elem->value_len); 485 | } 486 | table->mode = mode; 487 | // free old store house 488 | free(temp); 489 | return 0; 490 | } 491 | 492 | /** 493 | * Function to iterate through all elements of the hashtable 494 | * @param table hash table to be iterated 495 | * @param fct pointer to a function returning 1 if the element has to be removed 496 | * @param user arbitrary user pointer passed to the fct callback 497 | * @returns 0 when success 498 | */ 499 | int hash_table_iterate(hash_table_t *table, int (*fct)(void *user, 500 | void *value, void *key, size_t key_len), void *user) 501 | { 502 | LOG("iterating hash table"); 503 | int i; 504 | 505 | for(i=0;istore_house[i]) 508 | { 509 | hash_table_element_t *temp = table->store_house[i]; 510 | hash_table_element_t *prev = NULL; 511 | while(temp) 512 | { 513 | int r = fct(user, temp->value, temp->key, temp->key_len); 514 | if (r){ 515 | hash_table_element_t *next = temp->next; 516 | hash_table_element_delete(table,temp); 517 | if(prev == NULL) 518 | table->store_house[i] = next; 519 | else 520 | prev->next = next; 521 | temp = next; 522 | table->key_count--; 523 | } else { 524 | prev = temp; 525 | temp = temp->next; 526 | } 527 | } 528 | } 529 | } 530 | return 0; 531 | } 532 | -------------------------------------------------------------------------------- /hashtable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * License GPLv3+ 3 | * @file hashtable.h 4 | * @brief a simple hash table implementation 5 | * @author Ankur Shrivastava 6 | */ 7 | #ifndef _HASHTABLE_H 8 | #define _HASHTABLE_H 9 | 10 | #include 11 | #include 12 | 13 | #define HASH_LEN table->key_num 14 | #define HASH(x,y) hash_table_do_hash(x,y,HASH_LEN) 15 | 16 | // forward declaration 17 | typedef struct hash_table_element hash_table_element_t; 18 | 19 | /** 20 | * @struct hash_table_element "hashtable.h" 21 | * @brief stores an hash table element for use in the hash table 22 | */ 23 | struct hash_table_element 24 | { 25 | /** 26 | * store the length in bytes of the key 27 | */ 28 | size_t key_len; 29 | /** 30 | * stores the length in bytes of the key (only for copy mode) 31 | */ 32 | size_t value_len; 33 | /** 34 | * pointer to the key 35 | */ 36 | void * key; 37 | /** 38 | * pointer to the value 39 | */ 40 | void * value; 41 | /** 42 | * next chained key for this hash 43 | */ 44 | hash_table_element_t * next; 45 | }; 46 | #define hash_table_element_s sizeof(hash_table_element_t) 47 | 48 | /** 49 | * @enum hash_table_mode defines the mode of operation of hash table 50 | */ 51 | typedef enum hash_table_mode{ 52 | /** copy mode here values as well as key is copied */ 53 | MODE_COPY, 54 | /** value reference mode, here ONLY key is copies and value is always referred */ 55 | MODE_VALUEREF, 56 | /** in this mode all keys and values are referred */ 57 | MODE_ALLREF 58 | } hash_table_mode_t; 59 | 60 | /** 61 | * @struct hash_table "hashtable.h" 62 | * @brief identifies the hashtable for which operations are to be performed 63 | */ 64 | typedef struct hash_table 65 | { 66 | /** 67 | * the hash table array where all values are stored 68 | */ 69 | hash_table_element_t ** store_house; 70 | 71 | /** 72 | * mode of the hash table 73 | */ 74 | hash_table_mode_t mode; 75 | 76 | /** 77 | * number of keys in the hash table 78 | */ 79 | size_t key_count; 80 | 81 | /** 82 | * number of keys allocated in the hash table 83 | */ 84 | uint16_t key_num; 85 | 86 | /** 87 | * the ratio of key_count / key_num at which the hash table should be expanded 88 | */ 89 | size_t key_ratio; 90 | 91 | } hash_table_t; 92 | #define hash_table_s sizeof(hash_table_t) 93 | 94 | 95 | // element operations 96 | /** 97 | * Function to create a now hash_table element 98 | * @returns hash_table_element_t object when success 99 | * @returns NULL when no memory 100 | */ 101 | hash_table_element_t * hash_table_element_new(); 102 | 103 | /** 104 | * Function to delete an hash table element 105 | * @param table table from which element has to be deleted 106 | * @param element hash table element to be deleted 107 | */ 108 | void hash_table_element_delete(hash_table_t *, hash_table_element_t *); 109 | 110 | /** 111 | * Function that returns a hash value for a given key and key_len 112 | * @param key pointer to the key 113 | * @param key_len length of the key 114 | * @param max_key max value of the hash to be returned by the function 115 | * @returns hash value belonging to [0, max_key) 116 | */ 117 | uint16_t hash_table_do_hash(void * key, size_t key_len, uint16_t max_key); 118 | 119 | // hash table operations 120 | /** 121 | * Fuction to create a new hash table 122 | * @param mode hash_table_mode which the hash table should follow 123 | * @returns hash_table_t object which references the hash table 124 | * @returns NULL when no memory 125 | */ 126 | hash_table_t * hash_table_new(hash_table_mode_t); 127 | 128 | /** 129 | * Function to delete the hash table 130 | * @param table hash table to be deleted 131 | */ 132 | void hash_table_delete(hash_table_t *); 133 | 134 | /** 135 | * macro to add a key - value pair to the hash table 136 | * @note use this macro when size of key and/or value can be given by sizeof 137 | * @param table hash table to add element to 138 | * @param key pointer to the key for the hash table 139 | * @param value pointer to the value to be added against the key 140 | * @returns 0 on sucess 141 | * @returns -1 when no memory 142 | */ 143 | #define HT_ADD(table, key, value) hash_table_add(table, (void *) key, sizeof(*key), (void *) value, sizeof(*value)) 144 | 145 | /** 146 | * Function to add a key - value pair to the hash table, use HT_ADD macro 147 | * @param table hash table to add element to 148 | * @param key pointer to the key for the hash table 149 | * @param key_len length of the key in bytes 150 | * @param value pointer to the value to be added against the key 151 | * @param value_len length of the value in bytes 152 | * @returns 0 on sucess 153 | * @returns -1 when no memory 154 | */ 155 | int hash_table_add(hash_table_t *, void *, size_t, void *, size_t); 156 | 157 | /** 158 | * macro to remove an hash table element (for a given key) from a given hash table 159 | * @note use this macro when size of key and/or value can be given by sizeof 160 | * @param table hash table from which element has to be removed 161 | * @param key pointer to the key which has to be removed 162 | * @returns 0 on sucess 163 | * @returns -1 when key is not found 164 | */ 165 | #define HT_REMOVE(table, key) hash_table_remove(table, key, sizeof(*key)) 166 | 167 | /** 168 | * Function to remove an hash table element (for a given key) from a given hash table 169 | * @param table hash table from which element has to be removed 170 | * @param key pointer to the key which has to be removed 171 | * @param key_len size of the key in bytes 172 | * @returns 0 on sucess 173 | * @returns -1 when key is not found 174 | */ 175 | int hash_table_remove(hash_table_t *, void *, size_t); 176 | 177 | /** 178 | * macro to lookup a key in a particular table 179 | * @param table table to look key in 180 | * @param key pointer to key to be looked for 181 | * @returns NULL when key is not found in the hash table 182 | * @returns void* pointer to the value in the table 183 | */ 184 | #define HT_LOOKUP(table, key) hash_table_lookup(table, key, sizeof(*key)) 185 | 186 | /** 187 | * Function to lookup a key in a particular table 188 | * @note use this macro when size of key and/or value can be given by sizeof 189 | * @param table table to look key in 190 | * @param key pointer to key to be looked for 191 | * @param key_len size of the key to be searched 192 | * @returns NULL when key is not found in the hash table 193 | * @returns void* pointer to the value in the table 194 | */ 195 | void * hash_table_lookup(hash_table_t *, void *, size_t); 196 | 197 | /** 198 | * macro to look if the exists in the hash table 199 | * @note use this macro when size of key and/or value can be given by sizeof 200 | * @param key pointer to key to be looked for 201 | * @returns 0 when key is not found 202 | * @returns 1 when key is found 203 | */ 204 | #define HT_HAS_KEY(table, key) hash_table_has_key(table, key, sizeof(*key)) 205 | 206 | /** 207 | * Function to look if the exists in the hash table 208 | * @param key pointer to key to be looked for 209 | * @param key_len size of the key to be searched 210 | * @returns 0 when key is not found 211 | * @returns 1 when key is found 212 | */ 213 | int hash_table_has_key(hash_table_t *, void *, size_t); 214 | 215 | /** 216 | * Function to return all the keys in a given hash table 217 | * @param table hash table from which key are to be reterived 218 | * @param keys a void** pointer where keys are filled in (memory allocated internally and must be freed) 219 | * @return total number of keys filled in keys 220 | */ 221 | size_t hash_table_get_keys(hash_table_t *, void **); 222 | 223 | /** 224 | * Function to get all elements (key - value pairs) from the given hash table 225 | * @param table hash table from which elements have to be retrieved 226 | * @param elements a pointer to an array of hash_table_element_t pointer (malloced by function) 227 | * @returns 1 when no memory 228 | * @returns count of elements 229 | */ 230 | size_t hash_table_get_elements(hash_table_t *, hash_table_element_t *** ); 231 | 232 | /** 233 | * Function to resize the hash table store house 234 | * @param table hash table to be resized 235 | * @param len new length of the hash table 236 | * @returns -1 when no elements in hash table 237 | * @returns -2 when no emmory for new store house 238 | * @returns 0 when sucess 239 | */ 240 | int hash_table_resize(hash_table_t *, size_t); 241 | 242 | /** 243 | * Function to iterate through all elements of the hashtable 244 | * @param table hash table to be iterated 245 | * @param fct pointer to a function returning 1 if the element has to be removed 246 | * @param user arbitrary user pointer passed to the fct callback 247 | * @returns 0 when success 248 | */ 249 | int hash_table_iterate(hash_table_t *table, int (*fct)(void *user, 250 | void *value, void *key, size_t key_len), void *user); 251 | #endif 252 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hashtable.h" 3 | 4 | int main() 5 | { 6 | hash_table_t *table = hash_table_new(MODE_COPY); 7 | int i = 1; 8 | int val = 100; 9 | int val2 = 200; 10 | int j = 2; 11 | int x =0; 12 | for (x=0;x<3000;x++) 13 | { 14 | // use the macro 15 | HT_ADD(table, &j, &val); 16 | // or use the function 17 | //hash_table_add(table, &j, i, (void *) &val, sizeof(int)); 18 | val++; 19 | j++; 20 | } 21 | hash_table_add(table, &j, i, (void *) &val2, 1); 22 | j--; j--; 23 | hash_table_remove(table, &j, i); 24 | HT_REMOVE(table, &j); 25 | if (hash_table_has_key(table, &j, i)) 26 | { 27 | printf("Key found %d\n", j); 28 | } 29 | else 30 | { 31 | printf("Key NOT found %d\n", j); 32 | } 33 | val = -100; 34 | val2 = -200; 35 | j--; 36 | int *value = NULL; 37 | value = (int* ) HT_LOOKUP(table, &j); 38 | void** keys = NULL; 39 | size_t num = hash_table_get_keys(table, keys); 40 | printf("found %d keys\n", (int)num); 41 | printf("j -> %d \n", j); 42 | if (value) 43 | printf("value is %d\n", *value); 44 | else 45 | printf("*value is %p\n", value); 46 | 47 | return 0; 48 | } 49 | --------------------------------------------------------------------------------