aboutsummaryrefslogtreecommitdiff
path: root/dict.c
diff options
context:
space:
mode:
authorJuan Cespedes <cespedes@debian.org>2003-01-31 18:58:58 +0100
committerJuan Cespedes <cespedes@debian.org>2003-01-31 18:58:58 +0100
commitcac15c3f170b5ec2cc6304c8c0763a78103e1778 (patch)
tree248b244dc9c366275033db39187d1060da81e37b /dict.c
parentde5a7eb873c05a698e4267b554e25124dc92e7f4 (diff)
downloadltrace-cac15c3f170b5ec2cc6304c8c0763a78103e1778.tar.gz
Version 0.3.27
* Removed dependency on libdl (it is no longer needed) * Wrote generic dictionary, used in demangle.c and breakpoints.c * Added debug.c for better debugging output
Diffstat (limited to 'dict.c')
-rw-r--r--dict.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/dict.c b/dict.c
new file mode 100644
index 0000000..f428820
--- /dev/null
+++ b/dict.c
@@ -0,0 +1,151 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "debug.h"
+
+/*
+ Dictionary based on code by Morten Eriksen <mortene@sim.no>.
+*/
+
+#include "dict.h"
+
+struct dict_entry {
+ unsigned int hash;
+ void * key;
+ void * value;
+ struct dict_entry * next;
+};
+
+/* #define DICTTABLESIZE 97 */
+#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */
+/* #define DICTTABLESIZE 9973 */
+/* #define DICTTABLESIZE 99991 */
+/* #define DICTTABLESIZE 999983 */
+
+struct dict {
+ struct dict_entry * buckets[DICTTABLESIZE];
+ unsigned int (*key2hash)(void *);
+ int (*key_cmp)(void *, void *);
+};
+
+struct dict *
+dict_init(unsigned int (*key2hash)(void *), int (*key_cmp)(void *, void *)) {
+ struct dict * d;
+ int i;
+
+ d = malloc(sizeof(struct dict));
+ if (!d) {
+ perror("malloc()");
+ exit(1);
+ }
+ for (i = 0; i < DICTTABLESIZE; i++) { /* better use memset()? */
+ d->buckets[i] = NULL;
+ }
+ d->key2hash = key2hash;
+ d->key_cmp = key_cmp;
+ return d;
+}
+
+void
+dict_clear(struct dict * d) {
+ int i;
+ struct dict_entry * entry, * nextentry;
+
+ for (i = 0; i < DICTTABLESIZE; i++) {
+ for (entry = d->buckets[i]; entry != NULL; entry = nextentry) {
+ nextentry = entry->next;
+ free(entry);
+ }
+ d->buckets[i] = NULL;
+ }
+ free(d);
+}
+
+int
+dict_enter(struct dict * d, void * key, void * value) {
+ struct dict_entry * entry, * newentry;
+ unsigned int hash = d->key2hash(key);
+ unsigned int bucketpos = hash % DICTTABLESIZE;
+
+ newentry = malloc(sizeof(struct dict_entry));
+ if (!newentry) {
+ perror("malloc");
+ exit(1);
+ }
+
+ newentry->hash = hash;
+ newentry->key = key;
+ newentry->value = value;
+ newentry->next = NULL;
+
+ entry = d->buckets[bucketpos];
+ while (entry && entry->next) entry = entry->next;
+
+ if (entry) entry->next = newentry;
+ else d->buckets[bucketpos] = newentry;
+
+ debug(3, "new dict entry at %p[%d]: (%p,%p)\n", d, bucketpos, key, value);
+ return 0;
+}
+
+void *
+dict_find_entry(struct dict * d, void * key) {
+ unsigned int hash = d->key2hash(key);
+ unsigned int bucketpos = hash % DICTTABLESIZE;
+ struct dict_entry * entry;
+
+ for (entry = d->buckets[bucketpos]; entry; entry = entry->next) {
+ if (hash != entry->hash) {
+ continue;
+ }
+ if (!d->key_cmp(key, entry->key)) {
+ break;
+ }
+ }
+ return entry ? entry->value : NULL;
+}
+
+void
+dict_apply_to_all(struct dict * d, void (*func)(void *key, void *value, void *data), void *data) {
+ int i;
+
+ for (i = 0; i < DICTTABLESIZE; i++) {
+ struct dict_entry * entry = d->buckets[i];
+ while (entry) {
+ func(entry->key, entry->value, data);
+ entry = entry->next;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+unsigned int
+dict_key2hash_string(void * key) {
+ const char * s = (const char *)key;
+ unsigned int total = 0, shift = 0;
+
+ while (*s) {
+ total = total ^ ((*s) << shift);
+ shift += 5;
+ if (shift > 24) shift -= 24;
+ s++;
+ }
+ return total;
+}
+
+int
+dict_key_cmp_string(void * key1, void * key2) {
+ return strcmp((const char *)key1, (const char *)key2);
+}
+
+unsigned int
+dict_key2hash_int(void * key) {
+ return (unsigned int)key;
+}
+
+int
+dict_key_cmp_int(void * key1, void * key2) {
+ return key1 - key2;
+}
+