mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-11-22 04:49:46 +01:00
Add simple hash table implementation
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
00c8946497
commit
6dd9ae94bd
3 changed files with 175 additions and 0 deletions
27
include/util/hashtable.h
Normal file
27
include/util/hashtable.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef HASH_TABLE_H
|
||||||
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
|
typedef struct hash_bucket_t {
|
||||||
|
struct hash_bucket_t *next;
|
||||||
|
char *key;
|
||||||
|
void *value;
|
||||||
|
} hash_bucket_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hash_bucket_t **buckets;
|
||||||
|
size_t num_buckets;
|
||||||
|
size_t count;
|
||||||
|
} hash_table_t;
|
||||||
|
|
||||||
|
int hash_table_init(hash_table_t *table, size_t size);
|
||||||
|
|
||||||
|
void hash_table_cleanup(hash_table_t *table);
|
||||||
|
|
||||||
|
void *hash_table_lookup(hash_table_t *table, const char *key);
|
||||||
|
|
||||||
|
int hash_table_set(hash_table_t *table, const char *key, void *value);
|
||||||
|
|
||||||
|
void hash_table_foreach(hash_table_t *table, void *usr,
|
||||||
|
int(*fun)(void *usr, const char *key, void *value));
|
||||||
|
|
||||||
|
#endif /* HASH_TABLE_H */
|
|
@ -2,6 +2,7 @@ libutil_a_SOURCES = lib/util/input_file.c lib/util/mkdir_p.c
|
||||||
libutil_a_SOURCES += lib/util/write_retry.c lib/util/read_retry.c
|
libutil_a_SOURCES += lib/util/write_retry.c lib/util/read_retry.c
|
||||||
libutil_a_SOURCES += lib/util/canonicalize_name.c
|
libutil_a_SOURCES += lib/util/canonicalize_name.c
|
||||||
libutil_a_SOURCES += include/util/util.h include/util/input_file.h
|
libutil_a_SOURCES += include/util/util.h include/util/input_file.h
|
||||||
|
libutil_a_SOURCES += include/util/hashtable.h lib/util/hashtable.c
|
||||||
|
|
||||||
libfilelist_a_SOURCES = lib/filelist/dump_toc.c lib/filelist/image_entry.c
|
libfilelist_a_SOURCES = lib/filelist/dump_toc.c lib/filelist/image_entry.c
|
||||||
libfilelist_a_SOURCES += lib/filelist/image_entry_sort.c
|
libfilelist_a_SOURCES += lib/filelist/image_entry_sort.c
|
||||||
|
|
147
lib/util/hashtable.c
Normal file
147
lib/util/hashtable.c
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "util/hashtable.h"
|
||||||
|
|
||||||
|
/* R5 hash function (borrowed from reiserfs) */
|
||||||
|
static uint32_t strhash(const char *s)
|
||||||
|
{
|
||||||
|
const signed char *str = (const signed char *)s;
|
||||||
|
uint32_t a = 0;
|
||||||
|
|
||||||
|
while (*str != '\0') {
|
||||||
|
a += *str << 4;
|
||||||
|
a += *str >> 4;
|
||||||
|
a *= 11;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hash_table_init(hash_table_t *table, size_t size)
|
||||||
|
{
|
||||||
|
table->num_buckets = size;
|
||||||
|
table->count = 0;
|
||||||
|
table->buckets = calloc(size, sizeof(table->buckets[0]));
|
||||||
|
|
||||||
|
if (table->buckets == NULL) {
|
||||||
|
fputs("out of memory\n", stderr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_table_cleanup(hash_table_t *table)
|
||||||
|
{
|
||||||
|
hash_bucket_t *bucket;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < table->num_buckets; ++i) {
|
||||||
|
while (table->buckets[i] != NULL) {
|
||||||
|
bucket = table->buckets[i];
|
||||||
|
table->buckets[i] = bucket->next;
|
||||||
|
|
||||||
|
free(bucket->key);
|
||||||
|
free(bucket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(table->buckets);
|
||||||
|
|
||||||
|
table->buckets = NULL;
|
||||||
|
table->num_buckets = 0;
|
||||||
|
table->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *hash_table_lookup(hash_table_t *table, const char *key)
|
||||||
|
{
|
||||||
|
hash_bucket_t *bucket;
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
|
hash = strhash(key);
|
||||||
|
bucket = table->buckets[hash % table->num_buckets];
|
||||||
|
|
||||||
|
while (bucket != NULL) {
|
||||||
|
if (strcmp(bucket->key, key) == 0)
|
||||||
|
return bucket->value;
|
||||||
|
|
||||||
|
bucket = bucket->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hash_table_set(hash_table_t *table, const char *key, void *value)
|
||||||
|
{
|
||||||
|
hash_bucket_t *bucket;
|
||||||
|
uint32_t hash;
|
||||||
|
size_t index;
|
||||||
|
|
||||||
|
hash = strhash(key);
|
||||||
|
index = hash % table->num_buckets;
|
||||||
|
bucket = table->buckets[index];
|
||||||
|
|
||||||
|
while (bucket != NULL) {
|
||||||
|
if (strcmp(bucket->key, key) == 0) {
|
||||||
|
bucket->value = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket = bucket->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket = calloc(1, sizeof(*bucket));
|
||||||
|
if (bucket == NULL)
|
||||||
|
goto fail_oom;
|
||||||
|
|
||||||
|
bucket->key = strdup(key);
|
||||||
|
if (bucket->key == NULL)
|
||||||
|
goto fail_oom;
|
||||||
|
|
||||||
|
bucket->value = value;
|
||||||
|
bucket->next = table->buckets[index];
|
||||||
|
|
||||||
|
table->buckets[index] = bucket;
|
||||||
|
table->count += 1;
|
||||||
|
return 0;
|
||||||
|
fail_oom:
|
||||||
|
free(bucket);
|
||||||
|
fputs("out of memory\n", stderr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_table_foreach(hash_table_t *table, void *usr,
|
||||||
|
int(*fun)(void *usr, const char *key, void *value))
|
||||||
|
{
|
||||||
|
hash_bucket_t *bucket, *prev;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < table->num_buckets; ++i) {
|
||||||
|
prev = NULL;
|
||||||
|
bucket = table->buckets[i];
|
||||||
|
|
||||||
|
while (bucket != NULL) {
|
||||||
|
if (fun(usr, bucket->key, bucket->value)) {
|
||||||
|
if (prev == NULL) {
|
||||||
|
table->buckets[i] = bucket->next;
|
||||||
|
free(bucket->key);
|
||||||
|
free(bucket);
|
||||||
|
bucket = table->buckets[i];
|
||||||
|
} else {
|
||||||
|
prev->next = bucket->next;
|
||||||
|
free(bucket->key);
|
||||||
|
free(bucket);
|
||||||
|
bucket = prev->next;
|
||||||
|
}
|
||||||
|
table->count -= 1;
|
||||||
|
} else {
|
||||||
|
prev = bucket;
|
||||||
|
bucket = bucket->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue