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_print (trie_t *trie,
186 trie_predicate_t predicate)
192 if (trie->flags & TRIE_FLAGS_IS_WORD
193 && (predicate == NULL || predicate (trie)))
196 printf ("%s ", string->s);
199 /* Loop over each element, appending the character and recursing. */
200 for (i = 0; i < 26; i++) {
201 if (trie->next[i] == NULL)
204 c = TRIE_INDEX_TO_CHAR (i);
206 string_append_char (string, c);
207 count += trie_print (trie->next[i], string, predicate);
208 string_chop (string);
215 trie_seen_predicate (trie_t *trie)
217 return (trie->flags & TRIE_FLAGS_SEEN);
221 trie_print_seen (trie_t *trie, string_t *word)
223 return trie_print (trie, word, trie_seen_predicate);
227 trie_unseen_predicate (trie_t *trie)
229 return (! trie_seen_predicate (trie));
233 trie_print_unseen (trie_t *trie, string_t *word)
235 return trie_print (trie, word, trie_unseen_predicate);
239 dict_init (dict_t *dict)
245 dict_fini (dict_t *dict)
251 dict_add_word (dict_t *dict,
254 trie_add (dict, word);
258 dict_add_words_from_file (dict_t *dict,
259 const char *filename)
263 size_t line_size = 0;
266 file = fopen (filename, "r");
268 fprintf (stderr, "Error: failed to open %s: %s\n",
269 filename, strerror (errno));
274 bytes_read = getline (&line, &line_size, file);
275 if (bytes_read == -1)
278 dict_add_word (dict, line);
287 dict_lookup (dict_t *dict,
292 trie = trie_find (dict, word);
299 /* Yes, this function is rather silly. I have it here in the hope that
300 * it could be used for some better type-checking, (if only C had such
303 dict_root (dict_t *dict)
309 dict_cursor_next (dict_cursor_t cursor,
312 trie_t *trie = cursor;
315 return DICT_CURSOR_NIL;
317 return trie->next[TRIE_CHAR_TO_INDEX (next)];
321 dict_cursor_resolve (dict_cursor_t cursor)
325 if (cursor == DICT_CURSOR_NIL)
333 dict_print (dict_t *dict)
337 string_init (&string);
339 trie_print (dict, &string, NULL);
341 string_fini (&string);