int hashtable_add(HashTable * ht, void * key, void * value){ size_t hash = ht->hf(key); Item * next = ht->table[ hash % ht->size ]; size_t i = 0; while(next){ // Replace data if key is same if(ht->eq( next->key, key )){ next->value = value; return(1); } next = next->next; i++; } next = (Item *)malloc( sizeof(Item) ); next->key = key; next->value = value; next->next = ht->table[ hash % ht->size ]; ht->table[ hash % ht->size ] = next; if(i >= ht->maxCollisions){ hashtable_resize(ht, ht->size + ht->growthFactor); } return(1); }
int hashtable_set(struct hashtable *ht, const void *key, size_t keylen, void *data) { int i, k; ht_size_p_t extend_trigger, extend; struct hashtableitem *new_item; k = hashtable_get(ht, key, keylen, NULL); if (k == HASHTABLE_SUCCESS) { return HASHTABLE_DUPLICATE; } else if (k != HASHTABLE_KEY_NOT_FOUND) { /* some other error; bail */ return k; } extend = ht->table_size_p + ht->table_settings.size_extend; extend_trigger = ht->table_size_p + ht->table_settings.size_extend_trigger; if (extend <= ht->table_settings.size_maximum && extend <= ht_size_lim_p && extend_trigger <= ht_size_lim_p && ht->table_itemcount == (1 << extend_trigger)) { i = hashtable_resize(ht, extend); } else { i = HASHTABLE_SUCCESS; } new_item = malloc(sizeof(struct hashtableitem)); if (new_item == NULL) { return HASHTABLE_OUT_OF_MEMORY; } new_item->key = key; new_item->keylen = keylen; new_item->key_hash = (ht->table_settings.hashfunction)(key, keylen); new_item->data = data; hashtable_insert(ht, new_item); (ht->table_itemcount)++; if (i == HASHTABLE_OUT_OF_MEMORY) { return HASHTABLE_SUCCESS_YET_OUT_OF_MEMORY; } else { return HASHTABLE_SUCCESS; } }
/* Insert or update existing value. */ void hashtable_set(HashTable *table, const char *key, uint32_t len, void *value) { Entry *pEntry; /* 0 = Chain is empty, 1 = Found, 2 = Hit tail without finding. */ int action = 0; uint64_t hash = HASH(key, len); //DBGF("Insert: key %s hashed to %lu.\n", key, hash); /* TODO: Check if table is init'd. */ pEntry = table->entries[hash & table->mask]; /* Search chain. */ while (!action && pEntry) { if (hashtable_entry_test(pEntry, hash, key, len)) { action = 1; } else if (!pEntry->pNext) { /* The current item is the tail. */ action = 2; } else { pEntry = pEntry->pNext; } } if (action != 1) { if (action == 0) { /* Empty chain insert. */ DBG("Set: inserting value (head)."); pEntry = malloc(sizeof(Entry)); table->entries[hash & table->mask] = pEntry; pEntry->pPrev = NULL; } else { /* Non-empty chain insert. */ DBG("Set: inserting value."); pEntry->pNext = malloc(sizeof(Entry)); /* Point new entry back at tail. */ pEntry->pNext->pPrev = pEntry; pEntry = pEntry->pNext; } pEntry->pNext = NULL; pEntry->hash = hash; pEntry->key = malloc(len * sizeof(char)); pEntry->key_len = len; memcpy(pEntry->key, key, len * sizeof(char)); DBGF("Set: Allocated %u bytes for key %s.\n", len, key); table->count++; } else { DBG("Set: updating value."); } /* Set value. */ pEntry->value = value; if (table->count > table->size) { hashtable_resize(table); } }
/* Create a new hashtable which is initially configured to hold up to initial_size buckets. The table will be dynamically resized if more buckets are needed. */ struct hashtable * hashtable_new(int initial_size) { struct hashtable *table; table = (struct hashtable *)allocate(sizeof(struct hashtable)); table->size = 0; table->count = 0; table->buckets = NULL; hashtable_resize(table, initial_size); if (table->buckets == NULL) { /* XXX error processing */ free(table); return NULL; } return table; }
/** * Assign a value to the given key in the table. */ void hashtable_set(hashtable* t, char* key, void* value) { int index = hashtable_find_slot(t, key); if (t->body[index].key != NULL) { /* Entry exists; update it. */ t->body[index].value = value; } else { t->size++; /* Create a new entry */ if ((float)t->size / t->capacity > 0.8) { /* Resize the hash table */ hashtable_resize(t, t->capacity * 2); index = hashtable_find_slot(t, key); } t->body[index].key = key; t->body[index].value = value; } }
int main(int argc, char* argv[]) { hashtable_t* table = NULL; hashnode_t* node = NULL; int i; int size; table = (hashtable_t*)malloc(sizeof(hashtable_t)); assert(table != NULL); size = 50; hashtable_init(table, size); for (i = 0; i < size; i++) { assert(table->buckets[i] == NULL); } assert(table->size == 50); hashtable_insert(table, "abcd"); node = hashtable_find(table, "abcd"); assert(node != NULL); hashtable_insert(table, "bcde"); node = hashtable_find(table, "bcde"); assert(node != NULL); size = 80; hashtable_resize(&table, size); assert(table->size == size); node = hashtable_find(table, "abcd"); assert(node != NULL); node = hashtable_find(table, "bcde"); assert(node != NULL); hashtable_clear(table); free(table); return 0; }
/* Store a value in a hashtable, associated with a given key. A copy of the key is made. The previous association with this key is returned, or NULL if this is a new key for this hashtable. Note that you can specify NULL values to be stored, but you cannot remove a key association. This would require searching for following buckets that might have to be moved to this one to restore table consistancy. Since I don't see the need to delete at this time, I'm not worrying about it. */ void * hashtable_put(struct hashtable *table, char *key, void *value) { void *old; int hash = hash_string(key); struct hashtable_bucket *bucket = hashtable_find_bucket(table->buckets, table->size, hash, key); if (bucket->key == NULL) { bucket->hash = hash; bucket->key = copy_string(key); bucket->value = value; table->count++; if (((float)table->count) / (float)(table->size) > RESIDENCY) { hashtable_resize(table, table->size+1); } return NULL; } else { old = bucket->value; bucket->value = value; return old; } }
int hashtable_new_custom(struct hashtable *ht, const struct hashtablesettings *s) { int r; r = hashtable_verify_settings(s); if (r != HASHTABLE_SUCCESS) { return r; } ht->table = NULL; ht->table_size_p = 0; ht->table_size = 0; ht->table_itemcount = 0; ht->table_mask = 0; ht->table_settings = *s; /* If this fails now it won't have allocated any memory * (this is not true for its later use in hashtable_set) */ return hashtable_resize(ht, ht->table_settings.size_initial); }
uint deps_add_evr(struct deps *deps, const char *name, int flags, uint epoch, const char *version, const char *release) { uint i, iter = 0, hash, size = array_get_size(&deps->names), ver, rel, nam; nam = strings_add(deps->strings, name); ver = strings_add(deps->strings, version != NULL ? version : ""); rel = strings_add(deps->strings, release != NULL ? release : ""); if (hashtable_resize(&deps->hashtable)) { for (i = 0; i < size; i++) { hash = dephash(array_get(&deps->names, i)); hashtable_add(&deps->hashtable, i, hash); } } hash = dephash(nam); while ((i = hashtable_find(&deps->hashtable, hash, &iter)) != -1) if (array_get(&deps->names, i) == nam && array_get(&deps->epochs, i) == epoch && array_get(&deps->vers, i) == ver && array_get(&deps->rels, i) == rel && array_get(&deps->flags, i) == flags) break; if (i != -1) /* already stored */ return i; i = size; array_set(&deps->names, i, nam); array_set(&deps->epochs, i, epoch); array_set(&deps->vers, i, ver); array_set(&deps->rels, i, rel); array_set(&deps->flags, i, flags); hashtable_add_dir(&deps->hashtable, i, hash, iter); return i; }
void test_basic(dict *dct, const struct key_info *keys, const unsigned nkeys, const struct closest_lookup_info *cl_infos, unsigned n_cl_infos) { dict_itor *itor = dict_itor_new(dct); CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned i = 0; i < nkeys; ++i) { bool inserted = false; void **datum_location = dict_insert(dct, keys[i].key, &inserted); CU_ASSERT_TRUE(inserted); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_PTR_NULL(*datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned j = 0; j <= i; ++j) test_search(dct, itor, keys[j].key, keys[j].value); for (unsigned j = i + 1; j < nkeys; ++j) test_search(dct, itor, keys[j].key, NULL); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); if (dct->_vtable->insert == (dict_insert_func)hashtable_insert || dct->_vtable->insert == (dict_insert_func)hashtable2_insert) { /* Verify that hashtable_resize works as expected. */ dict *clone = dict_clone(dct, NULL); CU_ASSERT_TRUE(dict_verify(dct)); if (dct->_vtable->insert == (dict_insert_func)hashtable_insert) { CU_ASSERT_TRUE(hashtable_resize(dict_private(clone), 3)); } else { CU_ASSERT_TRUE(hashtable2_resize(dict_private(clone), 3)); } CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned j = 0; j < nkeys; ++j) test_search(clone, NULL, keys[j].key, keys[j].value); dict_free(clone); } if (dct->_vtable->clone) { dict *clone = dict_clone(dct, NULL); CU_ASSERT_PTR_NOT_NULL(clone); CU_ASSERT_TRUE(dict_verify(clone)); CU_ASSERT_EQUAL(dict_count(clone), nkeys); for (unsigned i = 0; i < nkeys; ++i) { test_search(clone, itor, keys[i].key, keys[i].value); } for (unsigned i = 0; i < nkeys; ++i) { CU_ASSERT_TRUE(dict_remove(clone, keys[i].key)); } dict_free(clone); } for (unsigned i = 0; i < nkeys; ++i) test_search(dct, itor, keys[i].key, keys[i].value); for (unsigned i = 0; i < nkeys; ++i) { bool inserted = false; void **datum_location = dict_insert(dct, keys[i].key, &inserted); CU_ASSERT_FALSE(inserted); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_EQUAL(*datum_location, keys[i].value); CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); CU_ASSERT_PTR_NOT_NULL(itor); char *last_key = NULL; unsigned n = 0; for (dict_itor_first(itor); dict_itor_valid(itor); dict_itor_next(itor)) { CU_ASSERT_PTR_NOT_NULL(dict_itor_key(itor)); CU_ASSERT_PTR_NOT_NULL(dict_itor_data(itor)); CU_ASSERT_PTR_NOT_NULL(*dict_itor_data(itor)); char *key = dict_itor_key(itor); bool key_matched = false; for (unsigned i = 0; i < nkeys; ++i) { if (keys[i].key == key) { CU_ASSERT_EQUAL(*dict_itor_data(itor), keys[i].value); key_matched = true; break; } } CU_ASSERT_TRUE(key_matched); if (dct->_vtable->insert != (dict_insert_func)hashtable_insert && dct->_vtable->insert != (dict_insert_func)hashtable2_insert) { if (last_key) { CU_ASSERT_TRUE(strcmp(last_key, dict_itor_key(itor)) < 0); } last_key = dict_itor_key(itor); } ++n; } CU_ASSERT_EQUAL(n, nkeys); last_key = NULL; n = 0; for (dict_itor_last(itor); dict_itor_valid(itor); dict_itor_prev(itor)) { CU_ASSERT_PTR_NOT_NULL(dict_itor_key(itor)); CU_ASSERT_PTR_NOT_NULL(dict_itor_data(itor)); CU_ASSERT_PTR_NOT_NULL(*dict_itor_data(itor)); char *key = dict_itor_key(itor); bool key_matched = false; for (unsigned i = 0; i < nkeys; ++i) { if (keys[i].key == key) { CU_ASSERT_EQUAL(*dict_itor_data(itor), keys[i].value); key_matched = true; break; } } CU_ASSERT_TRUE(key_matched); if (dct->_vtable->insert != (dict_insert_func)hashtable_insert && dct->_vtable->insert != (dict_insert_func)hashtable2_insert) { if (last_key) { CU_ASSERT_TRUE(strcmp(last_key, dict_itor_key(itor)) > 0); } last_key = dict_itor_key(itor); } ++n; } CU_ASSERT_EQUAL(n, nkeys); for (unsigned i = 0; i < nkeys; ++i) { bool inserted = false; void **datum_location = dict_insert(dct, keys[i].key, &inserted); CU_ASSERT_FALSE(inserted); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_PTR_NOT_NULL(*datum_location); *datum_location = keys[i].alt; CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); for (unsigned i = 0; i < nkeys; ++i) test_search(dct, itor, keys[i].key, keys[i].alt); for (unsigned i = 0; i < nkeys; ++i) { test_search(dct, itor, keys[i].key, keys[i].alt); CU_ASSERT_TRUE(dict_remove(dct, keys[i].key)); CU_ASSERT_TRUE(dict_verify(dct)); CU_ASSERT_EQUAL(dict_remove(dct, keys[i].key), false); for (unsigned j = 0; j <= i; ++j) { test_search(dct, itor, keys[j].key, NULL); } for (unsigned j = i + 1; j < nkeys; ++j) { test_search(dct, itor, keys[j].key, keys[j].alt); } } for (unsigned i = 0; i < nkeys; ++i) { bool inserted = false; void **datum_location = dict_insert(dct, keys[i].key, &inserted); CU_ASSERT_TRUE(inserted); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_PTR_NULL(*datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); CU_ASSERT_EQUAL(dict_clear(dct), nkeys); for (unsigned i = 0; i < nkeys; ++i) { bool inserted = false; void **datum_location = dict_insert(dct, keys[i].key, &inserted); CU_ASSERT_TRUE(inserted); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_PTR_NULL(*datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); } test_closest_lookup(dct, cl_infos, n_cl_infos); dict_itor_free(itor); CU_ASSERT_EQUAL(dict_count(dct), nkeys); CU_ASSERT_EQUAL(dict_free(dct), nkeys); }
void hashtable_set(hashtable_t* input, const void* key, size_t key_length, void* value) { //fprintf(stderr,"store(%s,%p)\n",key,value); uint32_t hashcode=_hashtable_function(key, key_length); uint32_t bucket=hashcode%input->size; hashelement_t* element=input->buckets[bucket]; #ifdef HASHTABLE_REORDER_ON_ACCESS hashelement_t* previous_element=NULL; #endif #ifdef HASHTABLE_GATHER_STATS unsigned int num_hits=1; #endif while(element!=NULL) { if(element->key_length==key_length && memcmp(element->key,key,key_length)==0) { element->value=value; #ifdef HASHTABLE_GATHER_STATS input->num_hits_per_access+=num_hits; input->num_accesses++; #endif #ifdef HASHTABLE_REORDER_ON_ACCESS if(previous_element!=NULL) { previous_element->next_in_bucket=element->next_in_bucket; element->next_in_bucket=input->buckets[bucket]; input->buckets[bucket]=element; } #endif return; } #ifdef HASHTABLE_GATHER_STATS num_hits++; #endif #ifdef HASHTABLE_REORDER_ON_ACCESS previous_element=element; #endif element=element->next_in_bucket; } #ifdef HASHTABLE_GATHER_STATS input->num_hits_per_access+=num_hits; input->num_accesses++; #endif element = (hashelement_t*)MALLOC(sizeof(hashelement_t)); element->hashcode=hashcode; #ifdef HASHTABLE_CENTRALIZE_KEYS if(input==_hashtable_key_repository) { element->key=key; } else { if(_hashtable_key_repository==NULL) _hashtable_key_repository=hashtable_new(); char* repository_key=hashtable_fetch(_hashtable_key_repository, key, key_length); if(repository_key==NULL) { repository_key=MALLOC(key_length); memcpy(repository_key,key,key_length); hashtable_store(_hashtable_key_repository, repository_key, key_length, repository_key); } element->key=repository_key; } #else element->key=MALLOC(key_length); memcpy(element->key,key,key_length); #endif element->key_length=key_length; element->value=value; element->next_in_bucket=input->buckets[bucket]; input->buckets[bucket]=element; input->length++; #ifdef HASHTABLE_INCREASE_SIZE if(input->length/input->size>input->max_average_collisions)hashtable_resize(input, (size_t)(input->size*(input->resize_factor)+1));//+input->size); #endif }
void test_basic(dict *dct, const struct key_info *keys, const unsigned nkeys) { CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned i = 0; i < nkeys; ++i) { void **datum_location = NULL; CU_ASSERT_TRUE(dict_insert(dct, keys[i].key, &datum_location)); CU_ASSERT_PTR_NOT_NULL(datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned j = 0; j <= i; ++j) CU_ASSERT_EQUAL(dict_search(dct, keys[j].key), keys[j].value); for (unsigned j = i + 1; j < nkeys; ++j) CU_ASSERT_EQUAL(dict_search(dct, keys[j].key), NULL); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); if (dct->_vtable->insert == (dict_insert_func)hashtable_insert) { /* Verify that hashtable_resize works as expected. */ dict *clone = dict_clone(dct, NULL); CU_ASSERT_TRUE(dict_verify(dct)); CU_ASSERT_TRUE(hashtable_resize(dict_private(clone), 3)); CU_ASSERT_TRUE(dict_verify(dct)); for (unsigned j = 0; j < nkeys; ++j) CU_ASSERT_EQUAL(dict_search(clone, keys[j].key), keys[j].value); dict_free(clone); } if (dct->_vtable->clone) { dict *clone = dict_clone(dct, NULL); CU_ASSERT_PTR_NOT_NULL(clone); CU_ASSERT_TRUE(dict_verify(clone)); CU_ASSERT_EQUAL(dict_count(clone), nkeys); for (unsigned i = 0; i < nkeys; ++i) { CU_ASSERT_EQUAL(dict_search(clone, keys[i].key), keys[i].value); } for (unsigned i = 0; i < nkeys; ++i) { CU_ASSERT_TRUE(dict_remove(clone, keys[i].key)); } dict_free(clone); } for (unsigned i = 0; i < nkeys; ++i) CU_ASSERT_EQUAL(dict_search(dct, keys[i].key), keys[i].value); for (unsigned i = 0; i < nkeys; ++i) { void **datum_location = NULL; CU_ASSERT_FALSE(dict_insert(dct, keys[i].key, &datum_location)); CU_ASSERT_PTR_NOT_NULL(datum_location); CU_ASSERT_EQUAL(*datum_location, keys[i].value); CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); dict_itor *itor = dict_itor_new(dct); CU_ASSERT_PTR_NOT_NULL(itor); char *last_key = NULL; unsigned n = 0; for (dict_itor_first(itor); dict_itor_valid(itor); dict_itor_next(itor)) { CU_ASSERT_PTR_NOT_NULL(dict_itor_key(itor)); CU_ASSERT_PTR_NOT_NULL(dict_itor_data(itor)); ++n; if (dct->_vtable->insert != (dict_insert_func)hashtable_insert) { if (last_key) { CU_ASSERT_TRUE(strcmp(last_key, dict_itor_key(itor)) < 0); } last_key = dict_itor_key(itor); } } CU_ASSERT_EQUAL(n, nkeys); last_key = NULL; n = 0; for (dict_itor_last(itor); dict_itor_valid(itor); dict_itor_prev(itor)) { CU_ASSERT_PTR_NOT_NULL(dict_itor_key(itor)); CU_ASSERT_PTR_NOT_NULL(dict_itor_data(itor)); ++n; if (dct->_vtable->insert != (dict_insert_func)hashtable_insert) { if (last_key) { CU_ASSERT_TRUE(strcmp(last_key, dict_itor_key(itor)) > 0); } last_key = dict_itor_key(itor); } } CU_ASSERT_EQUAL(n, nkeys); dict_itor_free(itor); for (unsigned i = 0; i < nkeys; ++i) { void **datum_location = NULL; CU_ASSERT_FALSE(dict_insert(dct, keys[i].key, &datum_location)); CU_ASSERT_PTR_NOT_NULL(datum_location); *datum_location = keys[i].alt; CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); for (unsigned i = 0; i < nkeys; ++i) CU_ASSERT_EQUAL(dict_search(dct, keys[i].key), keys[i].alt); for (unsigned i = 0; i < nkeys; ++i) { CU_ASSERT_EQUAL(dict_search(dct, keys[i].key), keys[i].alt); CU_ASSERT_TRUE(dict_remove(dct, keys[i].key)); CU_ASSERT_TRUE(dict_verify(dct)); CU_ASSERT_EQUAL(dict_remove(dct, keys[i].key), false); for (unsigned j = 0; j <= i; ++j) { CU_ASSERT_EQUAL(dict_search(dct, keys[j].key), NULL); } for (unsigned j = i + 1; j < nkeys; ++j) { CU_ASSERT_EQUAL(dict_search(dct, keys[j].key), keys[j].alt); } } for (unsigned i = 0; i < nkeys; ++i) { void **datum_location = NULL; CU_ASSERT_TRUE(dict_insert(dct, keys[i].key, &datum_location)); CU_ASSERT_PTR_NOT_NULL(datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); CU_ASSERT_EQUAL(dict_clear(dct), nkeys); for (unsigned i = 0; i < nkeys; ++i) { void **datum_location = NULL; CU_ASSERT_TRUE(dict_insert(dct, keys[i].key, &datum_location)); CU_ASSERT_PTR_NOT_NULL(datum_location); *datum_location = keys[i].value; CU_ASSERT_TRUE(dict_verify(dct)); } CU_ASSERT_EQUAL(dict_count(dct), nkeys); CU_ASSERT_EQUAL(dict_free(dct), nkeys); }