Now actually hashing the data but no longer managing keys as strings
This commit is contained in:
parent
7b818549bc
commit
7c1921581d
|
@ -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 */
|
||||
|
|
159
src/hash.c
159
src/hash.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user