diff options
Diffstat (limited to 'common/dict.c')
-rw-r--r-- | common/dict.c | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/common/dict.c b/common/dict.c deleted file mode 100644 index b7ab00d..0000000 --- a/common/dict.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2004 Stefan Walter - * Copyright (c) 2011 Collabora Ltd. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - */ - -#include "config.h" - -#include "debug.h" -#include "dict.h" -#include "hash.h" - -#include <sys/types.h> - -#include <assert.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -struct _p11_dict { - p11_dict_hasher hash_func; - p11_dict_equals equal_func; - p11_destroyer key_destroy_func; - p11_destroyer value_destroy_func; - - struct _p11_dictbucket **buckets; - unsigned int num_items; - unsigned int num_buckets; -}; - -typedef struct _p11_dictbucket { - void *key; - unsigned int hashed; - void *value; - struct _p11_dictbucket *next; -} dictbucket; - -static dictbucket * -next_entry (p11_dictiter *iter) -{ - dictbucket *bucket = iter->next; - while (!bucket) { - if (iter->index >= iter->dict->num_buckets) - return NULL; - bucket = iter->dict->buckets[iter->index++]; - } - iter->next = bucket->next; - return bucket; -} - - -bool -p11_dict_next (p11_dictiter *iter, - void **key, - void **value) -{ - dictbucket *bucket = next_entry (iter); - if (bucket == NULL) - return false; - if (key) - *key = bucket->key; - if (value) - *value = bucket->value; - return true; -} - -void -p11_dict_iterate (p11_dict *dict, - p11_dictiter *iter) -{ - iter->dict = dict; - iter->index = 0; - iter->next = NULL; -} - -static dictbucket ** -lookup_or_create_bucket (p11_dict *dict, - const void *key, - bool create) -{ - dictbucket **bucketp; - unsigned int hash; - - /* Perform the hashing */ - hash = dict->hash_func (key); - - /* scan linked list */ - for (bucketp = &dict->buckets[hash % dict->num_buckets]; - *bucketp != NULL; bucketp = &(*bucketp)->next) { - if((*bucketp)->hashed == hash && dict->equal_func ((*bucketp)->key, key)) - break; - } - - if ((*bucketp) != NULL || !create) - return bucketp; - - /* add a new entry for non-NULL val */ - (*bucketp) = calloc (sizeof (dictbucket), 1); - - if (*bucketp != NULL) { - (*bucketp)->key = (void*)key; - (*bucketp)->hashed = hash; - dict->num_items++; - } - - return bucketp; -} - -void * -p11_dict_get (p11_dict *dict, - const void *key) -{ - dictbucket **bucketp; - - bucketp = lookup_or_create_bucket (dict, key, false); - if (bucketp && *bucketp) - return (void*)((*bucketp)->value); - else - return NULL; -} - -bool -p11_dict_set (p11_dict *dict, - void *key, - void *val) -{ - dictbucket **bucketp; - p11_dictiter iter; - dictbucket *bucket; - dictbucket **new_buckets; - unsigned int num_buckets; - - bucketp = lookup_or_create_bucket (dict, key, true); - if(bucketp && *bucketp) { - - /* Destroy the previous key */ - if ((*bucketp)->key && (*bucketp)->key != key && dict->key_destroy_func) - dict->key_destroy_func ((*bucketp)->key); - - /* Destroy the previous value */ - if ((*bucketp)->value && (*bucketp)->value != val && dict->value_destroy_func) - dict->value_destroy_func ((*bucketp)->value); - - /* replace entry */ - (*bucketp)->key = key; - (*bucketp)->value = val; - - /* check that the collision rate isn't too high */ - if (dict->num_items > dict->num_buckets) { - num_buckets = dict->num_buckets * 2 + 1; - new_buckets = (dictbucket **)calloc (sizeof (dictbucket *), num_buckets); - - /* Ignore failures, maybe we can expand later */ - if(new_buckets) { - p11_dict_iterate (dict, &iter); - while ((bucket = next_entry (&iter)) != NULL) { - unsigned int i = bucket->hashed % num_buckets; - bucket->next = new_buckets[i]; - new_buckets[i] = bucket; - } - - free (dict->buckets); - dict->buckets = new_buckets; - dict->num_buckets = num_buckets; - } - } - - return true; - } - - return_val_if_reached (false); -} - -bool -p11_dict_steal (p11_dict *dict, - const void *key, - void **stolen_key, - void **stolen_value) -{ - dictbucket **bucketp; - - bucketp = lookup_or_create_bucket (dict, key, false); - if (bucketp && *bucketp) { - dictbucket *old = *bucketp; - *bucketp = (*bucketp)->next; - --dict->num_items; - if (stolen_key) - *stolen_key = old->key; - if (stolen_value) - *stolen_value = old->value; - free (old); - return true; - } - - return false; - -} - -bool -p11_dict_remove (p11_dict *dict, - const void *key) -{ - void *old_key; - void *old_value; - - if (!p11_dict_steal (dict, key, &old_key, &old_value)) - return false; - - if (dict->key_destroy_func) - dict->key_destroy_func (old_key); - if (dict->value_destroy_func) - dict->value_destroy_func (old_value); - return true; -} - -void -p11_dict_clear (p11_dict *dict) -{ - dictbucket *bucket, *next; - unsigned int i; - - /* Free all entries in the array */ - for (i = 0; i < dict->num_buckets; ++i) { - bucket = dict->buckets[i]; - while (bucket != NULL) { - next = bucket->next; - if (dict->key_destroy_func) - dict->key_destroy_func (bucket->key); - if (dict->value_destroy_func) - dict->value_destroy_func (bucket->value); - free (bucket); - bucket = next; - } - } - - memset (dict->buckets, 0, dict->num_buckets * sizeof (dictbucket *)); - dict->num_items = 0; -} - -p11_dict * -p11_dict_new (p11_dict_hasher hash_func, - p11_dict_equals equal_func, - p11_destroyer key_destroy_func, - p11_destroyer value_destroy_func) -{ - p11_dict *dict; - - assert (hash_func); - assert (equal_func); - - dict = malloc (sizeof (p11_dict)); - if (dict) { - dict->hash_func = hash_func; - dict->equal_func = equal_func; - dict->key_destroy_func = key_destroy_func; - dict->value_destroy_func = value_destroy_func; - - dict->num_buckets = 9; - dict->buckets = (dictbucket **)calloc (sizeof (dictbucket *), dict->num_buckets); - if (!dict->buckets) { - free (dict); - return NULL; - } - - dict->num_items = 0; - } - - return dict; -} - -void -p11_dict_free (p11_dict *dict) -{ - dictbucket *bucket; - p11_dictiter iter; - - if (!dict) - return; - - p11_dict_iterate (dict, &iter); - while ((bucket = next_entry (&iter)) != NULL) { - if (dict->key_destroy_func) - dict->key_destroy_func (bucket->key); - if (dict->value_destroy_func) - dict->value_destroy_func (bucket->value); - free (bucket); - } - - if (dict->buckets) - free (dict->buckets); - - free (dict); -} - -unsigned int -p11_dict_size (p11_dict *dict) -{ - return dict->num_items; -} - -unsigned int -p11_dict_str_hash (const void *string) -{ - uint32_t hash; - p11_hash_murmur3 (&hash, string, strlen (string), NULL); - return hash; -} - -bool -p11_dict_str_equal (const void *string_one, - const void *string_two) -{ - assert (string_one); - assert (string_two); - - return strcmp (string_one, string_two) == 0; -} - -unsigned int -p11_dict_ulongptr_hash (const void *to_ulong) -{ - assert (to_ulong); - return (unsigned int)*((unsigned long*)to_ulong); -} - -bool -p11_dict_ulongptr_equal (const void *ulong_one, - const void *ulong_two) -{ - assert (ulong_one); - assert (ulong_two); - return *((unsigned long*)ulong_one) == *((unsigned long*)ulong_two); -} - -unsigned int -p11_dict_intptr_hash (const void *to_int) -{ - assert (to_int); - return (unsigned int)*((int*)to_int); -} - -bool -p11_dict_intptr_equal (const void *int_one, - const void *int_two) -{ - assert (int_one); - assert (int_two); - return *((int*)int_one) == *((int*)int_two); -} - -unsigned int -p11_dict_direct_hash (const void *ptr) -{ - return (unsigned int)(size_t)ptr; -} - -bool -p11_dict_direct_equal (const void *ptr_one, - const void *ptr_two) -{ - return ptr_one == ptr_two; -} |