]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add virStringReplace method for substring replacement
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 19 Feb 2014 20:30:46 +0000 (20:30 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 24 Feb 2014 10:51:22 +0000 (10:51 +0000)
Add a virStringReplace method to virstring.{h,c} to perform
substring matching and replacement

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/libvirt_private.syms
src/util/virstring.c
src/util/virstring.h
tests/virstringtest.c

index c7c8c6a3bf970ca9d40fa7127d5b10f3598c34a1..7b0ca980cd2b2e093fe7125bfe20cb3b21ed1553 100644 (file)
@@ -1798,6 +1798,7 @@ virStringArrayHasString;
 virStringFreeList;
 virStringJoin;
 virStringListLength;
+virStringReplace;
 virStringSearch;
 virStringSortCompare;
 virStringSortRevCompare;
index 008293f5a98a398ccb0da0f96000b609cefad312..b3912f33318853df38f8924eed30504b9e743e47 100644 (file)
@@ -749,3 +749,48 @@ cleanup:
     }
     return ret;
 }
+
+/**
+ * virStringReplace:
+ * @haystack: the source string to process
+ * @oldneedle: the substring to locate
+ * @newneedle: the substring to insert
+ *
+ * Search @haystack and replace all occurences of @oldneedle with @newneedle.
+ *
+ * Returns: a new string with all the replacements, or NULL on error
+ */
+char *
+virStringReplace(const char *haystack,
+                 const char *oldneedle,
+                 const char *newneedle)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    const char *tmp1, *tmp2;
+    size_t oldneedlelen = strlen(oldneedle);
+    size_t newneedlelen = strlen(newneedle);
+
+    tmp1 = haystack;
+    tmp2 = NULL;
+
+    while (tmp1) {
+        tmp2 = strstr(tmp1, oldneedle);
+
+        if (tmp2) {
+            virBufferAdd(&buf, tmp1, (tmp2 - tmp1));
+            virBufferAdd(&buf, newneedle, newneedlelen);
+            tmp2 += oldneedlelen;
+        } else {
+            virBufferAdd(&buf, tmp1, -1);
+        }
+
+        tmp1 = tmp2;
+    }
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
+}
index 8efc80cdc79a0b81e86da5ba0763505bae9433be..5b77581aaadb11e83b46e6c6222784e50f0a7c2f 100644 (file)
@@ -232,5 +232,10 @@ ssize_t virStringSearch(const char *str,
                         char ***matches)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4);
 
+char *virStringReplace(const char *haystack,
+                       const char *oldneedle,
+                       const char *newneedle)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
 
 #endif /* __VIR_STRING_H__ */
index f6c44053cb9a7042b8e93d42c1a6b84387cb3839..8d45e7134e003b388cdfad11f425ebbb53abf74b 100644 (file)
@@ -338,6 +338,39 @@ testStringSearch(const void *opaque ATTRIBUTE_UNUSED)
     return ret;
 }
 
+
+struct stringReplaceData {
+    const char *haystack;
+    const char *oldneedle;
+    const char *newneedle;
+    const char *result;
+};
+
+static int
+testStringReplace(const void *opaque ATTRIBUTE_UNUSED)
+{
+    const struct stringReplaceData *data = opaque;
+    char *result;
+    int ret = -1;
+
+    result = virStringReplace(data->haystack,
+                              data->oldneedle,
+                              data->newneedle);
+
+    if (STRNEQ_NULLABLE(data->result, result)) {
+        fprintf(stderr, "Expected '%s' but got '%s'\n",
+                data->result, NULLSTR(result));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(result);
+    return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -428,6 +461,37 @@ mymain(void)
     const char *matches3[] = { "foo", "bar" };
     TEST_SEARCH("1foo2bar3eek", "([a-z]+)", 2, 2, matches3, false);
 
+#define TEST_REPLACE(h, o, n, r)                                        \
+    do {                                                                \
+        struct stringReplaceData data = {                               \
+            .haystack = h,                                              \
+            .oldneedle = o,                                             \
+            .newneedle = n,                                             \
+            .result = r                                                 \
+        };                                                              \
+        if (virtTestRun("virStringReplace " h, testStringReplace, &data) < 0) \
+            ret = -1;                                                   \
+    } while (0)
+
+    /* no matches */
+    TEST_REPLACE("foo", "bar", "eek", "foo");
+
+    /* complete match */
+    TEST_REPLACE("foo", "foo", "bar", "bar");
+
+    /* middle match */
+    TEST_REPLACE("foobarwizz", "bar", "eek", "fooeekwizz");
+
+    /* many matches */
+    TEST_REPLACE("foofoofoofoo", "foo", "bar", "barbarbarbar");
+
+    /* many matches */
+    TEST_REPLACE("fooooofoooo", "foo", "bar", "barooobaroo");
+
+    /* different length old/new needles */
+    TEST_REPLACE("fooooofoooo", "foo", "barwizzeek", "barwizzeekooobarwizzeekoo");
+    TEST_REPLACE("fooooofoooo", "foooo", "foo", "fooofoo");
+
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }