示例#1
0
int main(void) {
  size_t initcap = 10;
  HashTable *newht, *ht = hashtable_new(initcap);

  if (!ht)
    testfail("Could not create hash table!");

  if (ht->items != 0)
    testfail("New hash table should be empty, instead has size %lu", ht->items);

  hashtable_put(ht, "Elvis", "Presley");
  if (ht->items != 1)
    testfail("Hash table should have size 1 after put instead has size %lu", ht->items);
  expect_to_get(ht, "Elvis", "Presley");

  hashtable_put(ht, "Elvis", "Costello");
  if (ht->items != 1)
    testfail("Hash table should have remained size 1 after put instead has size %lu", ht->items);
  expect_to_get(ht, "Elvis", "Costello");

  hashtable_put(ht, "Janis", "Joplin");
  if (ht->items != 2)
    testfail("Hash table should have grown to size 2 after put instead has size %lu", ht->items);
  expect_to_get(ht, "Janis", "Joplin");

  newht = hashtable_rehash(ht, 100);
  if (newht != ht)
    testfail("Expected hashtable instance to be the same; should not have changed!");

  newht = hashtable_rehash(ht, 0);
  if (newht == ht)
    testfail("Expected hashtable instance to be the different; should have changed!");

  ht = newht;

  if (newht->capacity <= initcap)
    testfail("Expected new hashtable to be larger than %lu, instead got %lu", initcap, newht->capacity);

  if (newht->items != 2)
    testfail("Expected 2 items in new hash table!");

  expect_to_get(ht, "Elvis", "Costello");
  expect_to_get(ht, "Janis", "Joplin");

  hashtable_destroy(ht);

  return 0;
}
示例#2
0
static int
_hashtable_pop_entry(_Py_hashtable_t *ht, const void *key, void *data, size_t data_size)
{
    Py_uhash_t key_hash;
    size_t index;
    _Py_hashtable_entry_t *entry, *previous;

    key_hash = ht->hash_func(key);
    index = key_hash & (ht->num_buckets - 1);

    previous = NULL;
    for (entry = TABLE_HEAD(ht, index); entry != NULL; entry = ENTRY_NEXT(entry)) {
        if (entry->key_hash == key_hash && ht->compare_func(key, entry))
            break;
        previous = entry;
    }

    if (entry == NULL)
        return 0;

    _Py_slist_remove(&ht->buckets[index], (_Py_slist_item_t *)previous,
                     (_Py_slist_item_t *)entry);
    ht->entries--;

    if (data != NULL)
        _Py_HASHTABLE_ENTRY_READ_DATA(ht, data, data_size, entry);
    ht->alloc.free(entry);

    if ((float)ht->entries / (float)ht->num_buckets < HASHTABLE_LOW)
        hashtable_rehash(ht);
    return 1;
}
/**
 * Inserts the data with the given hash into the table.
 *
 * Note that insertion may rearrange the table on a resize or rehash,
 * so previously found hash_entries are no longer valid after this function.
 */
int ht_insert2(ht_t *ht, uint64_t hash, void *data, uint32_t length)
{
    uint64_t hash_address;

    if(length == 0 || length > ht->data_length) {
        return -1;
    }

    if(ht->entries >= ht->max_entries) {
        hashtable_rehash(ht, ht->size_index + 1);
    }
    else if(ht->deleted_entries + ht->entries >= ht->max_entries) {
        hashtable_rehash(ht, ht->size_index);
    }

    uint32_t element_size = sizeof(*ht->table) + ht->data_length;

    hash_address = hash % ht->size;
    do {
        ht_entry_t *entry = (ht_entry_t *)(
            (char *) ht->table + hash_address * element_size);

        if(!entry_is_present(entry)) {
            if(entry_is_deleted(entry)) {
                ht->deleted_entries--;
            }
            entry->hash = hash;
            entry->length = length;
            memcpy(entry->data, data, length);
            ht->entries++;
            return 0;
        }

        uint64_t double_hash = hash % ht->rehash;
        if(double_hash == 0) {
            double_hash = 1;
        }
        hash_address = (hash_address + double_hash) % ht->size;
    } while (hash_address != hash % ht->size);

    /* We could hit here if a required resize failed. An unchecked-malloc
     * application could ignore this result.
     */
    return -1;
}
示例#4
0
void
_Py_hashtable_clear(_Py_hashtable_t *ht)
{
    _Py_hashtable_entry_t *entry, *next;
    size_t i;

    for (i=0; i < ht->num_buckets; i++) {
        for (entry = TABLE_HEAD(ht, i); entry != NULL; entry = next) {
            next = ENTRY_NEXT(entry);
            if (ht->free_data_func)
                ht->free_data_func(_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry));
            ht->alloc.free(entry);
        }
        _Py_slist_init(&ht->buckets[i]);
    }
    ht->entries = 0;
    hashtable_rehash(ht);
}
示例#5
0
/* Add a new entry to the hash. The key must not be present in the hash table.
   Return 0 on success, -1 on memory error. */
int
_Py_hashtable_set(_Py_hashtable_t *ht, const void *key,
                  void *data, size_t data_size)
{
    Py_uhash_t key_hash;
    size_t index;
    _Py_hashtable_entry_t *entry;

    assert(data != NULL || data_size == 0);
#ifndef NDEBUG
    /* Don't write the assertion on a single line because it is interesting
       to know the duplicated entry if the assertion failed. The entry can
       be read using a debugger. */
    entry = _Py_hashtable_get_entry(ht, key);
    assert(entry == NULL);
#endif

    key_hash = ht->hash_func(key);
    index = key_hash & (ht->num_buckets - 1);

    entry = ht->alloc.malloc(HASHTABLE_ITEM_SIZE(ht));
    if (entry == NULL) {
        /* memory allocation failed */
        return -1;
    }

    entry->key = (void *)key;
    entry->key_hash = key_hash;

    assert(data_size == ht->data_size);
    memcpy(_Py_HASHTABLE_ENTRY_DATA(entry), data, data_size);

    _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry);
    ht->entries++;

    if ((float)ht->entries / (float)ht->num_buckets > HASHTABLE_HIGH)
        hashtable_rehash(ht);
    return 0;
}