aboutsummaryrefslogtreecommitdiff
path: root/libctf/ctf-hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'libctf/ctf-hash.c')
-rw-r--r--libctf/ctf-hash.c106
1 files changed, 35 insertions, 71 deletions
diff --git a/libctf/ctf-hash.c b/libctf/ctf-hash.c
index 1bc539e..f8032ae 100644
--- a/libctf/ctf-hash.c
+++ b/libctf/ctf-hash.c
@@ -22,25 +22,22 @@
#include "libiberty.h"
#include "hashtab.h"
-/* We have three hashtable implementations:
-
- - ctf_hash_* is an interface to a fixed-size hash from const char * ->
- ctf_id_t with number of elements specified at creation time, that should
- support addition of items but need not support removal.
+/* We have two hashtable implementations:
- ctf_dynhash_* is an interface to a dynamically-expanding hash with
- unknown size that should support addition of large numbers of items, and
- removal as well, and is used only at type-insertion time and during
- linking.
+ unknown size that should support addition of large numbers of items,
+ and removal as well, and is used only at type-insertion time and during
+ linking. It can be constructed with an expected initial number of
+ elements, but need not be.
- ctf_dynset_* is an interface to a dynamically-expanding hash that contains
only keys: no values.
These can be implemented by the same underlying hashmap if you wish. */
-/* The helem is used for general key/value mappings in both the ctf_hash and
- ctf_dynhash: the owner may not have space allocated for it, and will be
- garbage (not NULL!) in that case. */
+/* The helem is used for general key/value mappings in the ctf_dynhash: the
+ owner may not have space allocated for it, and will be garbage (not
+ NULL!) in that case. */
typedef struct ctf_helem
{
@@ -157,8 +154,9 @@ ctf_dynhash_item_free (void *item)
}
ctf_dynhash_t *
-ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
- ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
+ctf_dynhash_create_sized (unsigned long nelems, ctf_hash_fun hash_fun,
+ ctf_hash_eq_fun eq_fun, ctf_hash_free_fun key_free,
+ ctf_hash_free_fun value_free)
{
ctf_dynhash_t *dynhash;
htab_del del = ctf_dynhash_item_free;
@@ -173,8 +171,7 @@ ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
if (key_free == NULL && value_free == NULL)
del = free;
- /* 7 is arbitrary and untested for now. */
- if ((dynhash->htab = htab_create_alloc (7, (htab_hash) hash_fun, eq_fun,
+ if ((dynhash->htab = htab_create_alloc (nelems, (htab_hash) hash_fun, eq_fun,
del, xcalloc, free)) == NULL)
{
free (dynhash);
@@ -190,6 +187,15 @@ ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
return dynhash;
}
+ctf_dynhash_t *
+ctf_dynhash_create (ctf_hash_fun hash_fun, ctf_hash_eq_fun eq_fun,
+ ctf_hash_free_fun key_free, ctf_hash_free_fun value_free)
+{
+ /* 7 is arbitrary and not benchmarked yet. */
+
+ return ctf_dynhash_create_sized (7, hash_fun, eq_fun, key_free, value_free);
+}
+
static ctf_helem_t **
ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option insert)
{
@@ -767,80 +773,38 @@ ctf_dynset_next (ctf_dynset_t *hp, ctf_next_t **it, void **key)
return ECTF_NEXT_END;
}
-/* ctf_hash, used for fixed-size maps from const char * -> ctf_id_t without
- removal. This is a straight cast of a hashtab. */
-
-ctf_hash_t *
-ctf_hash_create (unsigned long nelems, ctf_hash_fun hash_fun,
- ctf_hash_eq_fun eq_fun)
-{
- return (ctf_hash_t *) htab_create_alloc (nelems, (htab_hash) hash_fun,
- eq_fun, free, xcalloc, free);
-}
-
-uint32_t
-ctf_hash_size (const ctf_hash_t *hp)
-{
- return htab_elements ((struct htab *) hp);
-}
+/* Helper functions for insertion/removal of types. */
int
-ctf_hash_insert_type (ctf_hash_t *hp, ctf_dict_t *fp, uint32_t type,
- uint32_t name)
+ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type,
+ uint32_t name)
{
- const char *str = ctf_strraw (fp, name);
+ const char *str;
+ int err;
if (type == 0)
return EINVAL;
- if (str == NULL
- && CTF_NAME_STID (name) == CTF_STRTAB_1
- && fp->ctf_syn_ext_strtab == NULL
- && fp->ctf_str[CTF_NAME_STID (name)].cts_strs == NULL)
- return ECTF_STRTAB;
-
- if (str == NULL)
- return ECTF_BADNAME;
+ if ((str = ctf_strptr_validate (fp, name)) == NULL)
+ return ctf_errno (fp);
if (str[0] == '\0')
return 0; /* Just ignore empty strings on behalf of caller. */
- if (ctf_hashtab_insert ((struct htab *) hp, (char *) str,
- (void *) (ptrdiff_t) type, NULL, NULL) != NULL)
+ if ((err = ctf_dynhash_insert (hp, (char *) str,
+ (void *) (ptrdiff_t) type)) == 0)
return 0;
- return errno;
-}
-
-/* if the key is already in the hash, override the previous definition with
- this new official definition. If the key is not present, then call
- ctf_hash_insert_type and hash it in. */
-int
-ctf_hash_define_type (ctf_hash_t *hp, ctf_dict_t *fp, uint32_t type,
- uint32_t name)
-{
- /* This matches the semantics of ctf_hash_insert_type in this
- implementation anyway. */
- return ctf_hash_insert_type (hp, fp, type, name);
+ return err;
}
ctf_id_t
-ctf_hash_lookup_type (ctf_hash_t *hp, ctf_dict_t *fp __attribute__ ((__unused__)),
- const char *key)
+ctf_dynhash_lookup_type (ctf_dynhash_t *hp, const char *key)
{
- ctf_helem_t **slot;
+ void *value;
- slot = ctf_hashtab_lookup ((struct htab *) hp, key, NO_INSERT);
-
- if (slot)
- return (ctf_id_t) (uintptr_t) ((*slot)->value);
+ if (ctf_dynhash_lookup_kv (hp, key, NULL, &value))
+ return (ctf_id_t) (uintptr_t) value;
return 0;
}
-
-void
-ctf_hash_destroy (ctf_hash_t *hp)
-{
- if (hp != NULL)
- htab_delete ((struct htab *) hp);
-}