remove old hash.[ch] implementation
Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
419a597f64
commit
efc684245b
@ -1,52 +0,0 @@
|
||||
hash API
|
||||
========
|
||||
|
||||
The hash API is a collection of simple hash table functions. Users are expected
|
||||
to implement their own hashing.
|
||||
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct hash_table`::
|
||||
|
||||
The hash table structure. The `array` member points to the hash table
|
||||
entries. The `size` member counts the total number of valid and invalid
|
||||
entries in the table. The `nr` member keeps track of the number of
|
||||
valid entries.
|
||||
|
||||
`struct hash_table_entry`::
|
||||
|
||||
An opaque structure representing an entry in the hash table. The `hash`
|
||||
member is the entry's hash key and the `ptr` member is the entry's
|
||||
value.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`init_hash`::
|
||||
|
||||
Initialize the hash table.
|
||||
|
||||
`free_hash`::
|
||||
|
||||
Release memory associated with the hash table.
|
||||
|
||||
`insert_hash`::
|
||||
|
||||
Insert a pointer into the hash table. If an entry with that hash
|
||||
already exists, a pointer to the existing entry's value is returned.
|
||||
Otherwise NULL is returned. This allows callers to implement
|
||||
chaining, etc.
|
||||
|
||||
`lookup_hash`::
|
||||
|
||||
Lookup an entry in the hash table. If an entry with that hash exists
|
||||
the entry's value is returned. Otherwise NULL is returned.
|
||||
|
||||
`for_each_hash`::
|
||||
|
||||
Call a function for each entry in the hash table. The function is
|
||||
expected to take the entry's value as its only argument and return an
|
||||
int. If the function returns a negative int the loop is aborted
|
||||
immediately. Otherwise, the return value is accumulated and the sum
|
||||
returned upon completion of the loop.
|
2
Makefile
2
Makefile
@ -677,7 +677,6 @@ LIB_H += git-compat-util.h
|
||||
LIB_H += gpg-interface.h
|
||||
LIB_H += graph.h
|
||||
LIB_H += grep.h
|
||||
LIB_H += hash.h
|
||||
LIB_H += hashmap.h
|
||||
LIB_H += help.h
|
||||
LIB_H += http.h
|
||||
@ -809,7 +808,6 @@ LIB_OBJS += gettext.o
|
||||
LIB_OBJS += gpg-interface.o
|
||||
LIB_OBJS += graph.o
|
||||
LIB_OBJS += grep.o
|
||||
LIB_OBJS += hash.o
|
||||
LIB_OBJS += hashmap.o
|
||||
LIB_OBJS += help.o
|
||||
LIB_OBJS += hex.o
|
||||
|
1
cache.h
1
cache.h
@ -3,7 +3,6 @@
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "hash.h"
|
||||
#include "hashmap.h"
|
||||
#include "advice.h"
|
||||
#include "gettext.h"
|
||||
|
110
hash.c
110
hash.c
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Some generic hashing helpers.
|
||||
*/
|
||||
#include "cache.h"
|
||||
#include "hash.h"
|
||||
|
||||
/*
|
||||
* Look up a hash entry in the hash table. Return the pointer to
|
||||
* the existing entry, or the empty slot if none existed. The caller
|
||||
* can then look at the (*ptr) to see whether it existed or not.
|
||||
*/
|
||||
static struct hash_table_entry *lookup_hash_entry(unsigned int hash, const struct hash_table *table)
|
||||
{
|
||||
unsigned int size = table->size, nr = hash % size;
|
||||
struct hash_table_entry *array = table->array;
|
||||
|
||||
while (array[nr].ptr) {
|
||||
if (array[nr].hash == hash)
|
||||
break;
|
||||
nr++;
|
||||
if (nr >= size)
|
||||
nr = 0;
|
||||
}
|
||||
return array + nr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Insert a new hash entry pointer into the table.
|
||||
*
|
||||
* If that hash entry already existed, return the pointer to
|
||||
* the existing entry (and the caller can create a list of the
|
||||
* pointers or do anything else). If it didn't exist, return
|
||||
* NULL (and the caller knows the pointer has been inserted).
|
||||
*/
|
||||
static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table)
|
||||
{
|
||||
struct hash_table_entry *entry = lookup_hash_entry(hash, table);
|
||||
|
||||
if (!entry->ptr) {
|
||||
entry->ptr = ptr;
|
||||
entry->hash = hash;
|
||||
table->nr++;
|
||||
return NULL;
|
||||
}
|
||||
return &entry->ptr;
|
||||
}
|
||||
|
||||
static void grow_hash_table(struct hash_table *table)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int old_size = table->size, new_size;
|
||||
struct hash_table_entry *old_array = table->array, *new_array;
|
||||
|
||||
new_size = alloc_nr(old_size);
|
||||
new_array = xcalloc(sizeof(struct hash_table_entry), new_size);
|
||||
table->size = new_size;
|
||||
table->array = new_array;
|
||||
table->nr = 0;
|
||||
for (i = 0; i < old_size; i++) {
|
||||
unsigned int hash = old_array[i].hash;
|
||||
void *ptr = old_array[i].ptr;
|
||||
if (ptr)
|
||||
insert_hash_entry(hash, ptr, table);
|
||||
}
|
||||
free(old_array);
|
||||
}
|
||||
|
||||
void *lookup_hash(unsigned int hash, const struct hash_table *table)
|
||||
{
|
||||
if (!table->array)
|
||||
return NULL;
|
||||
return lookup_hash_entry(hash, table)->ptr;
|
||||
}
|
||||
|
||||
void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
|
||||
{
|
||||
unsigned int nr = table->nr;
|
||||
if (nr >= table->size/2)
|
||||
grow_hash_table(table);
|
||||
return insert_hash_entry(hash, ptr, table);
|
||||
}
|
||||
|
||||
int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data)
|
||||
{
|
||||
int sum = 0;
|
||||
unsigned int i;
|
||||
unsigned int size = table->size;
|
||||
struct hash_table_entry *array = table->array;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
void *ptr = array->ptr;
|
||||
array++;
|
||||
if (ptr) {
|
||||
int val = fn(ptr, data);
|
||||
if (val < 0)
|
||||
return val;
|
||||
sum += val;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void free_hash(struct hash_table *table)
|
||||
{
|
||||
free(table->array);
|
||||
table->array = NULL;
|
||||
table->size = 0;
|
||||
table->nr = 0;
|
||||
}
|
50
hash.h
50
hash.h
@ -1,50 +0,0 @@
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
/*
|
||||
* These are some simple generic hash table helper functions.
|
||||
* Not necessarily suitable for all users, but good for things
|
||||
* where you want to just keep track of a list of things, and
|
||||
* have a good hash to use on them.
|
||||
*
|
||||
* It keeps the hash table at roughly 50-75% free, so the memory
|
||||
* cost of the hash table itself is roughly
|
||||
*
|
||||
* 3 * 2*sizeof(void *) * nr_of_objects
|
||||
*
|
||||
* bytes.
|
||||
*
|
||||
* FIXME: on 64-bit architectures, we waste memory. It would be
|
||||
* good to have just 32-bit pointers, requiring a special allocator
|
||||
* for hashed entries or something.
|
||||
*/
|
||||
struct hash_table_entry {
|
||||
unsigned int hash;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
struct hash_table {
|
||||
unsigned int size, nr;
|
||||
struct hash_table_entry *array;
|
||||
};
|
||||
|
||||
extern void *lookup_hash(unsigned int hash, const struct hash_table *table);
|
||||
extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
|
||||
extern int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data);
|
||||
extern void free_hash(struct hash_table *table);
|
||||
|
||||
static inline void init_hash(struct hash_table *table)
|
||||
{
|
||||
table->size = 0;
|
||||
table->nr = 0;
|
||||
table->array = NULL;
|
||||
}
|
||||
|
||||
static inline void preallocate_hash(struct hash_table *table, unsigned int elts)
|
||||
{
|
||||
assert(table->size == 0 && table->nr == 0 && table->array == NULL);
|
||||
table->size = elts * 2;
|
||||
table->array = xcalloc(sizeof(struct hash_table_entry), table->size);
|
||||
}
|
||||
|
||||
#endif
|
@ -126,85 +126,6 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
|
||||
}
|
||||
}
|
||||
|
||||
struct hash_entry
|
||||
{
|
||||
struct hash_entry *next;
|
||||
char key[FLEX_ARRAY];
|
||||
};
|
||||
|
||||
/*
|
||||
* Test performance of hash.[ch]
|
||||
* Usage: time echo "perfhash method rounds" | test-hashmap
|
||||
*/
|
||||
static void perf_hash(unsigned int method, unsigned int rounds)
|
||||
{
|
||||
struct hash_table map;
|
||||
char buf[16];
|
||||
struct hash_entry **entries, **res, *entry;
|
||||
unsigned int *hashes;
|
||||
unsigned int i, j;
|
||||
|
||||
entries = malloc(TEST_SIZE * sizeof(struct hash_entry *));
|
||||
hashes = malloc(TEST_SIZE * sizeof(int));
|
||||
for (i = 0; i < TEST_SIZE; i++) {
|
||||
snprintf(buf, sizeof(buf), "%i", i);
|
||||
entries[i] = malloc(sizeof(struct hash_entry) + strlen(buf) + 1);
|
||||
strcpy(entries[i]->key, buf);
|
||||
hashes[i] = hash(method, i, entries[i]->key);
|
||||
}
|
||||
|
||||
if (method & TEST_ADD) {
|
||||
/* test adding to the map */
|
||||
for (j = 0; j < rounds; j++) {
|
||||
init_hash(&map);
|
||||
|
||||
/* add entries */
|
||||
for (i = 0; i < TEST_SIZE; i++) {
|
||||
res = (struct hash_entry **) insert_hash(
|
||||
hashes[i], entries[i], &map);
|
||||
if (res) {
|
||||
entries[i]->next = *res;
|
||||
*res = entries[i];
|
||||
} else {
|
||||
entries[i]->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free_hash(&map);
|
||||
}
|
||||
} else {
|
||||
/* test map lookups */
|
||||
init_hash(&map);
|
||||
|
||||
/* fill the map (sparsely if specified) */
|
||||
j = (method & TEST_SPARSE) ? TEST_SIZE / 10 : TEST_SIZE;
|
||||
for (i = 0; i < j; i++) {
|
||||
res = (struct hash_entry **) insert_hash(hashes[i],
|
||||
entries[i], &map);
|
||||
if (res) {
|
||||
entries[i]->next = *res;
|
||||
*res = entries[i];
|
||||
} else {
|
||||
entries[i]->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < rounds; j++) {
|
||||
for (i = 0; i < TEST_SIZE; i++) {
|
||||
entry = lookup_hash(hashes[i], &map);
|
||||
while (entry) {
|
||||
if (!strcmp(entries[i]->key, entry->key))
|
||||
break;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_hash(&map);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define DELIM " \t\r\n"
|
||||
|
||||
/*
|
||||
@ -218,7 +139,6 @@ static void perf_hash(unsigned int method, unsigned int rounds)
|
||||
* size -> tablesize numentries
|
||||
*
|
||||
* perfhashmap method rounds -> test hashmap.[ch] performance
|
||||
* perfhash method rounds -> test hash.[ch] performance
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@ -324,10 +244,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
perf_hashmap(atoi(p1), atoi(p2));
|
||||
|
||||
} else if (!strcmp("perfhash", cmd) && l1 && l2) {
|
||||
|
||||
perf_hash(atoi(p1), atoi(p2));
|
||||
|
||||
} else {
|
||||
|
||||
printf("Unknown command %s\n", cmd);
|
||||
|
Loading…
Reference in New Issue
Block a user