From 56ac9bea51f338d488828ad1114d58b4a9542209 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Wed, 14 Mar 2007 01:15:21 +0100 Subject: [PATCH] more hash code simplifications. --- init.c | 4 +-- lib-lib/hash.c | 81 +++++++++++++++++++++++--------------------------- lib-lib/hash.h | 34 ++++++++++++--------- lib-mx/mbox.c | 4 +-- lib-mx/mh.c | 12 ++++---- lib-mx/mx.c | 8 ++--- mutt.h | 6 ++-- nntp/newsrc.c | 4 +-- nntp/nntp.c | 4 +-- nntp/nntp.h | 2 +- thread.c | 16 +++++----- thread.h | 4 +-- 12 files changed, 90 insertions(+), 89 deletions(-) diff --git a/init.c b/init.c index 45355c7..61d1f0a 100644 --- a/init.c +++ b/init.c @@ -42,7 +42,7 @@ static int parse_sort (struct option_t* dst, const char *s, const struct mapping_t *map, char* errbuf, ssize_t errlen); -static HASH *ConfigOptions = NULL; +static hash_t *ConfigOptions = NULL; /* for synonym warning reports: synonym found during parsing */ typedef struct syn_t { @@ -2200,7 +2200,7 @@ void mutt_init (int skip_sys_rc, string_list_t * commands) err.data = error; err.dsize = sizeof(error); - ConfigOptions = hash_create (sizeof(MuttVars) * 2, 0); + ConfigOptions = hash_new (sizeof(MuttVars) * 2, 0); for (i = 0; MuttVars[i].option; i++) { hash_insert (ConfigOptions, MuttVars[i].option, &MuttVars[i]); } diff --git a/lib-lib/hash.c b/lib-lib/hash.c index 2bfc65a..008c8fe 100644 --- a/lib-lib/hash.c +++ b/lib-lib/hash.c @@ -28,51 +28,66 @@ int hash_string(const unsigned char *s, int n) { - int h = 0; + unsigned h = 0; while (*s) { h += (h << 7) + *s++; } - h = (h * SOMEPRIME) % n; - h = (h >= 0) ? h : h + n; - return (h % n); + return (h * SOMEPRIME) % n; } -HASH *hash_create(int nelem, int allow_dup) +hash_t *hash_init(hash_t *table, int nelem, int allow_dup) { - HASH *table = p_new(HASH, 1); - table->dupes = allow_dup; table->nelem = MIN(nelem, 2); table->curnelem = 0; table->table = p_new(struct hash_elem *, table->nelem); - return table; } -void hash_resize(HASH *ptr, int nelem) +/* ptr pointer to the hash table to be freed + * destroy() function to call to free the ->data member (optional) + */ +void hash_wipe(hash_t *h, void (*dtor)(void *)) +{ + int i; + + for (i = 0; i < h->nelem; i++) { + struct hash_elem *elem, *tmp; + + for (elem = h->table[i]; elem;) { + tmp = elem; + elem = elem->next; + if (dtor) + dtor(tmp->data); + p_delete(&tmp); + } + } + p_delete(&h->table); +} + +void hash_resize(hash_t *ptr, int nelem) { - HASH *table; - struct hash_elem *elem, *tmp; + hash_t table; int i; /* XXX hack: we know the has was correct, no dupe checks is fater */ - table = hash_create(nelem, 1); + hash_init(&table, nelem, 1); for (i = 0; i < ptr->nelem; i++) { + struct hash_elem *elem, *tmp; for (elem = ptr->table[i]; elem;) { tmp = elem; elem = elem->next; - hash_insert(table, tmp->key, tmp->data); + hash_insert(&table, tmp->key, tmp->data); p_delete(&tmp); } } p_delete(&ptr->table); - ptr->nelem = table->nelem; - ptr->table = table->table; - p_delete(&table); + ptr->nelem = table.nelem; + ptr->table = table.table; } /* table hash table to update @@ -80,7 +95,7 @@ void hash_resize(HASH *ptr, int nelem) * data data to associate with `key' * allow_dup if nonzero, duplicate keys are allowed in the table */ -int hash_insert(HASH *table, const char *key, void *data) +int hash_insert(hash_t *table, const char *key, void *data) { struct hash_elem *ptr; int h; @@ -114,8 +129,9 @@ int hash_insert(HASH *table, const char *key, void *data) return h; } -void *hash_find_hash(const HASH *table, int hash, const char *key) +void *hash_find(const hash_t *table, const char *key) { + int hash = hash_string((unsigned char*)key, table->nelem); struct hash_elem *ptr; for (ptr = table->table[hash]; ptr; ptr = ptr->next) { @@ -125,9 +141,10 @@ void *hash_find_hash(const HASH *table, int hash, const char *key) return NULL; } -void hash_delete_hash(HASH *table, int hash, const char *key, const void *data, - void (*destroy)(void *)) +void hash_remove(hash_t *table, const char *key, const void *data, + void (*destroy)(void *)) { + int hash = hash_string((unsigned char*)key, table->nelem); struct hash_elem *ptr = table->table[hash]; struct hash_elem **last = &table->table[hash]; @@ -146,29 +163,7 @@ void hash_delete_hash(HASH *table, int hash, const char *key, const void *data, } } -/* ptr pointer to the hash table to be freed - * destroy() function to call to free the ->data member (optional) - */ -void hash_destroy(HASH **ptr, void (*destroy)(void *)) -{ - int i; - HASH *pptr = *ptr; - struct hash_elem *elem, *tmp; - - for (i = 0; i < pptr->nelem; i++) { - for (elem = pptr->table[i]; elem;) { - tmp = elem; - elem = elem->next; - if (destroy) - destroy (tmp->data); - p_delete(&tmp); - } - } - p_delete(&pptr->table); - p_delete(ptr); -} - -void hash_map(HASH *table, +void hash_map(hash_t *table, void (*mapfunc)(const char* key, void* data, unsigned long more), unsigned long more) { diff --git a/lib-lib/hash.h b/lib-lib/hash.h index 546b665..68468df 100644 --- a/lib-lib/hash.h +++ b/lib-lib/hash.h @@ -36,24 +36,30 @@ typedef struct { int nelem; int curnelem; struct hash_elem **table; -} HASH; +} hash_t; -#define hash_find(table, key) \ - hash_find_hash(table, hash_string((unsigned char *)key, table->nelem), key) +hash_t *hash_init(hash_t *, int nelem, int allow_dup); +static inline hash_t *hash_new(int nelem, int allow_dup) { + return hash_init(p_new(hash_t, 1), nelem, allow_dup); +} -#define hash_delete(table,key,data,destroy) \ - hash_delete_hash(table, hash_string((unsigned char *)key, table->nelem), key, data, destroy) +void hash_wipe(hash_t*, void (*dtor)(void*)); +static inline void hash_delete(hash_t **h, void (*dtor)(void*)) { + if (*h) { + hash_wipe(*h, dtor); + p_delete(h); + } +} -HASH *hash_create(int nelem, int allow_dup); int hash_string(const unsigned char *s, int n); -int hash_insert(HASH *table, const char *key, void *data); -void hash_resize(HASH *table, int nelem); -void *hash_find_hash(const HASH *table, int hash, const char *key); -void hash_delete_hash(HASH *table, int hash, const char *key, - const void *data, void (*destroy)(void *)); -void hash_destroy(HASH **hash, void (*destroy)(void *)); - -void hash_map(HASH *table, +void hash_resize(hash_t *table, int nelem); + +int hash_insert(hash_t *table, const char *key, void *data); +void *hash_find(const hash_t *table, const char *key); +void hash_remove(hash_t *table, const char *key, const void *data, + void (*destroy)(void *)); + +void hash_map(hash_t *table, void (*mapfunc)(const char *key, void *data, unsigned long more), unsigned long more); diff --git a/lib-mx/mbox.c b/lib-mx/mbox.c index 81beb52..7068742 100644 --- a/lib-mx/mbox.c +++ b/lib-mx/mbox.c @@ -838,9 +838,9 @@ static int mbox_reopen_mailbox (CONTEXT * ctx, int *index_hint) /* simulate a close */ if (ctx->id_hash) - hash_destroy (&ctx->id_hash, NULL); + hash_delete (&ctx->id_hash, NULL); if (ctx->subj_hash) - hash_destroy (&ctx->subj_hash, NULL); + hash_delete (&ctx->subj_hash, NULL); mutt_clear_threads (ctx); p_delete(&ctx->v2r); if (ctx->readonly) { diff --git a/lib-mx/mh.c b/lib-mx/mh.c index e1cf230..9108ed5 100644 --- a/lib-mx/mh.c +++ b/lib-mx/mh.c @@ -1431,7 +1431,7 @@ static int maildir_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __a struct maildir *md; /* list of messages in the mailbox */ struct maildir **last, *p; int i; - HASH *fnames; /* hash table for quickly looking up the base filename + hash_t *fnames; /* hash table for quickly looking up the base filename for a maildir message */ if (!option (OPTCHECKNEW)) @@ -1472,7 +1472,7 @@ static int maildir_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __a * of each message we scanned. This is used in the loop over the * existing messages below to do some correlation. */ - fnames = hash_create (1031, 0); + fnames = hash_new (1031, 0); for (p = md; p; p = p->next) { maildir_canon_filename (buf, p->h->path, sizeof (buf)); @@ -1530,7 +1530,7 @@ static int maildir_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __a } /* destroy the file name hash */ - hash_destroy (&fnames, NULL); + hash_delete (&fnames, NULL); /* If we didn't just get new mail, update the tables. */ if (occult) @@ -1564,7 +1564,7 @@ static int mh_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __attrib struct maildir *md, *p; struct maildir **last = NULL; struct mh_sequences mhs; - HASH *fnames; + hash_t *fnames; int i; if (!option (OPTCHECKNEW)) @@ -1610,7 +1610,7 @@ static int mh_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __attrib mhs_free_sequences (&mhs); /* check for modifications and adjust flags */ - fnames = hash_create (1031, 0); + fnames = hash_new (1031, 0); for (p = md; p; p = p->next) hash_insert (fnames, p->h->path, p); @@ -1633,7 +1633,7 @@ static int mh_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __attrib /* destroy the file name hash */ - hash_destroy (&fnames, NULL); + hash_delete (&fnames, NULL); /* If we didn't just get new mail, update the tables. */ if (occult) diff --git a/lib-mx/mx.c b/lib-mx/mx.c index d13a00f..3aaff52 100644 --- a/lib-mx/mx.c +++ b/lib-mx/mx.c @@ -552,9 +552,9 @@ void mx_fastclose_mailbox (CONTEXT * ctx) if (MX_IDX(ctx->magic-1) && mxfmts[ctx->magic-1]->mx_fastclose_mailbox) mxfmts[ctx->magic-1]->mx_fastclose_mailbox(ctx); if (ctx->subj_hash) - hash_destroy (&ctx->subj_hash, NULL); + hash_delete (&ctx->subj_hash, NULL); if (ctx->id_hash) - hash_destroy (&ctx->id_hash, NULL); + hash_delete (&ctx->id_hash, NULL); mutt_clear_threads (ctx); for (i = 0; i < ctx->msgcount; i++) header_delete(&ctx->hdrs[i]); @@ -906,10 +906,10 @@ void mx_update_tables (CONTEXT * ctx, int committing) ctx->hdrs[i]->content->hdr_offset); /* remove message from the hash tables */ if (ctx->subj_hash && ctx->hdrs[i]->env->real_subj) - hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, + hash_remove (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, ctx->hdrs[i], NULL); if (ctx->id_hash && ctx->hdrs[i]->env->message_id) - hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id, + hash_remove (ctx->id_hash, ctx->hdrs[i]->env->message_id, ctx->hdrs[i], NULL); header_delete(&ctx->hdrs[i]); } diff --git a/mutt.h b/mutt.h index 4b53da4..4758623 100644 --- a/mutt.h +++ b/mutt.h @@ -473,9 +473,9 @@ typedef struct { HEADER **hdrs; HEADER *last_tag; /* last tagged msg. used to link threads */ THREAD *tree; /* top of thread tree */ - HASH *id_hash; /* hash table by msg id */ - HASH *subj_hash; /* hash table by subject */ - HASH *thread_hash; /* hash table for threading */ + hash_t *id_hash; /* hash table by msg id */ + hash_t *subj_hash; /* hash table by subject */ + hash_t *thread_hash; /* hash table for threading */ int *v2r; /* mapping from virtual to real msgno */ int hdrmax; /* number of pointers in hdrs */ int msgcount; /* number of messages in the mailbox */ diff --git a/nntp/newsrc.c b/nntp/newsrc.c index 4e897f3..1a50b0d 100644 --- a/nntp/newsrc.c +++ b/nntp/newsrc.c @@ -378,13 +378,13 @@ NNTP_SERVER *mutt_select_newsserver (char *server) serv = p_new(NNTP_SERVER, 1); serv->conn = conn; serv->newsrc = m_strdup(file); - serv->newsgroups = hash_create(1009, false); + serv->newsgroups = hash_new(1009, false); slurp_newsrc (serv); /* load .newsrc */ nntp_parse_cacheindex (serv); /* load .index */ if (option (OPTNEWSCACHE) && serv->cache && nntp_get_cache_all (serv) >= 0) nntp_check_newgroups (serv, 1); else if (nntp_get_active (serv) < 0) { - hash_destroy (&serv->newsgroups, nntp_delete_data); + hash_delete (&serv->newsgroups, nntp_delete_data); for (list = serv->list; list; list = list->next) list->data = NULL; string_list_wipe(&serv->list); diff --git a/nntp/nntp.c b/nntp/nntp.c index 520ed7f..c2f8002 100644 --- a/nntp/nntp.c +++ b/nntp/nntp.c @@ -860,7 +860,7 @@ static int nntp_open_mailbox (CONTEXT * ctx) /* CACHE: delete cache and line from .index */ nntp_delete_cache (nntp_data); - hash_delete (serv->newsgroups, nntp_data->group, NULL, + hash_remove (serv->newsgroups, nntp_data->group, NULL, nntp_delete_data); while (l && l->data != (void *) nntp_data) l = l->next; @@ -1385,7 +1385,7 @@ int nntp_get_active (NNTP_SERVER * serv) if (data && data->deleted && !data->rc) { nntp_delete_cache (data); - hash_delete (serv->newsgroups, data->group, NULL, nntp_delete_data); + hash_remove (serv->newsgroups, data->group, NULL, nntp_delete_data); tmp->data = NULL; } } diff --git a/nntp/nntp.h b/nntp/nntp.h index bdd2936..de7627f 100644 --- a/nntp/nntp.h +++ b/nntp/nntp.h @@ -47,7 +47,7 @@ typedef struct { time_t mtime; time_t newgroups_time; time_t check_time; - HASH *newsgroups; + hash_t *newsgroups; string_list_t *list; /* list of newsgroups */ string_list_t *tail; /* last entry of list */ CONNECTION *conn; diff --git a/thread.c b/thread.c index f66afba..63013ba 100644 --- a/thread.c +++ b/thread.c @@ -502,7 +502,7 @@ void mutt_clear_threads (CONTEXT * ctx) ctx->tree = NULL; if (ctx->thread_hash) - hash_destroy (&ctx->thread_hash, free); + hash_delete (&ctx->thread_hash, free); } static int compare_threads (const void *a, const void *b) @@ -689,7 +689,7 @@ void mutt_sort_threads (CONTEXT * ctx, int init) init = 1; if (init) - ctx->thread_hash = hash_create (ctx->msgcount * 2, 1); + ctx->thread_hash = hash_new (ctx->msgcount * 2, 1); /* we want a quick way to see if things are actually attached to the top of the * thread tree or if they're just dangling, so we attach everything to a top @@ -1190,13 +1190,13 @@ int mutt_messages_in_thread (CONTEXT * ctx, HEADER * hdr, int flag) } -HASH *mutt_make_id_hash (CONTEXT * ctx) +hash_t *mutt_make_id_hash (CONTEXT * ctx) { int i; HEADER *hdr; - HASH *hash; + hash_t *hash; - hash = hash_create (ctx->msgcount * 2, 0); + hash = hash_new (ctx->msgcount * 2, 0); for (i = 0; i < ctx->msgcount; i++) { hdr = ctx->hdrs[i]; @@ -1207,13 +1207,13 @@ HASH *mutt_make_id_hash (CONTEXT * ctx) return hash; } -HASH *mutt_make_subj_hash (CONTEXT * ctx) +hash_t *mutt_make_subj_hash (CONTEXT * ctx) { int i; HEADER *hdr; - HASH *hash; + hash_t *hash; - hash = hash_create (ctx->msgcount * 2, 1); + hash = hash_new (ctx->msgcount * 2, 1); for (i = 0; i < ctx->msgcount; i++) { hdr = ctx->hdrs[i]; diff --git a/thread.h b/thread.h index 9522d26..0fa69f4 100644 --- a/thread.h +++ b/thread.h @@ -34,8 +34,8 @@ void mutt_set_virtual (CONTEXT *); int mutt_messages_in_thread (CONTEXT *, HEADER *, int); -HASH *mutt_make_id_hash (CONTEXT *); -HASH *mutt_make_subj_hash (CONTEXT *); +hash_t *mutt_make_id_hash (CONTEXT *); +hash_t *mutt_make_subj_hash (CONTEXT *); int mutt_link_threads (HEADER *, HEADER *, CONTEXT *); void mutt_break_thread (HEADER *); -- 2.20.1