X-Git-Url: https://git.cworth.org/git?p=wordgame;a=blobdiff_plain;f=dict.c;h=b2ad4952c9604f6990f095a35d846167499f38ad;hp=f975829c1877c74e1b85001c571fcbccbd2d8ccc;hb=a26e439b57a16e31a8fb67a079cbad659c21fd39;hpb=6717cd95edcf1332c81daaa6c608c293dc8ffb4a diff --git a/dict.c b/dict.c index f975829..b2ad495 100644 --- a/dict.c +++ b/dict.c @@ -16,31 +16,25 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA." */ -/* Portably, schmortability. I want ease of programming. */ -#define _GNU_SOURCE -#include -#include +#include "dict.h" + #include #include #include -#include "dict.h" - typedef struct _string { size_t size; char *s; size_t len; } string_t; -#define TRIE_FLAGS_IS_WORD (1<<0) - typedef bool_t (*trie_predicate_t) (trie_t *trie); #define TRIE_CHAR_TO_INDEX(c) (tolower (c) - 'a') #define TRIE_INDEX_TO_CHAR(i) (i + 'a') -void * +static void * xmalloc (size_t size) { void *res; @@ -54,7 +48,7 @@ xmalloc (size_t size) return res; } -void * +static void * xrealloc (void *ptr, size_t size) { void *res; @@ -68,7 +62,7 @@ xrealloc (void *ptr, size_t size) return res; } -void +static void chomp (char *s) { int len = strlen (s); @@ -78,7 +72,7 @@ chomp (char *s) s[len - 1] = '\0'; } -void +static void string_init (string_t *string) { string->size = 0; @@ -86,7 +80,7 @@ string_init (string_t *string) string->len = 0; } -void +static void string_fini (string_t *string) { string->size = 0; @@ -95,7 +89,7 @@ string_fini (string_t *string) string->len = 0; } -void +static void string_append_char (string_t *string, char c) { if (string->size == 0) { @@ -114,7 +108,7 @@ string_append_char (string_t *string, char c) string->s[string->len] = '\0'; } -void +static void string_chop (string_t *string) { if (string->len == 0) @@ -145,7 +139,7 @@ trie_fini (trie_t *trie) trie_destroy (trie->next[i]); } -trie_t * +static trie_t * trie_create (void) { trie_t *trie; @@ -165,26 +159,24 @@ trie_destroy (trie_t *trie) free (trie); } -void +static trie_t * trie_add (trie_t *trie, const char *word_chunk) { char c = word_chunk[0]; int i; - if (c == '\0') { - trie->flags |= TRIE_FLAGS_IS_WORD; - return; - } + if (c == '\0') + return trie; i = TRIE_CHAR_TO_INDEX (c); if (trie->next[i] == NULL) trie->next[i] = trie_create (); - trie_add (trie->next[i], word_chunk + 1); + return trie_add (trie->next[i], word_chunk + 1); } -trie_t * +static trie_t * trie_find (trie_t *trie, const char *word_chunk) { @@ -196,33 +188,36 @@ trie_find (trie_t *trie, return trie; } -int -trie_count (trie_t *trie, - trie_predicate_t predicate) +static int +trie_count_if (trie_t *trie, + trie_predicate_t predicate) { int i; int count = 0; - if ((predicate) (trie)) + if (predicate == NULL || (predicate) (trie)) count = 1; for (i = 0; i < 26; i++) { if (trie->next[i] == NULL) continue; - count += trie_count (trie->next[i], predicate); + count += trie_count_if (trie->next[i], predicate); } return count; } -int -trie_print (trie_t *trie, - string_t *string, - trie_predicate_t predicate, - int length, - int min_length, - int max_length) +static int +trie_for_each_of_length_if (trie_t *trie, + dict_action_t action, + void *closure, + int min_length, + int max_length, + trie_predicate_t predicate, + string_t *string, + int length) + { char c; int i; @@ -231,10 +226,12 @@ trie_print (trie_t *trie, if (length >= min_length && (predicate) (trie)) { count = 1; - printf ("%s ", string->s); + + if (action) + action (closure, string->s, &trie->flags); } - if (length == max_length) + if (max_length > 0 && length == max_length) return count; /* Loop over each element, appending the character and recursing. */ @@ -245,8 +242,11 @@ trie_print (trie_t *trie, c = TRIE_INDEX_TO_CHAR (i); string_append_char (string, c); - count += trie_print (trie->next[i], string, predicate, - length + 1, min_length, max_length); + count += trie_for_each_of_length_if (trie->next[i], + action, closure, + min_length, max_length, + predicate, + string, length + 1); string_chop (string); } @@ -269,7 +269,10 @@ void dict_add_word (dict_t *dict, const char *word) { - trie_add (dict, word); + trie_t *trie; + + trie = trie_add (dict, word); + trie->flags |= DICT_ENTRY_FLAG_IS_WORD; } void @@ -368,73 +371,144 @@ dict_predicate (trie_t *trie) } int -dict_count (dict_t *dict, - dict_entry_predicate_t predicate) +dict_count_if (dict_t *dict, + dict_entry_predicate_t predicate) { dict_entry_predicate = predicate; - return trie_count (dict, dict_predicate); + return trie_count_if (dict, dict_predicate); } int -dict_print (dict_t *dict) +dict_count (dict_t *dict) +{ + return dict_count_if (dict, NULL); +} + +int +dict_for_each_of_length_if (dict_t *dict, + dict_action_t action, + void *closure, + int min_length, + int max_length, + dict_entry_predicate_t predicate) { int count; string_t string; string_init (&string); - dict_entry_predicate = NULL; - count = trie_print (dict, &string, dict_predicate, - 0, 0, -1); + dict_entry_predicate = predicate; - string_fini (&string); + count = trie_for_each_of_length_if (dict, + action, closure, + min_length, max_length, + dict_predicate, + &string, 0); + string_fini (&string); + return count; } int -dict_print_if (dict_t *dict, - dict_entry_predicate_t predicate) +dict_for_each_of_length (dict_t *dict, + dict_action_t action, + void *closure, + int min_length, + int max_length) { - int count; - string_t string; + return dict_for_each_of_length_if (dict, + action, closure, + min_length, max_length, + NULL); +} - string_init (&string); +int +dict_for_each_if (dict_t *dict, + dict_action_t action, + void *closure, + dict_entry_predicate_t predicate) - dict_entry_predicate = predicate; - count = trie_print (dict, &string, dict_predicate, - 0, 0, -1); +{ + return dict_for_each_of_length_if (dict, + action, closure, + 0, 0, + predicate); +} - string_fini (&string); +int +dict_for_each (dict_t *dict, + dict_action_t action, + void *closure) +{ + return dict_for_each_if (dict, action, closure, NULL); +} - return count; +static void +dict_action_print (void *closure, char *word, dict_entry_t *entry) +{ + int *first = closure; + + if (*first) + *first = 0; + else + printf(" "); + + printf ("%s", word); } int -dict_print_by_length_if (dict_t *dict, +dict_print_of_length_if (dict_t *dict, + int min_length, + int max_length, dict_entry_predicate_t predicate) { - int length, total, words, count = 0; - string_t string; + int first = TRUE; - string_init (&string); + return dict_for_each_of_length_if (dict, + dict_action_print, &first, + min_length, max_length, + predicate); +} - dict_entry_predicate = predicate; +int +dict_print_by_length_if (dict_t *dict, + dict_entry_predicate_t predicate) +{ + int length, total, words, count = 0; - total = trie_count (dict, dict_predicate); + total = dict_count_if (dict, predicate); length = 1; do { - words = trie_print (dict, &string, dict_predicate, - 0, length, length); + words = dict_print_of_length_if (dict, length, length, predicate); if (words) { - printf ("\n"); count += words; + printf ("\n"); } length++; } while (count < total); - string_fini (&string); - return count; } + +int +dict_print_of_length (dict_t *dict, + int min_length, + int max_length) +{ + return dict_print_of_length_if (dict, min_length, max_length, NULL); +} + +int +dict_print_if (dict_t *dict, + dict_entry_predicate_t predicate) +{ + return dict_print_of_length_if (dict, 0, 0, predicate); +} + +int +dict_print (dict_t *dict) +{ + return dict_print_if (dict, NULL); +}