string_list: add a new function, filter_string_list()
This function allows entries that don't match a specified criterion to be discarded from a string_list while preserving the order of the remaining entries. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Sep 12, 2012 at 16:04 UTC
eb5f0c7a616531a024a582b72ca6d8775ff98d46
5 files changed
+96
Documentation/technical/api-string-list.txt
+11
@@ -33,6 +33,9 @@ member (you need this if you add things later) and you should set the
33
. Can remove individual items of an unsorted list using
34
`unsorted_string_list_delete_item`.
35
36
+. Can remove items not matching a criterion from a sorted or unsorted
37
+ list using `filter_string_list`.
38
+
39
. Finally it should free the list using `string_list_clear`.
40
41
Example:
@@ -61,6 +64,14 @@ Functions
64
65
* General ones (works with sorted and unsorted lists as well)
66
67
+`filter_string_list`::
68
+
69
+ Apply a function to each item in a list, retaining only the
70
+ items for which the function returns true. If free_util is
71
+ true, call free() on the util members of any items that have
72
+ to be deleted. Preserve the order of the items that are
73
+ retained.
74
+
75
`print_string_list`::
76
77
Dump a string_list to stdout, useful mainly for debugging purposes. It
string-list.c
+17
@@ -102,6 +102,23 @@ int for_each_string_list(struct string_list *list,
102
return ret;
103
}
104
105
+void filter_string_list(struct string_list *list, int free_util,
106
+ string_list_each_func_t want, void *cb_data)
107
+{
108
+ int src, dst = 0;
109
+ for (src = 0; src < list->nr; src++) {
110
+ if (want(&list->items[src], cb_data)) {
111
+ list->items[dst++] = list->items[src];
112
+ } else {
113
+ if (list->strdup_strings)
114
+ free(list->items[src].string);
115
+ if (free_util)
116
+ free(list->items[src].util);
117
+ }
118
+ }
119
+ list->nr = dst;
120
+}
121
+
122
void string_list_clear(struct string_list *list, int free_util)
123
{
124
if (list->items) {
string-list.h
+9
@@ -29,6 +29,15 @@ int for_each_string_list(struct string_list *list,
29
#define for_each_string_list_item(item,list) \
30
for (item = (list)->items; item < (list)->items + (list)->nr; ++item)
31
32
+/*
33
+ * Apply want to each item in list, retaining only the ones for which
34
+ * the function returns true. If free_util is true, call free() on
35
+ * the util members of any items that have to be deleted. Preserve
36
+ * the order of the items that are retained.
37
+ */
38
+void filter_string_list(struct string_list *list, int free_util,
39
+ string_list_each_func_t want, void *cb_data);
40
+
41
42
/* Use these functions only on sorted lists: */
43
int string_list_has_string(const struct string_list *list, const char *string);
t/t0063-string-list.sh
+11
@@ -60,4 +60,15 @@ test_split ":" ":" "-1" <<EOF
60
[1]: ""
61
EOF
62
63
+test_expect_success "test filter_string_list" '
64
+ test "x-" = "x$(test-string-list filter - y)" &&
65
+ test "x-" = "x$(test-string-list filter no y)" &&
66
+ test yes = "$(test-string-list filter yes y)" &&
67
+ test yes = "$(test-string-list filter no:yes y)" &&
68
+ test yes = "$(test-string-list filter yes:no y)" &&
69
+ test y1:y2 = "$(test-string-list filter y1:y2 y)" &&
70
+ test y2:y1 = "$(test-string-list filter y2:y1 y)" &&
71
+ test "x-" = "x$(test-string-list filter x1:x2 y)"
72
+'
73
+
74
test_done
test-string-list.c
+48
@@ -1,6 +1,20 @@
1
#include "cache.h"
2
#include "string-list.h"
3
4
+/*
5
+ * Parse an argument into a string list. arg should either be a
6
+ * ':'-separated list of strings, or "-" to indicate an empty string
7
+ * list (as opposed to "", which indicates a string list containing a
8
+ * single empty string). list->strdup_strings must be set.
9
+ */
10
+void parse_string_list(struct string_list *list, const char *arg)
11
+{
12
+ if (!strcmp(arg, "-"))
13
+ return;
14
+
15
+ (void)string_list_split(list, arg, ':', -1);
16
+}
17
+
18
void write_list(const struct string_list *list)
19
{
20
int i;
@@ -8,6 +22,25 @@ void write_list(const struct string_list *list)
22
printf("[%d]: \"%s\"\n", i, list->items[i].string);
23
}
24
25
+void write_list_compact(const struct string_list *list)
26
+{
27
+ int i;
28
+ if (!list->nr)
29
+ printf("-\n");
30
+ else {
31
+ printf("%s", list->items[0].string);
32
+ for (i = 1; i < list->nr; i++)
33
+ printf(":%s", list->items[i].string);
34
+ printf("\n");
35
+ }
36
+}
37
+
38
+int prefix_cb(struct string_list_item *item, void *cb_data)
39
+{
40
+ const char *prefix = (const char *)cb_data;
41
+ return !prefixcmp(item->string, prefix);
42
+}
43
+
44
int main(int argc, char **argv)
45
{
46
if (argc == 5 && !strcmp(argv[1], "split")) {
@@ -39,6 +72,21 @@ int main(int argc, char **argv)
72
return 0;
73
}
74
75
+ if (argc == 4 && !strcmp(argv[1], "filter")) {
76
+ /*
77
+ * Retain only the items that have the specified prefix.
78
+ * Arguments: list|- prefix
79
+ */
80
+ struct string_list list = STRING_LIST_INIT_DUP;
81
+ const char *prefix = argv[3];
82
+
83
+ parse_string_list(&list, argv[2]);
84
+ filter_string_list(&list, 0, prefix_cb, (void *)prefix);
85
+ write_list_compact(&list);
86
+ string_list_clear(&list, 0);
87
+ return 0;
88
+ }
89
+
90
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
91
argv[1] ? argv[1] : "(there was none)");
92
return 1;