Reimplement using mu_assoc_t
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 | ... | ... |
-
Please register or sign in to post a comment