Пример #1
0
struct int_set_entry *
int_set_random_entry(struct int_set *set,
		     int (*predicate)(struct int_set_entry *entry))
{
	struct int_set_entry *entry;
	uint32_t i = random() % set->size;

	if (set->entries == 0)
		return NULL;

	for (entry = set->table + i; entry != set->table + set->size; entry++) {
		if (entry_is_present(entry) &&
		    (!predicate || predicate(entry))) {
			return entry;
		}
	}

	for (entry = set->table; entry != set->table + i; entry++) {
		if (entry_is_present(entry) &&
		    (!predicate || predicate(entry))) {
			return entry;
		}
	}

	return NULL;
}
Пример #2
0
/**
 * 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_insert(SdbHash *ht, ut32 hash, void *data, SdbListIter *iter) {
	ut32 hash_address;

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

	hash_address = hash % ht->size;
	do {
		SdbHashEntry *entry = ht->table + hash_address;
		ut32 double_hash;

		if (!entry_is_present (entry)) {
			if (entry_is_deleted (entry))
				ht->deleted_entries--;
			entry->hash = hash;
			entry->data = data;
			if (!rehash) entry->iter = ls_append (ht->list, data);
			else entry->iter = iter;
			ht->entries++;
			return 1;
		}

		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 0;
}
Пример #3
0
static void
int_set_rehash(struct int_set *set, int new_size_index)
{
	struct int_set old_set;
	struct int_set_entry *table, *entry;

	if (new_size_index >= ARRAY_SIZE(hash_sizes))
		return;

	table = calloc(hash_sizes[new_size_index].size, sizeof(*set->table));
	if (table == NULL)
		return;

	old_set = *set;

	set->table = table;
	set->size_index = new_size_index;
	set->size = hash_sizes[set->size_index].size;
	set->rehash = hash_sizes[set->size_index].rehash;
	set->max_entries = hash_sizes[set->size_index].max_entries;
	set->entries = 0;
	set->deleted_entries = 0;

	for (entry = old_set.table;
	     entry != old_set.table + old_set.size;
	     entry++) {
		if (entry_is_present(entry)) {
			int_set_add(set, entry->value);
		}
	}

	free(old_set.table);
}
static void hashtable_rehash(ht_t *ht, unsigned int new_size_index)
{
    ht_t old_ht = *ht;
    if(new_size_index >= ARRAY_SIZE(hash_sizes)) return;

    // XXX: This code is redupped! f**k't
    ht->table = (ht_entry_t *) mem_alloc(hash_sizes[new_size_index].size *
        (sizeof(*ht->table) + ht->data_length));
    if(ht->table == NULL) {
        return;
    }

    ht->data_length = old_ht.data_length;
    ht->size_index = new_size_index;
    ht->size = hash_sizes[ht->size_index].size;
    ht->rehash = hash_sizes[ht->size_index].rehash;
    ht->max_entries = hash_sizes[ht->size_index].max_entries;
    ht->entries = 0;
    ht->deleted_entries = 0;

    uint32_t element_size = sizeof(*ht->table) + ht->data_length;
    for (uint32_t idx = 0; idx < old_ht.size; idx++) {
        ht_entry_t *e = (ht_entry_t *)(
            (char *) old_ht.table + idx * element_size);
        if(entry_is_present(e)) {
            ht_insert2(ht, e->hash, e->data, e->length);
        }
    }
    mem_free(old_ht.table);
}
/**
 * Finds a hash table entry with the given key and hash of that key.
 *
 * Returns NULL if no entry is found.  Note that the data pointer may be
 * modified by the user.
 */
static ht_entry_t* hashtable_search(const ht_t *ht, uint64_t hash)
{
    uint64_t double_hash, hash_address;
    if(ht == NULL) {
        return NULL;
    }

    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_free(entry)) {
            return NULL;
        }
        if(entry_is_present(entry) && entry->hash == hash) {
            return entry;
        }
        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);
    return NULL;
}
Пример #6
0
/**
 * Inserts the given value into the set.
 *
 * Note that insertion may rearrange the table on a resize or rehash,
 * so previously found int_set_entry pointers are no longer valid
 * after this function.
 */
