}
+/**
+ * virStringListRemove:
+ * @strings: a NULL-terminated array of strings
+ * @item: string to remove
+ *
+ * Remove every occurrence of @item in list of @strings.
+ */
+void
+virStringListRemove(char ***strings,
+ const char *item)
+{
+ size_t r, w = 0;
+
+ if (!strings || !*strings)
+ return;
+
+ for (r = 0; (*strings)[r]; r++) {
+ if (STREQ((*strings)[r], item)) {
+ VIR_FREE((*strings)[r]);
+ continue;
+ }
+ if (r != w)
+ (*strings)[w] = (*strings)[r];
+ w++;
+ }
+
+ if (w == 0) {
+ VIR_FREE(*strings);
+ } else {
+ (*strings)[w] = NULL;
+ ignore_value(VIR_REALLOC_N(*strings, w + 1));
+ }
+}
+
+
/**
* virStringListFree:
* @str_array: a NULL-terminated array of strings to free
char **virStringListAdd(const char **strings,
const char *item);
+void virStringListRemove(char ***strings,
+ const char *item);
void virStringListFree(char **strings);
void virStringListFreeCount(char **strings,
}
+static int testRemove(const void *args)
+{
+ const struct testSplitData *data = args;
+ char **list = NULL;
+ size_t ntokens;
+ size_t i;
+ int ret = -1;
+
+ if (!(list = virStringSplitCount(data->string, data->delim,
+ data->max_tokens, &ntokens))) {
+ VIR_DEBUG("Got no tokens at all");
+ return -1;
+ }
+
+ for (i = 0; data->tokens[i]; i++) {
+ virStringListRemove(&list, data->tokens[i]);
+ if (virStringListHasString((const char **) list, data->tokens[i])) {
+ virFilePrintf(stderr, "Not removed %s", data->tokens[i]);
+ 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 *
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 };