From eb5f0c7a616531a024a582b72ca6d8775ff98d46 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Wed, 12 Sep 2012 16:04:44 +0200 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- Documentation/technical/api-string-list.txt | 11 +++++ string-list.c | 17 ++++++++ string-list.h | 9 ++++ t/t0063-string-list.sh | 11 +++++ test-string-list.c | 48 +++++++++++++++++++++ 5 files changed, 96 insertions(+) diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt index 1dcad47f7..300b30109 100644 --- a/Documentation/technical/api-string-list.txt +++ b/Documentation/technical/api-string-list.txt @@ -33,6 +33,9 @@ member (you need this if you add things later) and you should set the . Can remove individual items of an unsorted list using `unsorted_string_list_delete_item`. +. Can remove items not matching a criterion from a sorted or unsorted + list using `filter_string_list`. + . Finally it should free the list using `string_list_clear`. Example: @@ -61,6 +64,14 @@ Functions * General ones (works with sorted and unsorted lists as well) +`filter_string_list`:: + + Apply a function to each item in a list, retaining only the + items for which the function returns true. If free_util is + true, call free() on the util members of any items that have + to be deleted. Preserve the order of the items that are + retained. + `print_string_list`:: Dump a string_list to stdout, useful mainly for debugging purposes. It diff --git a/string-list.c b/string-list.c index acb1f5b6d..179fde421 100644 --- a/string-list.c +++ b/string-list.c @@ -102,6 +102,23 @@ int for_each_string_list(struct string_list *list, return ret; } +void filter_string_list(struct string_list *list, int free_util, + string_list_each_func_t want, void *cb_data) +{ + int src, dst = 0; + for (src = 0; src < list->nr; src++) { + if (want(&list->items[src], cb_data)) { + list->items[dst++] = list->items[src]; + } else { + if (list->strdup_strings) + free(list->items[src].string); + if (free_util) + free(list->items[src].util); + } + } + list->nr = dst; +} + void string_list_clear(struct string_list *list, int free_util) { if (list->items) { diff --git a/string-list.h b/string-list.h index dc5fbc80a..7d18e622e 100644 --- a/string-list.h +++ b/string-list.h @@ -29,6 +29,15 @@ int for_each_string_list(struct string_list *list, #define for_each_string_list_item(item,list) \ for (item = (list)->items; item < (list)->items + (list)->nr; ++item) +/* + * Apply want to each item in list, retaining only the ones for which + * the function returns true. If free_util is true, call free() on + * the util members of any items that have to be deleted. Preserve + * the order of the items that are retained. + */ +void filter_string_list(struct string_list *list, int free_util, + string_list_each_func_t want, void *cb_data); + /* Use these functions only on sorted lists: */ int string_list_has_string(const struct string_list *list, const char *string); diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh index fb8543075..a5f05cd20 100755 --- a/t/t0063-string-list.sh +++ b/t/t0063-string-list.sh @@ -60,4 +60,15 @@ test_split ":" ":" "-1" <strdup_strings must be set. + */ +void parse_string_list(struct string_list *list, const char *arg) +{ + if (!strcmp(arg, "-")) + return; + + (void)string_list_split(list, arg, ':', -1); +} + void write_list(const struct string_list *list) { int i; @@ -8,6 +22,25 @@ void write_list(const struct string_list *list) printf("[%d]: \"%s\"\n", i, list->items[i].string); } +void write_list_compact(const struct string_list *list) +{ + int i; + if (!list->nr) + printf("-\n"); + else { + printf("%s", list->items[0].string); + for (i = 1; i < list->nr; i++) + printf(":%s", list->items[i].string); + printf("\n"); + } +} + +int prefix_cb(struct string_list_item *item, void *cb_data) +{ + const char *prefix = (const char *)cb_data; + return !prefixcmp(item->string, prefix); +} + int main(int argc, char **argv) { if (argc == 5 && !strcmp(argv[1], "split")) { @@ -39,6 +72,21 @@ int main(int argc, char **argv) return 0; } + if (argc == 4 && !strcmp(argv[1], "filter")) { + /* + * Retain only the items that have the specified prefix. + * Arguments: list|- prefix + */ + struct string_list list = STRING_LIST_INIT_DUP; + const char *prefix = argv[3]; + + parse_string_list(&list, argv[2]); + filter_string_list(&list, 0, prefix_cb, (void *)prefix); + write_list_compact(&list); + string_list_clear(&list, 0); + return 0; + } + fprintf(stderr, "%s: unknown function name: %s\n", argv[0], argv[1] ? argv[1] : "(there was none)"); return 1; -- 2.26.2