From 4ea9f5f2dd5067960faf925b9c3d27f0e5436496 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Mon, 20 Jul 2015 16:27:17 -0500 Subject: [PATCH] Need those --- src/dict.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/hash.c | 20 +++++++ 2 files changed, 191 insertions(+) create mode 100644 src/dict.c create mode 100644 src/hash.c diff --git a/src/dict.c b/src/dict.c new file mode 100644 index 0000000..d933d95 --- /dev/null +++ b/src/dict.c @@ -0,0 +1,171 @@ +#include +#include + +#include +#include + +patty_dict *patty_dict_new() { + patty_dict *dict; + + if ((dict = malloc(sizeof(*dict))) == NULL) { + goto error_malloc_dict; + } + + memset(dict, 0x00, sizeof(*dict)); + + return dict; + +error_malloc_dict: + return NULL; +} + +patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t hash) { + patty_dict_bucket *bucket = &dict->bucket; + + int collisions; + + for (collisions = 0; collisions < 7; collisions++) { + uint32_t mask = 0x0f << (4 * collisions); + uint8_t index = (hash & mask) >> (4 * collisions); + + patty_dict_slot *slot = &bucket->slots[index]; + + if (slot->hash == 0x00000000) { + /* + * In this case, we have determined that there is no value in the + * dict for the given hash. + */ + return NULL; + } else if (slot->hash == hash) { + /* + * We have found the desired slot, so return that. + */ + return slot; + } + + /* + * Otherwise, look for the next bucket, if present. + */ + bucket = (patty_dict_bucket *)slot->next; + + /* + * If there is no next bucket available, then return null. + */ + if (bucket == NULL) { + return NULL; + } + } + + return NULL; +} + +static int bucket_each_slot(int level, patty_dict_bucket *bucket, patty_dict_callback callback, void *ctx) { + int i; + + if (level > 7) { + return 0; + } + + for (i=0; islots[i]; + + if (slot->key != NULL && slot->keysz > 0) { + if (callback(slot->key, slot->keysz, slot->value, ctx) < 0) { + goto error_callback; + } + } + + if (slot->next) { + return bucket_each_slot(level+1, (patty_dict_bucket *)slot->next, callback, ctx); + } + } + + return 0; + +error_callback: + return -1; +} + +int patty_dict_each(patty_dict *dict, patty_dict_callback callback, void *ctx) { + return bucket_each_slot(0, &dict->bucket, callback, ctx); +} + +void *patty_dict_get(patty_dict *dict, void *key, size_t keysz) { + patty_dict_slot *slot; + + uint32_t hash = patty_hash(key, keysz); + + if ((slot = patty_dict_slot_find(dict, hash)) == NULL) { + return NULL; + } + + return slot->value; +} + +void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value) { + patty_dict_bucket *bucket = &dict->bucket; + + uint32_t hash = patty_hash(key, keysz); + + int collisions; + + for (collisions = 0; collisions < 7; collisions++) { + uint32_t mask = 0x0f << (4 * collisions); + uint8_t index = (hash & mask) >> (4 * collisions); + + patty_dict_slot *slot = &bucket->slots[index]; + + if (slot->hash == 0x00000000 && slot->key == NULL) { + /* + * We have found an empty hash slot, so let's store the value. + */ + slot->hash = hash; + slot->key = key; + slot->keysz = keysz; + slot->value = value; + + return value; + } else if (slot->hash == hash) { + /* + * Otherwise, we've found an existing slot, so let's update that + * and bail. + */ + return slot->value = value; + } + + /* + * Take a look to see if there is a next bucket in the chain. + */ + bucket = (patty_dict_bucket *)slot->next; + + /* + * If there is no next bucket available, then create one. + */ + if (bucket == NULL) { + if ((bucket = malloc(sizeof(*bucket))) == NULL) { + goto error_malloc_bucket; + } + + memset(bucket, 0x00, sizeof(*bucket)); + + slot->next = (patty_dict_slot *)bucket; + } + } + + return NULL; + +error_malloc_bucket: + return NULL; +} + +static int dict_item_release(void *key, size_t keysz, void *value, void *ctx) { + free(value); + + return 0; +} + +void patty_dict_destroy(patty_dict *dict) { + (void)patty_dict_each(dict, dict_item_release, NULL); + + free(dict); +} diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..5e42293 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,20 @@ +#include +#include + +#include + +uint32_t patty_hash(void *key, size_t size) { + uint32_t hash = 0, i; + + for (i=0; i> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +}