[libvirt] [RESEND PATCH 2/5] virstring.h/c: Util method for making some find and replace in strings

Manuel VIVES manuel.vives at diateam.net
Fri Jul 19 13:56:05 UTC 2013


---
 src/libvirt_private.syms |    1 +
 src/util/virstring.c     |  129 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virstring.h     |    6 +++
 3 files changed, 136 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 57a1b50..65e85d4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1901,6 +1901,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 1f4850e..81a3a4d 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -613,3 +613,132 @@ size_t virStringListLength(char **strings)
 
     return i;
 }
+
+/*
+ virStrReplace(haystack, haystacksize, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Resulting haystack contains no more than haystacksize characters (including the '\0').
+  If haystacksize is too small to make the replacements, do not modify haystack at all.
+
+ RETURN VALUES
+ virStrReplace() returns haystack on success and NULL on failure.
+ Failure means there was not enough room to replace all occurences of oldneedle.
+ Success is returned otherwise, even if no replacement is made.
+Methods found here: http://stackoverflow.com/a/12546318, author: Brandin
+*/
+char *
+virStrReplace(char *haystack, size_t haystacksize,
+                    const char *oldneedle, const char *newneedle)
+{
+    size_t oldneedle_len = strlen(oldneedle);
+    size_t newneedle_len = strlen(newneedle);
+    char *oldneedle_ptr;    // locates occurences of oldneedle
+    char *read_ptr;         // where to read in the haystack
+    char *write_ptr;        // where to write in the haystack
+    const char *oldneedle_last =  // the last character in oldneedle
+        oldneedle +
+        oldneedle_len - 1;
+
+    // Case 0: oldneedle is empty
+    if (oldneedle_len == 0)
+        return (char *)haystack;     // nothing to do;
+
+    // Case 1: newneedle is not longer than oldneedle
+    if (newneedle_len <= oldneedle_len) {
+        // Pass 1: Perform copy/replace using read_ptr and write_ptr
+        for (oldneedle_ptr = (char *)oldneedle,
+            read_ptr = haystack, write_ptr = haystack;
+            *read_ptr != '\0';
+            read_ptr++, write_ptr++)
+        {
+            *write_ptr = *read_ptr;
+            bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+                        oldneedle, oldneedle_last);
+            if (found)  {
+                // then perform update
+                write_ptr -= oldneedle_len;
+                memcpy(write_ptr+1, newneedle, newneedle_len);
+                write_ptr += newneedle_len;
+            }
+        }
+        *write_ptr = '\0';
+        return (char *)haystack;
+    }
+
+    // Case 2: newneedle is longer than oldneedle
+    else {
+        size_t diff_len =       // the amount of extra space needed
+            newneedle_len -     // to replace oldneedle with newneedle
+            oldneedle_len;      // in the expanded haystack
+
+        // Pass 1: Perform forward scan, updating write_ptr along the way
+        for (oldneedle_ptr = (char *)oldneedle,
+            read_ptr = haystack, write_ptr = haystack;
+            *read_ptr != '\0';
+            read_ptr++, write_ptr++)
+        {
+            bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+                        oldneedle, oldneedle_last);
+            if (found) {
+                // then advance write_ptr
+                write_ptr += diff_len;
+            }
+            if (write_ptr >= haystack+haystacksize)
+                return NULL; // no more room in haystack
+        }
+
+        // Pass 2: Walk backwards through haystack, performing copy/replace
+        for (oldneedle_ptr = (char *)oldneedle_last;
+            write_ptr >= haystack;
+            write_ptr--, read_ptr--)
+        {
+            *write_ptr = *read_ptr;
+            bool found = virLocateBackward(&oldneedle_ptr, read_ptr,
+                        oldneedle, oldneedle_last);
+            if (found) {
+                // then perform replacement
+                write_ptr -= diff_len;
+                memcpy(write_ptr, newneedle, newneedle_len);
+            }
+        }
+        return (char *)haystack;
+    }
+}
+
+// virLocateForward: compare needle_ptr and read_ptr to see if a match occured
+// needle_ptr is updated as appropriate for the next call
+// return true if match occured, false otherwise
+bool
+virLocateForward(char **needle_ptr, char *read_ptr,
+        const char *needle, const char *needle_last)
+{
+    if (**needle_ptr == *read_ptr) {
+        (*needle_ptr)++;
+        if (*needle_ptr > needle_last) {
+            *needle_ptr = (char *)needle;
+            return true;
+        }
+    }
+    else
+        *needle_ptr = (char *)needle;
+    return false;
+}
+
+// virLocateBackward: compare needle_ptr and read_ptr to see if a match occured
+// needle_ptr is updated as appropriate for the next call
+// return true if match occured, false otherwise
+bool
+virLocateBackward(char **needle_ptr, char *read_ptr,
+        const char *needle, const char *needle_last)
+{
+    if (**needle_ptr == *read_ptr) {
+        (*needle_ptr)--;
+        if (*needle_ptr < needle) {
+            *needle_ptr = (char *)needle_last;
+            return true;
+        }
+    }
+    else
+        *needle_ptr = (char *)needle_last;
+    return false;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..f69597f 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,10 @@ size_t virStringListLength(char **strings);
     virAsprintfInternal(false, 0, NULL, NULL, 0, \
                         strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, size_t haystacksize, const char *oldneedle, const char *newneedle);
+
+bool virLocateForward(char **needle_ptr, char *read_ptr, const char *needle, const char *needle_last);
+
+bool virLocateBackward(char **needle_ptr, char *read_ptr,const char *needle, const char *needle_last);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4




More information about the libvir-list mailing list