From 3c97263990648f808010220a080f4f9a4e846dac Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 14 Jun 2018 16:48:22 +0200 Subject: [PATCH 6/7] util: add _adcli_strv_remove_unsorted Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014 --- library/adprivate.h | 4 ++ library/adutil.c | 21 ++++++++ library/seq.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++--- library/seq.h | 12 +++++ 4 files changed, 179 insertions(+), 7 deletions(-) diff --git a/library/adprivate.h b/library/adprivate.h index 7485249..bc9df6d 100644 --- a/library/adprivate.h +++ b/library/adprivate.h @@ -111,6 +111,10 @@ char ** _adcli_strv_add (char **strv, char *string, int *length) GNUC_WARN_UNUSED; +void _adcli_strv_remove_unsorted (char **strv, + const char *string, + int *length); + void _adcli_strv_free (char **strv); int _adcli_strv_has (char **strv, diff --git a/library/adutil.c b/library/adutil.c index a27bd68..6334b52 100644 --- a/library/adutil.c +++ b/library/adutil.c @@ -221,6 +221,27 @@ _adcli_strv_add (char **strv, return seq_push (strv, length, string); } +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) + +void +_adcli_strv_remove_unsorted (char **strv, + const char *string, + int *length) +{ + int len; + + return_if_fail (string != NULL); + + if (!length) { + len = seq_count (strv); + length = &len; + } + + return seq_remove_unsorted (strv, length, discard_const (string), + (seq_compar)strcasecmp, free); +} + + int _adcli_strv_has (char **strv, const char *str) diff --git a/library/seq.c b/library/seq.c index 627dcaf..8e7475d 100644 --- a/library/seq.c +++ b/library/seq.c @@ -111,6 +111,24 @@ seq_push (seq_voidp sequence, return seq; } +static int +linear_search (void **seq, + int low, + int high, + void *match, + seq_compar compar) +{ + int at; + + for (at = low; at < high; at++) { + if (compar (match, seq[at]) == 0) { + break; + } + } + + return at; +} + static int binary_search (void **seq, int low, @@ -171,12 +189,13 @@ seq_insert (seq_voidp sequence, return seq; } -void -seq_remove (seq_voidp sequence, - int *length, - void *match, - seq_compar compar, - seq_destroy destroy) +static void +seq_remove_int (seq_voidp sequence, + int *length, + void *match, + seq_search search, + seq_compar compar, + seq_destroy destroy) { void **seq = sequence; int at; @@ -187,7 +206,7 @@ seq_remove (seq_voidp sequence, assert (match != NULL); len = *length; - at = binary_search (seq, 0, len, match, compar); + at = search (seq, 0, len, match, compar); /* We have a matching value */ if (at < len && compar (match, seq[at]) == 0) { @@ -201,6 +220,26 @@ seq_remove (seq_voidp sequence, *length = len; } +void +seq_remove (seq_voidp sequence, + int *length, + void *match, + seq_compar compar, + seq_destroy destroy) +{ + return seq_remove_int (sequence, length, match, binary_search, compar, destroy); +} + +void +seq_remove_unsorted (seq_voidp sequence, + int *length, + void *match, + seq_compar compar, + seq_destroy destroy) +{ + return seq_remove_int (sequence, length, match, linear_search, compar, destroy); +} + void seq_filter (seq_voidp sequence, int *length, @@ -430,6 +469,99 @@ test_remove (void) seq_free (seq, NULL); } +static void +test_remove_unsorted (void) +{ + void **seq = NULL; + int len = 0; + + seq = seq_push (seq, &len, "3"); + seq = seq_push (seq, &len, "5"); + seq = seq_push (seq, &len, "1"); + seq = seq_push (seq, &len, "4"); + seq = seq_push (seq, &len, "2"); + + assert_str_eq (seq[0], "3"); + assert_str_eq (seq[1], "5"); + assert_str_eq (seq[2], "1"); + assert_str_eq (seq[3], "4"); + assert_str_eq (seq[4], "2"); + assert (seq[5] == NULL); + assert_num_eq (len, 5); + + seq_remove_unsorted (seq, &len, "3", (seq_compar)strcmp, NULL); + seq_remove_unsorted (seq, &len, "2", (seq_compar)strcmp, NULL); + + assert_str_eq (seq[0], "5"); + assert_str_eq (seq[1], "1"); + assert_str_eq (seq[2], "4"); + assert (seq[3] == NULL); + assert_num_eq (len, 3); + + seq_free (seq, NULL); +} + +static void +test_remove_first (void) +{ + void **seq = NULL; + int len = 0; + + seq = seq_insert (seq, &len, "3", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "5", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "1", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "4", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "2", (seq_compar)strcmp, NULL); + + assert_str_eq (seq[0], "1"); + assert_str_eq (seq[1], "2"); + assert_str_eq (seq[2], "3"); + assert_str_eq (seq[3], "4"); + assert_str_eq (seq[4], "5"); + assert (seq[5] == NULL); + assert_num_eq (len, 5); + + seq_remove (seq, &len, "1", (seq_compar)strcmp, NULL); + + assert_str_eq (seq[0], "2"); + assert_str_eq (seq[1], "3"); + assert_str_eq (seq[2], "4"); + assert_str_eq (seq[3], "5"); + assert (seq[4] == NULL); + assert_num_eq (len, 4); + + seq_free (seq, NULL); +} + +static void +test_remove_last (void) +{ + void **seq = NULL; + int len = 0; + + seq = seq_insert (seq, &len, "3", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "1", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "4", (seq_compar)strcmp, NULL); + seq = seq_insert (seq, &len, "2", (seq_compar)strcmp, NULL); + + assert_str_eq (seq[0], "1"); + assert_str_eq (seq[1], "2"); + assert_str_eq (seq[2], "3"); + assert_str_eq (seq[3], "4"); + assert (seq[4] == NULL); + assert_num_eq (len, 4); + + seq_remove (seq, &len, "4", (seq_compar)strcmp, NULL); + + assert_str_eq (seq[0], "1"); + assert_str_eq (seq[1], "2"); + assert_str_eq (seq[2], "3"); + assert (seq[3] == NULL); + assert_num_eq (len, 3); + + seq_free (seq, NULL); +} + static int compar_even (void *match, void *value) @@ -631,6 +763,9 @@ main (int argc, test_func (test_insert, "/seq/insert"); test_func (test_insert_destroys, "/seq/insert_destroys"); test_func (test_remove, "/seq/remove"); + test_func (test_remove_unsorted, "/seq/remove_unsorted"); + test_func (test_remove_first, "/seq/remove_first"); + test_func (test_remove_last, "/seq/remove_last"); test_func (test_remove_destroys, "/seq/remove_destroys"); test_func (test_filter, "/seq/filter"); test_func (test_filter_null, "/seq/filter_null"); diff --git a/library/seq.h b/library/seq.h index 694965b..5d48848 100644 --- a/library/seq.h +++ b/library/seq.h @@ -44,6 +44,12 @@ typedef void * (* seq_copy) (void *value); typedef void (* seq_destroy) (void *value); +typedef int (* seq_search) (void **seq, + int low, + int high, + void *match, + seq_compar compar); + seq_voidp seq_push (seq_voidp seq, int *length, void *value) WARN_UNUSED; @@ -62,6 +68,12 @@ void seq_remove (seq_voidp seq, seq_compar compar, seq_destroy destroy); +void seq_remove_unsorted (seq_voidp seq, + int *length, + void *match, + seq_compar compar, + seq_destroy destroy); + seq_voidp seq_lookup (seq_voidp seq, int *length, void *match, -- 2.14.4