/** * Function to iterate through all elements of the hashtable * @param table hash table to be iterated * @param fct pointer to a function returning 1 if the element has to be removed * @param user arbitrary user pointer passed to the fct callback * @returns 0 when success */ int _cdecl hash_table_iterate(hash_table_t *table, int (*fct)(void *user, void *value, void *key, size_t key_len), void *user) { int i; print_info("iterating hash table\n"); for(i=0;i<HASH_LEN;i++) { if (table->store_house[i]) { hash_table_element_t *temp = table->store_house[i]; hash_table_element_t *prev = NULL; while(temp) { int r = fct(user, temp->value, temp->key, temp->key_len); if (r){ hash_table_element_t *next = temp->next; hash_table_element_delete(table,temp); if(prev == NULL) table->store_house[i] = next; else prev->next = next; temp = next; table->key_count--; } else { prev = temp; temp = temp->next; } } } } return 0; }
/** * Function to remove an hash table element (for a given key) from a given hash table * @param table hash table from which element has to be removed * @param key pointer to the key which has to be removed * @param key_len size of the key in bytes * @returns 0 on sucess * @returns -1 when key is not found */ int _cdecl hash_table_remove(hash_table_t * table, void * key, size_t key_len) { size_t hash; hash_table_element_t *temp, *prev; print_info("Deleting a key-value pair from the hash table\n"); if ((table->key_num/ table->key_count) >= table->key_ratio) { print_info("Ratio(%d) reached the set limit %d\nContracting hash_table\n", (table->key_num / table->key_count), table->key_ratio); hash_table_resize(table, table->key_num/2); //exit(0); } hash = HASH(key, key_len); if (!table->store_house[hash]) { print_info("Key Not Found -> No element at %d\n", (int)hash); return -1; // key not found } temp = table->store_house[hash]; prev = temp; while(temp) { while(temp && temp->key_len!=key_len) { prev = temp; temp = temp->next; } if(temp) { if (!memcmp(temp->key, key, key_len)) { if (prev == table->store_house[hash]) { table->store_house[hash] = temp->next; } else { prev->next = temp->next; } hash_table_element_delete(table, temp); print_info("Deleted a key-value pair from the hash table\n"); table->key_count--; return 0; } prev=temp; temp=temp->next; } } print_info("Key Not Found\n"); return -1; // key not found }
/** * Function to delete the hash table * @param table hash table to be deleted */ void hash_table_delete(hash_table_t * table) { INFO("Deleating a hash table"); size_t i=0; for (;i<HASH_LEN;i++) { while (table->store_house[i]) { hash_table_element_t * temp = table->store_house[i]; table->store_house[i] = table->store_house[i]->next; hash_table_element_delete(table, temp); } } free(table); }
/** * Function to delete the hash table * @param table hash table to be deleted */ void _cdecl hash_table_delete(hash_table_t * table) { size_t i=0; print_info("Deleating a hash table\n"); for (;i<HASH_LEN;i++) { while (table->store_house[i]) { hash_table_element_t * temp = table->store_house[i]; table->store_house[i] = table->store_house[i]->next; hash_table_element_delete(table, temp); } } free(table->store_house); free(table); }
/** * Function to remove an hash table element (for a given key) from a given hash table * @param table hash table from which element has to be removed * @param key pointer to the key which has to be removed * @param key_len size of the key in bytes * @returns 0 on sucess * @returns -1 when key is not found */ int hash_table_remove(hash_table_t * table, void * key, size_t key_len) { INFO("Deleting a key-value pair from the hash table"); size_t hash = HASH(key, key_len); if (!table->store_house[hash]) { LOG("Key Not Found -> No element at %d", (int)hash); return -1; // key not found } hash_table_element_t *temp = table->store_house[hash]; hash_table_element_t *prev = temp; while(temp) { while(temp && temp->key_len!=key_len) { prev = temp; temp = temp->next; } if(temp) { if (!memcmp(temp->key, key, key_len)) { if (prev == table->store_house[hash]) { table->store_house[hash] = temp->next; } else { prev->next = temp->next; } hash_table_element_delete(table, temp); INFO("Deleted a key-value pair from the hash table"); table->key_count--; return 0; } temp=temp->next; } } INFO("Key Not Found"); return -1; // key not found }
/** * Function to add a key - value pair to the hash table, use HT_ADD macro * @param table hash table to add element to * @param key pointer to the key for the hash table * @param key_len length of the key in bytes * @param value pointer to the value to be added against the key * @param value_len length of the value in bytes * @returns 0 on sucess * @returns -1 when no memory */ int hash_table_add(hash_table_t * table, void * key, size_t key_len, void * value, size_t value_len) { size_t hash = HASH(key, key_len); hash_table_element_t * element = hash_table_element_new(); if (!element) { INFO("Cannot allocate memory for element"); return -1; // No Memory } if (table->mode == MODE_COPY) { LOG("Adding a key-value pair to the hash table with hash -> %d, in COPY MODE", (int)hash); element->key = malloc(key_len); element->value = malloc(value_len); if (element->key && element->value) { memcpy(element->key, key, key_len); memcpy(element->value, value, value_len); } else { if (element->key) { free(element->key); INFO("Cannot allocate memory for value"); } if (element->value) { free(element->value); INFO("Cannot allocate memory for key"); } free(element); return -1; //No Memory } } else if (table->mode == MODE_VALUEREF) { LOG("Adding a key-value pair to the hash table with hash -> %d, in VALUEREF MODE", (int)hash); element->key = malloc(key_len); if (element->key) { memcpy(element->key, key, key_len); } else { INFO("Cannot allocate memory for key"); free(element); return -1; //No Memory } element->value = value; } element->key_len = key_len; element->value_len = value_len; element->next = NULL; // find the key position for chaining if (!table->store_house[hash]) { LOG("No Conflicts adding the first element at %d", (int)hash); table->store_house[hash] = element; table->key_count++; } else { LOG("Conflicts adding element at %d", (int)hash); hash_table_element_t * temp = table->store_house[hash]; while(temp->next) { while(temp->next && temp->next->key_len!=key_len) { temp = temp->next; } if(temp->next) { if (!memcmp(temp->next->key, key, key_len)) { LOG("Found Key at hash -> %d", (int)hash); hash_table_element_t *to_delete = temp->next; temp->next = element; element->next = to_delete->next; hash_table_element_delete(table, to_delete); // since we are replacing values no need to change key_count return 0; } else { temp = temp->next; } } } temp->next = element; table->key_count++; } return 0; }
/** * Function to add a key - value pair to the hash table, use HT_ADD macro * @param table hash table to add element to * @param key pointer to the key for the hash table * @param key_len length of the key in bytes * @param value pointer to the value to be added against the key * @param value_len length of the value in bytes * @returns 0 on sucess * @returns -1 when no memory */ int _cdecl hash_table_add(hash_table_t * table, void * key, size_t key_len, void * value, size_t value_len) { size_t hash; hash_table_element_t * element; if ((table->key_count / table->key_num) >= table->key_ratio) { print_info("Ratio(%d) reached the set limit %d\nExpanding hash_table\n", (table->key_count / table->key_num), table->key_ratio); hash_table_resize(table, table->key_num*2); //exit(0); } hash = HASH(key, key_len); element = hash_table_element_new(); if (!element) { print_info("Cannot allocate memory for element\n"); return -1; // No Memory } if (table->mode == MODE_COPY) { print_info("Adding a key-value pair to the hash table with hash -> %d, in COPY MODE\n", (int)hash); element->key = malloc(key_len); element->value = malloc(value_len); if (element->key && element->value) { memcpy(element->key, key, key_len); memcpy(element->value, value, value_len); } else { if (element->key) { free(element->key); print_info("Cannot allocate memory for value\n"); } if (element->value) { free(element->value); print_info("Cannot allocate memory for key\n"); } free(element); return -1; //No Memory } } else if (table->mode == MODE_VALUEREF) { print_info("Adding a key-value pair to the hash table with hash -> %d, in VALUEREF MODE\n", (int)hash); element->key = malloc(key_len); if (element->key) { memcpy(element->key, key, key_len); } else { print_info("Cannot allocate memory for key\n"); free(element); return -1; //No Memory } element->value = value; } else if (table->mode == MODE_ALLREF) { print_info("Adding a key-value pair to the hash table with hash -> %d, in ALLREF MODE\n", (int)hash); element->key = key; element->value = value; } element->key_len = key_len; element->value_len = value_len; element->next = NULL; // find the key position for chaining if (!table->store_house[hash]) { print_info("No Conflicts adding the first element at %d\n", (int)hash); table->store_house[hash] = element; table->key_count++; } else { hash_table_element_t * temp = table->store_house[hash]; print_info("Conflicts adding element at %d\n", (int)hash); while(temp->next) { while(temp->next && temp->next->key_len!=key_len) { temp = temp->next; } if(temp->next) { if (!memcmp(temp->next->key, key, key_len)) { hash_table_element_t *to_delete = temp->next; print_info("Found Key at hash -> %d\n", (int)hash); temp->next = element; element->next = to_delete->next; hash_table_element_delete(table, to_delete); // since we are replacing values no need to change key_count return 0; } else { temp = temp->next; } } } temp->next = element; table->key_count++; } return 0; }