struct int_set_entry *
int_set_add(struct int_set *set, uint32_t value)
{
	uint32_t hash_address;
	struct int_set_entry *available_entry = NULL;

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

	hash_address = value % set->size;
	do {
		struct int_set_entry *entry = set->table + hash_address;
		uint32_t double_hash;

		if (!entry_is_present(entry)) {
			if (available_entry == NULL)
				available_entry = entry;
			if (entry_is_free(entry))
				break;
			if (entry_is_deleted(entry)) {
				set->deleted_entries--;
				entry->deleted = 0;
			}
		}

		if (entry->value == value) {
			return entry;
		}

		double_hash = 1 + value % set->rehash;

		hash_address = (hash_address + double_hash) % set->size;
	} while (hash_address != value % set->size);

	if (available_entry) {
		available_entry->value = value;
		available_entry->occupied = 1;
		set->entries++;
		return available_entry;
	}

	/* We could hit here if a required resize failed. An unchecked-malloc
	 * application could ignore this result.
	 */
	return NULL;
}
int ht_next_key(const ht_t *ht, uint32_t *index, uint64_t *hash)
{
    uint32_t element_size = sizeof(*ht->table) + ht->data_length;

    for (uint32_t idx = *index; idx < ht->size; idx++) {
        ht_entry_t *e = (ht_entry_t *)(
            (char *) ht->table + idx * element_size);
        if(entry_is_present(e)) {
            *index = idx + 1;
            *hash = e->hash;
            return 0;
        }
    }
    return -1;
}
Пример #8
0
/**
 * Finds a hash table entry with the given key and hash of that key.
 *
 * Returns NULL if no entry is found.  Note that the data pointer may be
 * modified by the user.
 */
SdbHashEntry* ht_search(SdbHash *ht, ut32 hash) {
	ut32 double_hash, hash_address = hash % ht->size;
	if (ht->entries)
	do {
		SdbHashEntry *entry = ht->table + hash_address;
		if (entry_is_free (entry))
			return NULL;
		if (entry_is_present (entry) && entry->hash == hash)
			return entry;
		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);
	return NULL;
}
Пример #9
0
/**
 * This function is an iterator over the set.
 *
 * Pass in NULL for the first entry, as in the start of a for loop.  Note that
 * an iteration over the table is O(table_size) not O(entries).
 */
struct int_set_entry *
int_set_next_entry(struct int_set *set, struct int_set_entry *entry)
{
	if (entry == NULL)
		entry = set->table;
	else
		entry = entry + 1;

	for (; entry != set->table + set->size; entry++) {
		if (entry_is_present(entry)) {
			return entry;
		}
	}

	return NULL;
}
/**
 * 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;
}
Пример #11
0
/**
 * Finds a hash table entry with the given key and hash of that key.
 *
 * Returns NULL if no entry is found.  Note that the data pointer may be
 * modified by the user.
 */
static RHTE* ht_(search)(RHT *ht, utH hash) {
	utH double_hash, hash_address;
	if (ht == NULL)
		return NULL;
	hash_address = hash % ht->size;
	do {
		RHTE *entry = ht->table + hash_address;
		if (entry_is_free (entry))
			return NULL;
		if (entry_is_present (entry) && entry->hash == hash)
			return entry;
		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);
	return NULL;
}
Пример #12
0
static void ht_(rehash)(RHT *ht, int new_size_index) {
	RHT old_ht = *ht;
	RHTE *e;
	if (new_size_index >= ARRAY_SIZE (hash_sizes))
		return;
	// XXX: This code is redupped! f**k't
	ht->table = calloc (hash_sizes[new_size_index].size, sizeof (*ht->table));
	if (!ht->table)
		return;
	ht->size_index = new_size_index;
	ht->size = hash_sizes[ht->size_index].size;
	ht->rehash = hash_sizes[ht->size_index].rehash;
	ht->max_entries = hash_sizes[ht->size_index].max_entries;
	ht->entries = 0;
	ht->deleted_entries = 0;
	for (e = old_ht.table; e != old_ht.table + old_ht.size; e++) {
		if (entry_is_present (e))
			ht_(insert) (ht, e->hash, e->data);
	}
	free (old_ht.table);
}
Пример #13
0
static void ht_rehash(SdbHash *ht, int new_size_index) {
	SdbHash old_ht = *ht;
	SdbHashEntry *e;
	if (new_size_index >= ARRAY_SIZE (hash_sizes))
		return;
	// XXX: This code is redupped! f**k't
	ht->table = calloc (hash_sizes[new_size_index].size, sizeof (*ht->table));
	if (!ht->table)
		return;
rehash = 1;
	ht->size_index = new_size_index;
	ht->size = hash_sizes[ht->size_index].size;
	ht->rehash = hash_sizes[ht->size_index].rehash;
	ht->max_entries = hash_sizes[ht->size_index].max_entries;
	ht->entries = 0;
	ht->deleted_entries = 0;
	for (e = old_ht.table; e != old_ht.table + old_ht.size; e++) {
		if (entry_is_present (e))
			ht_insert (ht, e->hash, e->data, e->iter);
	}
	free (old_ht.table);
rehash = 0;
}
Пример #14
0
/**
 * Finds a set entry with the given value
 *
 * Returns NULL if no entry is found.
 */
struct int_set_entry *
int_set_search(struct int_set *set, uint32_t value)
{
	uint32_t hash_address;

	hash_address = value % set->size;
	do {
		uint32_t double_hash;

		struct int_set_entry *entry = set->table + hash_address;

		if (entry_is_free(entry)) {
			return NULL;
		} else if (entry_is_present(entry) && entry->value == value) {
			return entry;
		}

		double_hash = 1 + value % set->rehash;

		hash_address = (hash_address + double_hash) % set->size;
	} while (hash_address != value % set->size);

	return NULL;
}