From: Carl Worth <cworth@cworth.org>
Date: Mon, 18 Dec 2006 05:38:43 +0000 (-0800)
Subject: dict: Add dict_for_each functions
X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=a5187a6b925208af24014e40290f323f8ecd9be7;p=wordgame

dict: Add dict_for_each functions

These new functions allow the caller to pass a callback to act on
all entries within a dictionary.
---

diff --git a/dict.c b/dict.c
index a920293..d7edc47 100644
--- a/dict.c
+++ b/dict.c
@@ -209,12 +209,14 @@ trie_count (trie_t		*trie,
 }
 
 static int
-trie_print (trie_t		*trie,
-	    string_t		*string,
-	    trie_predicate_t	 predicate,
-	    int			 length,
-	    int			 min_length,
-	    int			 max_length)
+trie_for_each (trie_t		*trie,
+	       string_t		*string,
+	       trie_predicate_t	 predicate,
+	       int		 length,
+	       int		 min_length,
+	       int		 max_length,
+	       dict_action_t	 action,
+	       void		*closure)
 {
     char c;
     int i;
@@ -223,7 +225,8 @@ trie_print (trie_t		*trie,
     if (length >= min_length && (predicate) (trie))
     {
 	count = 1;
-	printf ("%s ", string->s);
+
+	action (closure, string->s);
     }
 
     if (length == max_length)
@@ -237,8 +240,9 @@ 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 (trie->next[i], string, predicate,
+				length + 1, min_length, max_length,
+				action, closure);
 	string_chop (string);
     }
 
@@ -371,16 +375,20 @@ dict_count (dict_t			*dict,
 }
 
 int
-dict_print (dict_t *dict)
+dict_for_each_if (dict_t			*dict,
+		  dict_action_t			 action,
+		  void				*closure,
+		  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;
+    count = trie_for_each (dict, &string, dict_predicate,
+			   0, 0, -1, action, closure);
 
     string_fini (&string);
 
@@ -388,26 +396,18 @@ dict_print (dict_t *dict)
 }
 
 int
-dict_print_if (dict_t			*dict,
-	       dict_entry_predicate_t	 predicate)
+dict_for_each (dict_t		*dict,
+	       dict_action_t	 action,
+	       void		*closure)
 {
-    int count;
-    string_t string;
-
-    string_init (&string);
-
-    dict_entry_predicate = predicate;
-    count = trie_print (dict, &string, dict_predicate,
-			0, 0, -1);
-
-    string_fini (&string);
-
-    return count;
+    return dict_for_each_if (dict, action, closure, NULL);
 }
 
 int
-dict_print_by_length_if (dict_t			*dict,
-			 dict_entry_predicate_t	 predicate)
+dict_for_each_by_length_if (dict_t			*dict,
+			    dict_action_t		 action,
+			    void			*closure,
+			    dict_entry_predicate_t	 predicate)
 {
     int length, total, words, count = 0;
     string_t string;
@@ -420,12 +420,11 @@ dict_print_by_length_if (dict_t			*dict,
 
     length = 1;
     do {
-	words = trie_print (dict, &string, dict_predicate,
-			    0, length, length);
-	if (words) {
-	    printf ("\n");
+	words = trie_for_each (dict, &string, dict_predicate,
+			       0, length, length,
+			       action, closure);
+	if (words)
 	    count += words;
-	}
 	length++;
     } while (count < total);
 
@@ -433,3 +432,67 @@ dict_print_by_length_if (dict_t			*dict,
     
     return count;
 }
+
+int
+dict_for_each_by_length (dict_t		*dict,
+			 dict_action_t	 action,
+			 void		*closure)
+{
+    return dict_for_each_by_length_if (dict, action, closure, NULL);
+}
+
+static void
+dict_action_print (void *closure, char *word)
+{
+    int *length_of_last = closure;
+    int length = strlen (word);
+
+    if (length == *length_of_last)
+	printf(" ");
+    else if (*length_of_last)
+	printf("\n");
+
+    printf ("%s", word);
+
+    *length_of_last = length;
+}
+
+int
+dict_print (dict_t *dict)
+{
+    int length_of_last = 0;
+
+    return dict_for_each (dict,
+			  dict_action_print, &length_of_last);
+}
+
+int
+dict_print_by_length (dict_t *dict)
+{
+    int length_of_last = 0;
+
+    return dict_for_each_by_length (dict,
+				    dict_action_print, &length_of_last);
+}
+
+int
+dict_print_if (dict_t			*dict,
+	       dict_entry_predicate_t	 predicate)
+{
+    int length_of_last = 0;
+
+    return dict_for_each_if (dict,
+			     dict_action_print, &length_of_last,
+			     predicate);
+}
+
+int
+dict_print_by_length_if (dict_t			*dict,
+			 dict_entry_predicate_t	 predicate)
+{
+    int length_of_last = 0;
+
+    return dict_for_each_by_length_if (dict,
+				       dict_action_print, &length_of_last,
+				       predicate);
+}
diff --git a/dict.h b/dict.h
index af21015..6152c72 100644
--- a/dict.h
+++ b/dict.h
@@ -82,6 +82,9 @@ dict_count (dict_t			*dict,
 int
 dict_print (dict_t *dict);
 
+int
+dict_print_by_length (dict_t *dict);
+
 int
 dict_print_if (dict_t			*dict,
 	       dict_entry_predicate_t	 predicate);
@@ -90,6 +93,31 @@ int
 dict_print_by_length_if (dict_t			*dict,
 			 dict_entry_predicate_t	 predicate);
 
+/* More general callback-based iteration of all entries */
+typedef void (* dict_action_t) (void *closure, char *word);
+
+int
+dict_for_each (dict_t		*dict,
+	       dict_action_t	 action,
+	       void		*closure);
+
+int
+dict_for_each_by_length (dict_t		*dict,
+			 dict_action_t	 action,
+			 void		*closure);
+
+int
+dict_for_each_if (dict_t			*dict,
+		  dict_action_t			 action,
+		  void				*closure,
+		  dict_entry_predicate_t	 predicate);
+
+int
+dict_for_each_by_length_if (dict_t			*dict,
+			    dict_action_t		 action,
+			    void			*closure,
+			    dict_entry_predicate_t	 predicate);
+
 /* Character-by-character perusal of the dictionary */
 dict_cursor_t
 dict_root (dict_t *dict);