diff options
author | Juan Cespedes <cespedes@debian.org> | 2003-01-31 18:58:58 +0100 |
---|---|---|
committer | Juan Cespedes <cespedes@debian.org> | 2003-01-31 18:58:58 +0100 |
commit | cac15c3f170b5ec2cc6304c8c0763a78103e1778 (patch) | |
tree | 248b244dc9c366275033db39187d1060da81e37b /dict.c | |
parent | de5a7eb873c05a698e4267b554e25124dc92e7f4 (diff) | |
download | ltrace-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.c | 151 |
1 files changed, 151 insertions, 0 deletions
@@ -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; +} + |