summaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorRocco Rutte <pdmef@gmx.net>2009-03-09 11:11:51 +0100
committerRocco Rutte <pdmef@gmx.net>2009-03-09 11:11:51 +0100
commit579dc6a5c507b6dc8133561cd711224ef5bef447 (patch)
treefc1c83911fc07b7097a417ef11f1bf80b0539383 /hash.c
parent8c99cc1a83d9a745490999fefa1743c10cac4f39 (diff)
Restore $reverse_alias feature by using case-insensitive hash keys
The fix is implemented as callbacks in the hash table so we can avoid working with copies of the mailbox keys but work on the originals instead and don't pollute the code with lower-case conversions all over the place. While I'm at it, turn int hashes into unsigned values since the hash function returns unsigned values now, too. Closes #3185.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/hash.c b/hash.c
index 7e4e19fd..08f71717 100644
--- a/hash.c
+++ b/hash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1996-2009 Michael R. Elkins <me@mutt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,12 +23,13 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "mutt.h"
#define SOMEPRIME 149711
-unsigned int hash_string (const unsigned char *s, unsigned int n)
+static unsigned int hash_string (const unsigned char *s, unsigned int n)
{
unsigned int h = 0;
@@ -39,13 +40,34 @@ unsigned int hash_string (const unsigned char *s, unsigned int n)
return h;
}
-HASH *hash_create (int nelem)
+static unsigned int hash_case_string (const unsigned char *s, unsigned int n)
+{
+ unsigned int h = 0;
+
+ while (*s)
+ h += (h << 7) + tolower (*s++);
+ h = (h * SOMEPRIME) % n;
+
+ return h;
+}
+
+HASH *hash_create (int nelem, int lower)
{
HASH *table = safe_malloc (sizeof (HASH));
if (nelem == 0)
nelem = 2;
table->nelem = nelem;
table->table = safe_calloc (nelem, sizeof (struct hash_elem *));
+ if (lower)
+ {
+ table->hash_string = hash_case_string;
+ table->cmp_string = mutt_strcasecmp;
+ }
+ else
+ {
+ table->hash_string = hash_string;
+ table->cmp_string = mutt_strcmp;
+ }
return table;
}
@@ -57,10 +79,10 @@ HASH *hash_create (int nelem)
int hash_insert (HASH * table, const char *key, void *data, int allow_dup)
{
struct hash_elem *ptr;
- int h;
+ unsigned int h;
ptr = (struct hash_elem *) safe_malloc (sizeof (struct hash_elem));
- h = hash_string ((unsigned char *) key, table->nelem);
+ h = table->hash_string ((unsigned char *) key, table->nelem);
ptr->key = key;
ptr->data = data;
@@ -76,7 +98,7 @@ int hash_insert (HASH * table, const char *key, void *data, int allow_dup)
for (tmp = table->table[h], last = NULL; tmp; last = tmp, tmp = tmp->next)
{
- r = mutt_strcmp (tmp->key, key);
+ r = table->cmp_string (tmp->key, key);
if (r == 0)
{
FREE (&ptr);
@@ -99,7 +121,7 @@ void *hash_find_hash (const HASH * table, int hash, const char *key)
struct hash_elem *ptr = table->table[hash];
for (; ptr; ptr = ptr->next)
{
- if (mutt_strcmp (key, ptr->key) == 0)
+ if (table->cmp_string (key, ptr->key) == 0)
return (ptr->data);
}
return NULL;
@@ -114,7 +136,7 @@ void hash_delete_hash (HASH * table, int hash, const char *key, const void *data
while (ptr)
{
if ((data == ptr->data || !data)
- && mutt_strcmp (ptr->key, key) == 0)
+ && table->cmp_string (ptr->key, key) == 0)
{
*last = ptr->next;
if (destroy)