Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virstring.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ tests/virstringtest.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bc6588969..3d4da7356 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2467,6 +2467,7 @@ virStringListGetFirstWithPrefix; virStringListHasString; virStringListJoin; virStringListLength; +virStringListRemove; virStringReplace; virStringSearch; virStringSortCompare; diff --git a/src/util/virstring.c b/src/util/virstring.c index 629f8ca32..96786db7f 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -202,6 +202,56 @@ virStringListAdd(const char **strings, } +/** + * virStringListRemove: + * @strings: a NULL-terminated array of strings + * @newStrings: new NULL-terminated array of strings + * @item: string to remove + * + * Creates new strings list with all strings duplicated except + * for every occurrence of @item. Callers is responsible for + * freeing both @strings and returned list. + * + * Returns the number of items in the new list (excluding NULL + * anchor), -1 on error. + */ +int +virStringListRemove(const char **strings, + char ***newStrings, + const char *item) +{ + char **ret = NULL; + size_t i, j = 0; + + for (i = 0; strings && strings[i]; i++) { + if (STRNEQ(strings[i], item)) + j++; + } + + if (!j) { + *newStrings = NULL; + return 0; + } + + if (VIR_ALLOC_N(ret, j + 1) < 0) + goto error; + + for (i = 0, j = 0; strings[i]; i++) { + if (STREQ(strings[i], item)) + continue; + if (VIR_STRDUP(ret[j], strings[i]) < 0) + goto error; + j++; + } + + *newStrings = ret; + return j; + error: + virStringListFree(ret); + return -1; +} + + /** * virStringListFree: * @str_array: a NULL-terminated array of strings to free diff --git a/src/util/virstring.h b/src/util/virstring.h index da9d35cca..88eacd404 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -43,6 +43,9 @@ char *virStringListJoin(const char **strings, char **virStringListAdd(const char **strings, const char *item); +int virStringListRemove(const char **strings, + char ***newStrings, + const char *item); void virStringListFree(char **strings); void virStringListFreeCount(char **strings, diff --git a/tests/virstringtest.c b/tests/virstringtest.c index 43657c84c..63a5e90db 100644 --- a/tests/virstringtest.c +++ b/tests/virstringtest.c @@ -162,6 +162,60 @@ static int testAdd(const void *args) } +static int testRemove(const void *args) +{ + const struct testSplitData *data = args; + char **list = NULL; + size_t ntokens; + size_t i; + int ret = -1; + size_t listLenght; + + if (!(list = virStringSplitCount(data->string, data->delim, + data->max_tokens, &ntokens))) { + VIR_DEBUG("Got no tokens at all"); + return -1; + } + + listLenght = virStringListLength((const char **) list); + + for (i = 0; data->tokens[i]; i++) { + char **tmp; + int rv; + size_t j, toRemove = 0; + + for (j = 0; list && list[j]; j++) + if (STREQ(list[j], data->tokens[i])) + toRemove++; + + if ((rv = virStringListRemove((const char **) list, + &tmp, data->tokens[i])) < 0) + goto cleanup; + virStringListFree(list); + list = tmp; + tmp = NULL; + listLenght -= toRemove; + + if (rv != listLenght) { + virFilePrintf(stderr, + "Unexpected length of new list: %d expected %zu", + rv, listLenght); + goto cleanup; + } + } + + if (list && list[0]) { + virFilePrintf(stderr, "Not removed all tokens: %s", list[0]); + goto cleanup; + } + + ret = 0; + cleanup: + virStringListFree(list); + return ret; +} + + static bool fail; static const char * @@ -636,6 +690,8 @@ mymain(void) ret = -1; \ if (virTestRun("Add " #str, testAdd, &joinData) < 0) \ ret = -1; \ + if (virTestRun("Remove " #str, testRemove, &splitData) < 0) \ + ret = -1; \ } while (0) const char *tokens1[] = { NULL }; -- 2.11.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list