Now actually hashing the data but no longer managing keys as strings

This commit is contained in:
Pierre Pronchery 2008-06-10 16:21:52 +00:00
parent 7b818549bc
commit 7c1921581d
2 changed files with 134 additions and 45 deletions

View File

@ -24,15 +24,27 @@
/* Hash */
/* types */
typedef Array Hash;
typedef struct _Hash Hash;
typedef unsigned int (*HashFunc)(void const * value);
typedef int (*HashCompare)(void const * value1, void const * value2);
typedef void (*HashForeach)(void const * key, void * value, void * data);
/* functions */
Hash * hash_new(void);
Hash * hash_new(HashFunc func, HashCompare compare);
void hash_delete(Hash * h);
/* helpers */
extern unsigned int hash_func_string(void const * value);
extern int hash_compare_string(void const * value1, void const * value2);
/* accessors */
void * hash_get(Hash * h, char const * name);
int hash_set(Hash * h, char const * name, void * data);
void * hash_get(Hash * h, void const * key);
int hash_set(Hash * h, void const * key, void * value);
size_t hash_count(Hash * hash);
/* useful */
void hash_foreach(Hash * hash, HashForeach func, void * data);
#endif /* !LIBSYSTEM_HASH_H */

View File

@ -13,8 +13,6 @@
* You should have received a copy of the Creative Commons Attribution-
* NonCommercial-ShareAlike 3.0 along with libSystem; if not, browse to
* http://creativecommons.org/licenses/by-nc-sa/3.0/ */
/* TODO:
* - actually hash the data... */
@ -28,45 +26,97 @@
/* types */
typedef struct _HashEntry
{
char * name;
void * data;
unsigned int hash;
void const * key;
void * value;
} HashEntry;
ARRAY(HashEntry, _hashentry);
#define HashEntryArray _hashentryArray
/* prototypes */
static void _hashentry_init(HashEntry * he, HashFunc func, void const * key,
void * value);
/* accessors */
static void _hashentry_set_value(HashEntry * he, void * value);
/* functions */
/* hashentry_init */
static int _hashentry_init(HashEntry * he, char const * name, void * data)
static void _hashentry_init(HashEntry * he, HashFunc func, void const * key,
void * value)
{
if((he->name = string_new(name)) == NULL)
return 1;
he->data = data;
return 0;
}
static void _hashentry_destroy(HashEntry * he)
{
free(he->name);
he->hash = (func != NULL) ? func(key) : 0;
he->key = key;
he->value = value;
}
/* useful */
static void _hashentry_set_data(HashEntry * he, void * data)
/* accessors */
/* hashentry_set_value */
static void _hashentry_set_value(HashEntry * he, void * value)
{
he->data = data;
he->value = value;
}
/* Hash */
/* protected */
/* types */
struct _Hash
{
HashFunc func;
HashCompare compare;
HashEntryArray * entries;
};
/* functions */
/* hash_func_string */
unsigned int hash_func_string(void const * key)
{
String const * str = key;
size_t i;
unsigned int hash = 0;
for(i = 0; i < sizeof(hash) && str[i] != '\0'; i++)
hash |= str[i] << (i << 3);
return hash;
}
/* hash_compare_string */
int hash_compare_string(void const * value1, void const * value2)
{
String const * str1 = value1;
String const * str2 = value2;
return string_compare(str1, str2);
}
/* public */
/* functions */
/* hash_new */
Hash * hash_new(void)
Hash * hash_new(HashFunc func, HashCompare compare)
{
Hash * hash;
if((hash = _hashentryarray_new()) == NULL)
if(compare == NULL)
{
error_set_code(1, "%s", "Invalid comparison function");
return NULL;
}
if((hash = object_new(sizeof(*hash))) == NULL)
return NULL;
if((hash->entries = _hashentryarray_new()) == NULL)
{
object_delete(hash);
return NULL;
}
hash->func = func;
hash->compare = compare;
return hash;
}
@ -74,56 +124,83 @@ Hash * hash_new(void)
/* hash_delete */
void hash_delete(Hash * hash)
{
size_t i;
HashEntry * he;
for(i = array_count(hash); i > 0; i--)
if((he = array_get(hash, i - 1)) != NULL)
_hashentry_destroy(he);
array_delete(hash);
array_delete(hash->entries);
object_delete(hash);
}
/* accessors */
/* hash_get */
void * hash_get(Hash * hash, char const * name)
void * hash_get(Hash * hash, void const * key)
{
unsigned int h;
size_t i;
HashEntry * he;
for(i = array_count(hash); i > 0; i--)
h = (hash->func != NULL) ? hash->func(key) : 0;
for(i = array_count(hash->entries); i > 0; i--)
{
if((he = array_get(hash, i - 1)) == NULL)
if((he = array_get(hash->entries, i - 1)) == NULL)
return NULL;
if(string_compare(he->name, name) == 0)
return he->data;
if(he->hash != h)
continue;
if(hash->compare(he->key, key) == 0)
return he->value;
}
error_set_code(1, "%s%s", name, ": Not found");
error_set_code(1, "%s", "Key not found");
return NULL;
}
/* hash_set */
int hash_set(Hash * hash, char const * name, void * data)
int hash_set(Hash * hash, void const * key, void * value)
{
unsigned int h;
size_t i;
HashEntry he;
HashEntry * p;
for(i = array_count(hash); i > 0; i--)
h = (hash->func != NULL) ? hash->func(key) : 0;
for(i = array_count(hash->entries); i > 0; i--)
{
if((p = array_get(hash, i - 1)) == NULL)
if((p = array_get(hash->entries, i - 1)) == NULL)
return 1;
if(string_compare(p->name, name) == 0)
if(p->hash != h)
continue;
if(hash->compare(p->key, key) == 0)
{
_hashentry_set_data(p, data);
_hashentry_set_value(p, value);
return 0;
}
}
if(_hashentry_init(&he, name, data) != 0)
return 1;
if(array_append(hash, &he) == 0)
_hashentry_init(&he, hash->func, key, value);
if(array_append(hash->entries, &he) == 0)
return 0;
_hashentry_destroy(&he);
return 1;
}
/* useful */
static void _hash_foreach(void * value, void * data);
/* FIXME ugly name */
struct a
{
HashForeach func;
void * data;
};
void hash_foreach(Hash * hash, HashForeach func, void * data)
{
struct a ad = { func, data };
array_foreach(hash->entries, _hash_foreach, &ad);
}
static void _hash_foreach(void * value, void * data)
{
HashEntry * he = value;
struct a * ad = data;
ad->func(he->key, he->value, ad->data);
}