Пример #1
0
void hash_resize(struct hashtable *table, int buckets)
{
    struct entry **new_buckets;
    if ((new_buckets = (struct entry **)malloc( sizeof(struct entry *) * buckets )) == NULL)
        return;

    // Set all buckets to NULL (empty linked lists)
    for (int i = 0; i < buckets; i++)
        (new_buckets)[i] = NULL;

    // Iterate over all existing buckets
    for (int i = 0; i < table->num_buckets; i++)
    {   
        // Iterate over each entry in the existing bucket,
        // rehashing it and adding it to a bucket (or creating
        // a bucket) in the new list of buckets.
        struct entry *entry = table->buckets[i];
        while (entry != NULL)
        {
            struct entry *next = entry->next;
            int new_index = bucket_index(entry->key, buckets);

            add_entry(&(new_buckets[new_index]), entry);

            // Get next entry
            entry = next;
        }
    }

    // Free the buckets!
    free(table->buckets);

    table->buckets = new_buckets;
    table->num_buckets = buckets;
}
Пример #2
0
bool hash_insert(struct hashtable *table, const char *key, const void *value)
{
    // Find relevant bucket and keep index (used to find reference to bucket in buckets array)
    int index            = bucket_index(key, table->num_buckets);
    struct entry *bucket = table->buckets[index];

    // Check the table for an existing entry (bucket is first entry, as it
    // represents the head of the linked list)
    for (struct entry *entry = bucket; entry != NULL; entry = entry->next)
    {
        if (!strcmp(entry->key, key))
        {
            entry->value = value;
            return true;
        }
    }

    // Ensure that the table will not exceed the maximum load factor
    // with the new number of entries; if it will, resize it to double the
    // number of buckets, and set the new index/bucket.
    if ( (float)(table->num_entries + 1) / table->num_buckets > MAX_LOAD_FACTOR )
    {
        hash_resize(table, table->num_buckets * 2);

        index = bucket_index(key, table->num_buckets);
        bucket = table->buckets[index];
    }

    // Create the new entry to add to the table
    struct entry *new_entry;

    if ((new_entry = (struct entry *)malloc( sizeof(struct entry) )) == NULL)
        return false;

    new_entry->key = key;
    new_entry->value = value;
    new_entry->next = NULL;

    add_entry(&(table->buckets[index]), new_entry);

    // Increment the number of table entries
    ++table->num_entries;
    return true;
}
Пример #3
0
void*
ht_find(
    struct ht const* ht,
    void const* cmp,
    struct r_set_cfg const* cfg
) {
    r_hash hash = cfg->hashf(cmp);
    size_t i = bucket_index(ht, hash);
    ht_dbg("Finding element with hash %zi in bucket %zi", hash, i);
    return avl_find(&ht->buckets[i].avl, hash, cmp, cfg);
}
Пример #4
0
int
ht_insert(
    struct ht* ht,
    void* data,
    struct r_set_cfg const* cfg
) {
    r_hash hash = cfg->hashf(data);

    // this is equivalent to hash / 2^(BITCOUNT(hash) - ht->sizeexp) due to the
    // right shift
    size_t i = bucket_index(ht, hash);
    ht_dbg("Adding element %p with hash %zi in bucket %zi", data, hash, i);
    return avl_insert(&ht->buckets[i].avl, hash, data, cfg);
}
Пример #5
0
const void *hash_get(struct hashtable *table, const char *key)
{
    int index = bucket_index(key, table->num_buckets);
    struct entry *bucket = table->buckets[index];

    // If bucket exists, traverse the list
    if (bucket != NULL)
    {
        for (struct entry *entry = bucket; entry != NULL; entry = entry->next)
        {
            // Check to see if entry key matches
            if (!strcmp(entry->key, key))
                return entry->value;
        }
    }

    return NULL;
}
Пример #6
0
const void *hash_delete(struct hashtable *table, const char *key)
{ 
    int index = bucket_index(key, table->num_buckets);
    struct entry *bucket = table->buckets[index];

    // Stop if bucket doesn't exist
    if (!bucket)
        return NULL;

    struct entry *prev = NULL;
    for (struct entry *entry = bucket; entry != NULL; prev = entry, entry = entry->next)
    {
        // Find element with same key in bucket
        if (!strcmp(entry->key, key))
        {
            const void *value = entry->value;

            // Remove from linked list chain, if it was not the head.
            // Otherwise, make the next element the head (which may be NULL).
            if (prev != NULL)
                prev->next = entry->next;
            else
                table->buckets[index] = entry->next; // Will set to NULL if it is the only element

            // Free the entry (it was malloc'd upon insertion)
            free(entry);

            // Decrement number of entries
            table->num_entries--;

            return value;
        }
    }

    return NULL;

}
Пример #7
0
void test_bucket_index() {
    uint64_t digest = 11538222250332604846LLU;
    sassert(5 == bucket_index(digest, 3));
    sassert(1 == bucket_index(digest, 1));
    sassert(160 == bucket_index(digest, 8));
}