2 * Copyright © 2006 Carl Worth
4 * This program is free software; you can redistribute it and\/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA."
19 /* Portably, schmortability. I want ease of programming. */
36 fprintf (stderr, "Error: out of memory\n");
44 xrealloc (void *ptr, size_t size)
48 res = realloc (ptr, size);
50 fprintf (stderr, "Error: out of memory\n");
61 if (s[len - 1] == '\n')
66 string_init (string_t *string)
74 string_fini (string_t *string)
83 string_append_char (string_t *string, char c)
85 if (string->size == 0) {
87 string->s = xmalloc (string->size);
92 if (string->len + 1 == string->size) {
94 string->s = xrealloc (string->s, string->size);
97 string->s[string->len++] = c;
98 string->s[string->len] = '\0';
102 string_chop (string_t *string)
104 if (string->len == 0)
107 string->s[--string->len] = '\0';
111 trie_init (trie_t *trie)
115 for (i = 0; i < 26; i++)
116 trie->next[i] = NULL;
120 trie_destroy (trie_t *trie);
123 trie_fini (trie_t *trie)
127 for (i = 0; i < 26; i++)
129 trie_destroy (trie->next[i]);
137 trie = xmalloc (sizeof (trie_t));
145 trie_destroy (trie_t *trie)
153 trie_add (trie_t *trie,
154 const char *word_chunk)
156 char c = word_chunk[0];
160 trie->flags |= TRIE_FLAGS_IS_WORD;
164 i = TRIE_CHAR_TO_INDEX (c);
165 if (trie->next[i] == NULL)
166 trie->next[i] = trie_create ();
168 trie_add (trie->next[i], word_chunk + 1);
172 trie_find (trie_t *trie,
173 const char *word_chunk)
175 const char *s = word_chunk;
178 trie = trie->next[TRIE_CHAR_TO_INDEX (*s++)];
184 trie_count (trie_t *trie,
185 trie_predicate_t predicate)
190 if ((predicate) (trie))
193 for (i = 0; i < 26; i++) {
194 if (trie->next[i] == NULL)
197 count += trie_count (trie->next[i], predicate);
204 trie_print (trie_t *trie,
206 trie_predicate_t predicate,
215 if (length >= min_length && (predicate) (trie))
218 printf ("%s ", string->s);
221 if (length == max_length)
224 /* Loop over each element, appending the character and recursing. */
225 for (i = 0; i < 26; i++) {
226 if (trie->next[i] == NULL)
229 c = TRIE_INDEX_TO_CHAR (i);
231 string_append_char (string, c);
232 count += trie_print (trie->next[i], string, predicate,
233 length + 1, min_length, max_length);
234 string_chop (string);
241 dict_init (dict_t *dict)
247 dict_fini (dict_t *dict)
253 dict_add_word (dict_t *dict,
256 trie_add (dict, word);
260 dict_add_words_from_file (dict_t *dict,
261 const char *filename)
265 size_t line_size = 0;
268 file = fopen (filename, "r");
270 fprintf (stderr, "Error: failed to open %s: %s\n",
271 filename, strerror (errno));
276 bytes_read = getline (&line, &line_size, file);
277 if (bytes_read == -1)
280 dict_add_word (dict, line);
289 dict_lookup (dict_t *dict,
294 trie = trie_find (dict, word);
301 /* Yes, this function is rather silly. I have it here in the hope that
302 * it could be used for some better type-checking, (if only C had such
305 dict_root (dict_t *dict)
311 dict_cursor_next (dict_cursor_t cursor,
314 trie_t *trie = cursor;
317 return DICT_CURSOR_NIL;
319 return trie->next[TRIE_CHAR_TO_INDEX (next)];
323 dict_cursor_resolve (dict_cursor_t cursor)
327 if (cursor == DICT_CURSOR_NIL)
334 /* XXX: This static function pointer is really nasty and definitely
335 * un-thread safe. What I really want it a lambda so I can construct a
336 * composite predicate on the fly. Oh well... */
337 static dict_entry_predicate_t dict_entry_predicate = NULL;
340 dict_predicate (trie_t *trie)
344 entry = dict_cursor_resolve (trie);
345 if (! DICT_ENTRY_IS_WORD (entry))
348 if (dict_entry_predicate)
349 return (dict_entry_predicate) (*entry);
355 dict_count (dict_t *dict,
356 dict_entry_predicate_t predicate)
358 dict_entry_predicate = predicate;
359 return trie_count (dict, dict_predicate);
363 dict_print (dict_t *dict)
368 string_init (&string);
370 dict_entry_predicate = NULL;
371 count = trie_print (dict, &string, dict_predicate,
374 string_fini (&string);
380 dict_print_if (dict_t *dict,
381 dict_entry_predicate_t predicate)
386 string_init (&string);
388 dict_entry_predicate = predicate;
389 count = trie_print (dict, &string, dict_predicate,
392 string_fini (&string);
398 dict_print_by_length_if (dict_t *dict,
399 dict_entry_predicate_t predicate)
401 int length, total, words, count = 0;
404 string_init (&string);
406 dict_entry_predicate = predicate;
408 total = trie_count (dict, dict_predicate);
412 words = trie_print (dict, &string, dict_predicate,
419 } while (count < total);
421 string_fini (&string);