mutt stable branch with some hacks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert HASH to be indexable by unsigned int. (see #3905)

Convert the HASH to be usable for either string or unsigned int keys,
so that a uid hash can be added for imap.

To keep hash-usage code disruption to a minimum, this introduces new
create/insert/find/delete functions for the int hash, but keeps the
old function names for string keys.

This implementation makes the key a union. It may have been a better
idea to introduce a whole new structure, but this way allows minimum
changes to and maximum reuse of the existing hash code.

+159 -34
+135 -20
hash.c
··· 29 29 30 30 #define SOMEPRIME 149711 31 31 32 - static unsigned int hash_string (const unsigned char *s, unsigned int n) 32 + static unsigned int gen_string_hash (union hash_key key, unsigned int n) 33 33 { 34 34 unsigned int h = 0; 35 + unsigned char *s = (unsigned char *)key.strkey; 35 36 36 37 while (*s) 37 38 h += (h << 7) + *s++; ··· 40 41 return h; 41 42 } 42 43 43 - static unsigned int hash_case_string (const unsigned char *s, unsigned int n) 44 + static int cmp_string_key (union hash_key a, union hash_key b) 45 + { 46 + return mutt_strcmp (a.strkey, b.strkey); 47 + } 48 + 49 + static unsigned int gen_case_string_hash (union hash_key key, unsigned int n) 44 50 { 45 51 unsigned int h = 0; 52 + unsigned char *s = (unsigned char *)key.strkey; 46 53 47 54 while (*s) 48 55 h += (h << 7) + tolower (*s++); ··· 51 58 return h; 52 59 } 53 60 54 - HASH *hash_create (int nelem, int lower) 61 + static int cmp_case_string_key (union hash_key a, union hash_key b) 62 + { 63 + return mutt_strcasecmp (a.strkey, b.strkey); 64 + } 65 + 66 + static unsigned int gen_int_hash (union hash_key key, unsigned int n) 67 + { 68 + return key.intkey % n; 69 + } 70 + 71 + static int cmp_int_key (union hash_key a, union hash_key b) 72 + { 73 + if (a.intkey == b.intkey) 74 + return 0; 75 + if (a.intkey < b.intkey) 76 + return -1; 77 + return 1; 78 + } 79 + 80 + static HASH *new_hash (int nelem) 55 81 { 56 82 HASH *table = safe_malloc (sizeof (HASH)); 57 83 if (nelem == 0) 58 84 nelem = 2; 59 85 table->nelem = nelem; 60 86 table->table = safe_calloc (nelem, sizeof (struct hash_elem *)); 87 + return table; 88 + } 89 + 90 + HASH *hash_create (int nelem, int lower) 91 + { 92 + HASH *table = new_hash (nelem); 61 93 if (lower) 62 94 { 63 - table->hash_string = hash_case_string; 64 - table->cmp_string = mutt_strcasecmp; 95 + table->gen_hash = gen_case_string_hash; 96 + table->cmp_key = cmp_case_string_key; 65 97 } 66 98 else 67 99 { 68 - table->hash_string = hash_string; 69 - table->cmp_string = mutt_strcmp; 100 + table->gen_hash = gen_string_hash; 101 + table->cmp_key = cmp_string_key; 70 102 } 71 103 return table; 72 104 } 73 105 106 + HASH *int_hash_create (int nelem) 107 + { 108 + HASH *table = new_hash (nelem); 109 + table->gen_hash = gen_int_hash; 110 + table->cmp_key = cmp_int_key; 111 + return table; 112 + } 113 + 74 114 /* table hash table to update 75 115 * key key to hash on 76 116 * data data to associate with `key' 77 117 * allow_dup if nonzero, duplicate keys are allowed in the table 78 118 */ 79 - int hash_insert (HASH * table, const char *key, void *data, int allow_dup) 119 + static int union_hash_insert (HASH * table, union hash_key key, void *data, int allow_dup) 80 120 { 81 121 struct hash_elem *ptr; 82 122 unsigned int h; 83 123 84 124 ptr = (struct hash_elem *) safe_malloc (sizeof (struct hash_elem)); 85 - h = table->hash_string ((unsigned char *) key, table->nelem); 125 + h = table->gen_hash (key, table->nelem); 86 126 ptr->key = key; 87 127 ptr->data = data; 88 128 ··· 98 138 99 139 for (tmp = table->table[h], last = NULL; tmp; last = tmp, tmp = tmp->next) 100 140 { 101 - r = table->cmp_string (tmp->key, key); 141 + r = table->cmp_key (tmp->key, key); 102 142 if (r == 0) 103 143 { 104 144 FREE (&ptr); ··· 116 156 return h; 117 157 } 118 158 119 - void *hash_find_hash (const HASH * table, int hash, const char *key) 159 + int hash_insert (HASH * table, const char *strkey, void *data, int allow_dup) 160 + { 161 + union hash_key key; 162 + key.strkey = strkey; 163 + return union_hash_insert (table, key, data, allow_dup); 164 + } 165 + 166 + int int_hash_insert (HASH * table, unsigned int intkey, void *data, int allow_dup) 167 + { 168 + union hash_key key; 169 + key.intkey = intkey; 170 + return union_hash_insert (table, key, data, allow_dup); 171 + } 172 + 173 + static void *union_hash_find (const HASH *table, union hash_key key) 120 174 { 121 - struct hash_elem *ptr = table->table[hash]; 175 + int hash; 176 + struct hash_elem *ptr; 177 + 178 + if (!table) 179 + return NULL; 180 + 181 + hash = table->gen_hash (key, table->nelem); 182 + ptr = table->table[hash]; 122 183 for (; ptr; ptr = ptr->next) 123 184 { 124 - if (table->cmp_string (key, ptr->key) == 0) 185 + if (table->cmp_key (key, ptr->key) == 0) 125 186 return (ptr->data); 126 187 } 127 188 return NULL; 128 189 } 129 190 130 - void hash_delete_hash (HASH * table, int hash, const char *key, const void *data, 191 + void *hash_find (const HASH *table, const char *strkey) 192 + { 193 + union hash_key key; 194 + key.strkey = strkey; 195 + return union_hash_find (table, key); 196 + } 197 + 198 + void *int_hash_find (const HASH *table, unsigned int intkey) 199 + { 200 + union hash_key key; 201 + key.intkey = intkey; 202 + return union_hash_find (table, key); 203 + } 204 + 205 + struct hash_elem *hash_find_bucket (const HASH *table, const char *strkey) 206 + { 207 + union hash_key key; 208 + int hash; 209 + 210 + if (!table) 211 + return NULL; 212 + 213 + key.strkey = strkey; 214 + hash = table->gen_hash (key, table->nelem); 215 + return table->table[hash]; 216 + } 217 + 218 + static void union_hash_delete (HASH *table, union hash_key key, const void *data, 131 219 void (*destroy) (void *)) 132 220 { 133 - struct hash_elem *ptr = table->table[hash]; 134 - struct hash_elem **last = &table->table[hash]; 221 + int hash; 222 + struct hash_elem *ptr, **last; 223 + 224 + if (!table) 225 + return; 226 + 227 + hash = table->gen_hash (key, table->nelem); 228 + ptr = table->table[hash]; 229 + last = &table->table[hash]; 135 230 136 - while (ptr) 231 + while (ptr) 137 232 { 138 233 if ((data == ptr->data || !data) 139 - && table->cmp_string (ptr->key, key) == 0) 234 + && table->cmp_key (ptr->key, key) == 0) 140 235 { 141 236 *last = ptr->next; 142 237 if (destroy) 143 238 destroy (ptr->data); 144 239 FREE (&ptr); 145 - 240 + 146 241 ptr = *last; 147 242 } 148 243 else ··· 153 248 } 154 249 } 155 250 251 + void hash_delete (HASH *table, const char *strkey, const void *data, 252 + void (*destroy) (void *)) 253 + { 254 + union hash_key key; 255 + key.strkey = strkey; 256 + union_hash_delete (table, key, data, destroy); 257 + } 258 + 259 + void int_hash_delete (HASH *table, unsigned int intkey, const void *data, 260 + void (*destroy) (void *)) 261 + { 262 + union hash_key key; 263 + key.intkey = intkey; 264 + union_hash_delete (table, key, data, destroy); 265 + } 266 + 156 267 /* ptr pointer to the hash table to be freed 157 268 * destroy() function to call to free the ->data member (optional) 158 269 */ 159 270 void hash_destroy (HASH **ptr, void (*destroy) (void *)) 160 271 { 161 272 int i; 162 - HASH *pptr = *ptr; 273 + HASH *pptr; 163 274 struct hash_elem *elem, *tmp; 164 275 276 + if (!ptr || !*ptr) 277 + return; 278 + 279 + pptr = *ptr; 165 280 for (i = 0 ; i < pptr->nelem; i++) 166 281 { 167 282 for (elem = pptr->table[i]; elem; )
+23 -10
hash.h
··· 19 19 #ifndef _HASH_H 20 20 #define _HASH_H 21 21 22 + union hash_key 23 + { 24 + const char *strkey; 25 + unsigned int intkey; 26 + }; 27 + 22 28 struct hash_elem 23 29 { 24 - const char *key; 30 + union hash_key key; 25 31 void *data; 26 32 struct hash_elem *next; 27 33 }; ··· 30 36 { 31 37 int nelem; 32 38 struct hash_elem **table; 33 - unsigned int (*hash_string)(const unsigned char *, unsigned int); 34 - int (*cmp_string)(const char *, const char *); 39 + unsigned int (*gen_hash)(union hash_key, unsigned int); 40 + int (*cmp_key)(union hash_key, union hash_key); 35 41 } 36 42 HASH; 37 43 38 - #define hash_find(table, key) hash_find_hash(table, table->hash_string ((unsigned char *)key, table->nelem), key) 44 + HASH *hash_create (int nelem, int lower); 45 + HASH *int_hash_create (int nelem); 46 + 47 + int hash_insert (HASH * table, const char *key, void *data, int allow_dup); 48 + int int_hash_insert (HASH *table, unsigned int key, void *data, int allow_dup); 39 49 40 - #define hash_delete(table,key,data,destroy) hash_delete_hash(table, table->hash_string ((unsigned char *)key, table->nelem), key, data, destroy) 50 + void *hash_find (const HASH *table, const char *key); 51 + void *int_hash_find (const HASH *table, unsigned int key); 41 52 42 - HASH *hash_create (int nelem, int lower); 43 - int hash_insert (HASH * table, const char *key, void *data, int allow_dup); 44 - void *hash_find_hash (const HASH * table, int hash, const char *key); 45 - void hash_delete_hash (HASH * table, int hash, const char *key, const void *data, 46 - void (*destroy) (void *)); 53 + struct hash_elem *hash_find_bucket (const HASH *table, const char *key); 54 + 55 + void hash_delete (HASH * table, const char *key, const void *data, 56 + void (*destroy) (void *)); 57 + void int_hash_delete (HASH * table, unsigned int key, const void *data, 58 + void (*destroy) (void *)); 59 + 47 60 void hash_destroy (HASH ** hash, void (*destroy) (void *)); 48 61 49 62 #endif
+1 -4
thread.c
··· 416 416 { 417 417 struct hash_elem *ptr; 418 418 THREAD *tmp, *last = NULL; 419 - unsigned int hash; 420 419 LIST *subjects = NULL, *oldlist; 421 420 time_t date = 0; 422 421 ··· 424 423 425 424 while (subjects) 426 425 { 427 - hash = ctx->subj_hash->hash_string ((unsigned char *) subjects->data, 428 - ctx->subj_hash->nelem); 429 - for (ptr = ctx->subj_hash->table[hash]; ptr; ptr = ptr->next) 426 + for (ptr = hash_find_bucket (ctx->subj_hash, subjects->data); ptr; ptr = ptr->next) 430 427 { 431 428 tmp = ((HEADER *) ptr->data)->thread; 432 429 if (tmp != cur && /* don't match the same message */