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

Manuel VIVES manuel.vives at diateam.net
Thu Jun 20 08:34:49 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 6511044..09ad1c1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1829,6 +1829,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 1937f82..9526a7d 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -608,3 +608,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 34ffae1..6d44778 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -166,4 +166,10 @@ int virStrndup(char **dest, const char *src, ssize_t n, bool report, int domcode
 
 size_t virStringListLength(char **strings);
 
+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