Commit d806b526 d806b526667f3dc3f3f0d549bf2de65be338ebea by Sergey Poznyakoff

Reimplement using mu_assoc_t

1 parent aaa480e7
Showing 1 changed file with 115 additions and 220 deletions
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002, 2005, 2006 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2005, 2006, 2007 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -18,260 +18,111 @@ ...@@ -18,260 +18,111 @@
18 18
19 #include "mail.h" 19 #include "mail.h"
20 20
21 static void alias_print (char *name); 21 typedef struct _alias *alias_t;
22 static void alias_print_group (char *name, mu_list_t list);
23 static int alias_create (char *name, mu_list_t *plist);
24 static int alias_lookup (char *name, mu_list_t *plist);
25
26 /*
27 * a[lias] [alias [address...]]
28 * g[roup] [alias [address...]]
29 */
30
31 int
32 mail_alias (int argc, char **argv)
33 {
34 if (argc == 1)
35 alias_print (NULL);
36 else if (argc == 2)
37 alias_print (argv[1]);
38 else
39 {
40 mu_list_t list;
41
42 if (alias_create (argv[1], &list))
43 return 1;
44
45 argc --;
46 argv ++;
47 while (--argc)
48 util_slist_add (&list, *++argv);
49 }
50 return 0;
51 }
52
53 typedef struct _alias alias_t;
54 22
55 struct _alias 23 struct _alias
56 { 24 {
57 char *name;
58 mu_list_t list; 25 mu_list_t list;
59 }; 26 };
60 27
61 /* Hash sizes. These are prime numbers, the distance between each 28 static mu_assoc_t aliases;
62 pair of them grows exponentially, starting from 64.
63 Hopefully no one will need more than 32797 aliases, and even if
64 someone will, it is easy enough to add more numbers to the sequence. */
65 static unsigned int hash_size[] =
66 {
67 37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411, 32797,
68 };
69 /* Maximum number of re-hashes: */
70 static unsigned int max_rehash = sizeof (hash_size) / sizeof (hash_size[0]);
71 static alias_t *aliases; /* Table of aliases */
72 static unsigned int hash_num; /* Index to hash_size table */
73
74 static unsigned int hash (char *name);
75 static int alias_rehash (void);
76 static alias_t *alias_lookup_or_install (char *name, int install);
77 static void alias_print_group (char *name, mu_list_t list);
78
79 unsigned
80 hash (char *name)
81 {
82 unsigned i;
83 29
84 for (i = 0; *name; name++) { 30 static void
85 i <<= 1; 31 alias_free (void *data)
86 i ^= *(unsigned char*) name;
87 }
88 return i % hash_size[hash_num];
89 }
90
91 int
92 alias_rehash ()
93 { 32 {
94 alias_t *old_aliases = aliases; 33 alias_t al = data;
95 alias_t *ap; 34 util_slist_destroy (&al->list);
96 unsigned int i;
97
98 if (++hash_num >= max_rehash)
99 {
100 util_error (_("alias hash table full"));
101 return 1;
102 }
103
104 aliases = xcalloc (hash_size[hash_num], sizeof (aliases[0]));
105 if (old_aliases)
106 {
107 for (i = 0; i < hash_size[hash_num-1]; i++)
108 {
109 if (old_aliases[i].name)
110 {
111 ap = alias_lookup_or_install (old_aliases[i].name, 1);
112 ap->name = old_aliases[i].name;
113 ap->list = old_aliases[i].list;
114 }
115 }
116 free (old_aliases);
117 }
118 return 0;
119 } 35 }
120 36
121 alias_t * 37 static void
122 alias_lookup_or_install (char *name, int install) 38 alias_print_group (const char *name, alias_t al)
123 { 39 {
124 unsigned i, pos; 40 fprintf (ofile, "%s ", name);
125 41 util_slist_print (al->list, 0);
126 if (!aliases) 42 fprintf (ofile, "\n");
127 {
128 if (install)
129 {
130 if (alias_rehash ())
131 return NULL;
132 }
133 else
134 return NULL;
135 }
136
137 pos = hash (name);
138
139 for (i = pos; aliases[i].name;)
140 {
141 if (strcmp(aliases[i].name, name) == 0)
142 return &aliases[i];
143 if (++i >= hash_size[hash_num])
144 i = 0;
145 if (i == pos)
146 break;
147 }
148
149 if (!install)
150 return NULL;
151
152 if (aliases[i].name == NULL)
153 return &aliases[i];
154
155 if (alias_rehash ())
156 return NULL;
157
158 return alias_lookup_or_install (name, install);
159 } 43 }
160 44
161 static int 45 static alias_t
162 alias_lookup (char *name, mu_list_t *plist) 46 alias_lookup (const char *name)
163 { 47 {
164 alias_t *ap = alias_lookup_or_install (name, 0); 48 return mu_assoc_ref (aliases, name);
165 if (ap)
166 {
167 *plist = ap->list;
168 return 1;
169 }
170 return 0;
171 } 49 }
172 50
173 void 51 static void
174 alias_print (char *name) 52 alias_print (char *name)
175 { 53 {
176 if (!name) 54 if (!name)
177 { 55 {
178 unsigned int i; 56 mu_iterator_t itr;
179 57
180 if (!aliases) 58 if (!aliases)
181 return; 59 return;
182 60
183 for (i = 0; i < hash_size[hash_num]; i++) 61 mu_assoc_get_iterator (aliases, &itr);
62 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
63 mu_iterator_next (itr))
184 { 64 {
185 if (aliases[i].name) 65 const char *name;
186 alias_print_group (aliases[i].name, aliases[i].list); 66 alias_t al;
67 if (mu_iterator_current_kv (itr, (const void **)&name, (void**)&al))
68 continue;
69 alias_print_group (name, al);
187 } 70 }
188 } 71 }
189 else 72 else
190 { 73 {
191 mu_list_t list; 74 alias_t al;
192 75
193 if (!alias_lookup (name, &list)) 76 al = alias_lookup (name);
77 if (!al)
194 { 78 {
195 util_error (_("\"%s\": not a group"), name); 79 util_error (_("\"%s\": not a group"), name);
196 return; 80 return;
197 } 81 }
198 alias_print_group (name, list); 82 alias_print_group (name, al);
199 } 83 }
200 } 84 }
201 85
202 int 86 static int
203 alias_create (char *name, mu_list_t *plist) 87 alias_create (const char *name, alias_t *al)
204 { 88 {
205 alias_t *ap = alias_lookup_or_install (name, 1); 89 int rc;
206 if (!ap)
207 return 1;
208 90
209 if (!ap->name) 91 if (!aliases)
210 { 92 {
211 /* new entry */ 93 mu_assoc_create (&aliases, sizeof (struct _alias));
212 if (mu_list_create (&ap->list)) 94 mu_assoc_set_free (aliases, alias_free);
213 return 1;
214 ap->name = strdup (name);
215 if (!ap->name)
216 return 1;
217 } 95 }
218 96
219 *plist = ap->list; 97 rc = mu_assoc_ref_install (aliases, name, (void**) al);
220 98 if (rc == MU_ERR_EXISTS)
221 return 0; 99 return 0;
222 } 100 if (rc == 0)
223 101 return mu_list_create (&(*al)->list);
224 void 102 return 1;
225 alias_print_group (char *name, mu_list_t list)
226 {
227 fprintf (ofile, "%s ", name);
228 util_slist_print (list, 0);
229 fprintf (ofile, "\n");
230 } 103 }
231 104
232 void 105 void
233 alias_destroy (char *name) 106 alias_destroy (const char *name)
234 { 107 {
235 unsigned int i, j, r; 108 mu_assoc_remove (aliases, name);
236 alias_t *alias = alias_lookup_or_install (name, 0);
237 if (!alias)
238 return;
239 free (alias->name);
240 util_slist_destroy (&alias->list);
241
242 for (i = alias - aliases;;)
243 {
244 aliases[i].name = NULL;
245 j = i;
246
247 do
248 {
249 if (++i >= hash_size[hash_num])
250 i = 0;
251 if (!aliases[i].name)
252 return;
253 r = hash(aliases[i].name);
254 }
255 while ((j < r && r <= i) || (i < j && j < r) || (r <= i && i < j));
256
257 aliases[j] = aliases[i];
258 }
259 } 109 }
260 110
111
261 static void 112 static void
262 recursive_alias_expand (char *name, mu_list_t exlist, mu_list_t origlist) 113 recursive_alias_expand (char *name, mu_list_t exlist, mu_list_t origlist)
263 { 114 {
264 mu_list_t alist; 115 alias_t al;
265 mu_iterator_t itr; 116 mu_iterator_t itr;
266 117
267 if (!alias_lookup (name, &alist)) 118 if ((al = alias_lookup (name)) == NULL)
268 { 119 {
269 if (mu_list_locate (exlist, name, NULL) == MU_ERR_NOENT) 120 if (mu_list_locate (exlist, name, NULL) == MU_ERR_NOENT)
270 mu_list_append (exlist, name); 121 mu_list_append (exlist, name);
271 return; 122 return;
272 } 123 }
273 124
274 mu_list_get_iterator (alist, &itr); 125 mu_list_get_iterator (al->list, &itr);
275 for (mu_iterator_first (itr); 126 for (mu_iterator_first (itr);
276 !mu_iterator_is_done (itr); 127 !mu_iterator_is_done (itr);
277 mu_iterator_next (itr)) 128 mu_iterator_next (itr))
...@@ -298,8 +149,9 @@ string_comp (const void *item, const void *value) ...@@ -298,8 +149,9 @@ string_comp (const void *item, const void *value)
298 char * 149 char *
299 alias_expand (char *name) 150 alias_expand (char *name)
300 { 151 {
152 alias_t al;
301 mu_list_t list; 153 mu_list_t list;
302 154
303 if (util_getenv (NULL, "recursivealiases", Mail_env_boolean, 0) == 0) 155 if (util_getenv (NULL, "recursivealiases", Mail_env_boolean, 0) == 0)
304 { 156 {
305 char *s; 157 char *s;
...@@ -327,55 +179,98 @@ alias_expand (char *name) ...@@ -327,55 +179,98 @@ alias_expand (char *name)
327 return s; 179 return s;
328 } 180 }
329 181
330 if (!alias_lookup (name, &list)) 182 if ((al = alias_lookup (name)) == NULL)
331 return NULL; 183 return NULL;
332 return util_slist_to_string (list, ","); 184 return util_slist_to_string (al->list, ",");
333 } 185 }
334 186
187
335 struct alias_iterator 188 struct alias_iterator
336 { 189 {
190 mu_iterator_t itr;
337 const char *prefix; 191 const char *prefix;
338 int prefixlen; 192 int prefixlen;
339 int pos; 193 int pos;
340 }; 194 };
341 195
342 const char * 196 const char *
343 alias_iterate_next (alias_iterator_t itr) 197 alias_iterate_next (alias_iterator_t atr)
344 { 198 {
345 int i; 199 while (!mu_iterator_is_done (atr->itr))
346 for (i = itr->pos; i < hash_size[hash_num]; i++) 200 {
347 if (aliases[i].name 201 const char *name;
348 && strlen (aliases[i].name) >= itr->prefixlen 202 alias_t al;
349 && strncmp (aliases[i].name, itr->prefix, itr->prefixlen) == 0) 203
350 { 204 if (mu_iterator_current_kv (atr->itr, (const void **)&name, (void**)&al))
351 itr->pos = i + 1; 205 continue;
352 return aliases[i].name; 206 mu_iterator_next (atr->itr);
353 } 207 if (strlen (name) >= atr->prefixlen
208 && strncmp (name, atr->prefix, atr->prefixlen) == 0)
209 return name;
210 }
354 return NULL; 211 return NULL;
355 } 212 }
356 213
357 const char * 214 const char *
358 alias_iterate_first (const char *prefix, alias_iterator_t *pc) 215 alias_iterate_first (const char *prefix, alias_iterator_t *pc)
359 { 216 {
360 struct alias_iterator *itr; 217 mu_iterator_t itr;
361 218 alias_iterator_t atr;
219
362 if (!aliases) 220 if (!aliases)
363 { 221 {
364 *pc = NULL; 222 *pc = NULL;
365 return NULL; 223 return NULL;
366 } 224 }
367 225
368 itr = xmalloc (sizeof *itr); 226 if (mu_assoc_get_iterator (aliases, &itr))
369 itr->prefix = prefix; 227 return NULL;
370 itr->prefixlen = strlen (prefix); 228 mu_iterator_first (itr);
371 itr->pos = 0; 229 atr = xmalloc (sizeof *atr);
372 *pc = itr; 230 atr->prefix = prefix;
373 return alias_iterate_next (itr); 231 atr->prefixlen = strlen (prefix);
232 atr->pos = 0;
233 atr->itr = itr;
234 *pc = atr;
235
236 return alias_iterate_next (atr);
374 } 237 }
375 238
376 void 239 void
377 alias_iterate_end (alias_iterator_t *pc) 240 alias_iterate_end (alias_iterator_t *pc)
378 { 241 {
242 mu_iterator_destroy (&(*pc)->itr);
379 free (*pc); 243 free (*pc);
380 *pc = NULL; 244 *pc = NULL;
381 } 245 }
246
247
248
249 /*
250 * a[lias] [alias [address...]]
251 * g[roup] [alias [address...]]
252 */
253
254 int
255 mail_alias (int argc, char **argv)
256 {
257 if (argc == 1)
258 alias_print (NULL);
259 else if (argc == 2)
260 alias_print (argv[1]);
261 else
262 {
263 alias_t al;
264
265 if (alias_create (argv[1], &al))
266 return 1;
267
268 argc--;
269 argv++;
270 while (--argc)
271 util_slist_add (&al->list, *++argv);
272 }
273 return 0;
274 }
275
276
......