Re: [libvirt] [PATCH 2/2] Add virStringReplace method for substring replacement

2014-02-20 Thread Ján Tomko
On 02/19/2014 09:36 PM, Daniel P. Berrange wrote:
 Add a virStringReplace method to virstring.{h,c} to perform
 substring matching and replacement
 
 Signed-off-by: Daniel P. Berrange berra...@redhat.com
 ---
  src/libvirt_private.syms |  1 +
  src/util/virstring.c | 44 +++-
  src/util/virstring.h |  5 
  tests/virstringtest.c| 59 
 
  4 files changed, 108 insertions(+), 1 deletion(-)
 
 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
 index f26190d..f7379a2 100644
 --- a/src/libvirt_private.syms
 +++ b/src/libvirt_private.syms
 @@ -1794,6 +1794,7 @@ virStringArrayHasString;
  virStringFreeList;
  virStringJoin;
  virStringListLength;
 +virStringReplace;
  virStringSearch;
  virStringSortCompare;
  virStringSortRevCompare;
 diff --git a/src/util/virstring.c b/src/util/virstring.c
 index 67a87d3..3e42b06 100644
 --- a/src/util/virstring.c
 +++ b/src/util/virstring.c
 @@ -619,7 +619,6 @@ size_t virStringListLength(char **strings)
  return i;
  }
  
 -
  /**
   * virStringSortCompare:
   *

Unrelated whitespace change.

 @@ -747,3 +746,46 @@ 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))

virBufferError doesn't report an error, but I think this function should.

 +return NULL;
 +
 +return virBufferContentAndReset(buf);
 +}

 diff --git a/tests/virstringtest.c b/tests/virstringtest.c
 index b8c6115..43023d5 100644
 --- a/tests/virstringtest.c
 +++ b/tests/virstringtest.c
 @@ -428,6 +460,33 @@ 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(fof, foo, bar, barooobaroo);
 +
  return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
  }
  

A test with different length of old and new needles would be nice.

ACK with error reporting.

Jan




signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 2/2] Add virStringReplace method for substring replacement

2014-02-19 Thread Daniel P. Berrange
Add a virStringReplace method to virstring.{h,c} to perform
substring matching and replacement

Signed-off-by: Daniel P. Berrange berra...@redhat.com
---
 src/libvirt_private.syms |  1 +
 src/util/virstring.c | 44 +++-
 src/util/virstring.h |  5 
 tests/virstringtest.c| 59 
 4 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f26190d..f7379a2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1794,6 +1794,7 @@ virStringArrayHasString;
 virStringFreeList;
 virStringJoin;
 virStringListLength;
+virStringReplace;
 virStringSearch;
 virStringSortCompare;
 virStringSortRevCompare;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 67a87d3..3e42b06 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -619,7 +619,6 @@ size_t virStringListLength(char **strings)
 return i;
 }
 
-
 /**
  * virStringSortCompare:
  *
@@ -747,3 +746,46 @@ 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))
+return NULL;
+
+return virBufferContentAndReset(buf);
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 8efc80c..5b77581 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -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__ */
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index b8c6115..43023d5 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -338,6 +338,38 @@ 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:
+return ret;
+}
+
+
 static int
 mymain(void)
 {
@@ -428,6 +460,33 @@ 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(fof, foo, bar, barooobaroo);
+
 return