* just do one malloc call

* p = realloc(p, new_size) was not good
(see http://www.iso-9899.info/wiki/Why_not_realloc)

* use more efficient strncpy instead of strncat

Signed-off-by: Xavier Chantry <[email protected]>
---
 src/pacman/util.c |   81 ++++++++++++++++++++++++++++++++---------------------
 1 files changed, 49 insertions(+), 32 deletions(-)

diff --git a/src/pacman/util.c b/src/pacman/util.c
index 6af8229..1e8515c 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -335,48 +335,65 @@ char *strtrim(char *str)
        return(str);
 }
 
-/* Helper function for strreplace */
-static void _strnadd(char **str, const char *append, unsigned int count)
-{
-       if(*str) {
-               *str = realloc(*str, strlen(*str) + count + 1);
-       } else {
-               *str = calloc(sizeof(char), count + 1);
-       }
-
-       strncat(*str, append, count);
-}
-
 /* Replace all occurances of 'needle' with 'replace' in 'str', returning
  * a new string (must be free'd) */
 char *strreplace(const char *str, const char *needle, const char *replace)
 {
-       const char *p, *q;
-       p = q = str;
+       const char *p = NULL, *q = NULL;
+       char *newstr = NULL, *newp = NULL;
+       alpm_list_t *i = NULL, *list = NULL;
+       size_t needlesz = strlen(needle), replacesz = strlen(replace);
+       size_t newsz;
 
-       char *newstr = NULL;
-       unsigned int needlesz = strlen(needle),
-                                                        replacesz = 
strlen(replace);
+       if(!str) {
+               return(NULL);
+       }
 
-       while (1) {
+       p = str;
+       q = strstr(p, needle);
+       while(q) {
+               list = alpm_list_add(list, (char *)q);
+               p = q + needlesz;
                q = strstr(p, needle);
-               if(!q) { /* not found */
-                       if(*p) {
-                               /* add the rest of 'p' */
-                               _strnadd(&newstr, p, strlen(p));
-                       }
-                       break;
-               } else { /* found match */
-                       if(q > p){
-                               /* add chars between this occurance and last 
occurance, if any */
-                               _strnadd(&newstr, p, q - p);
-                       }
-                       _strnadd(&newstr, replace, replacesz);
-                       p = q + needlesz;
+       }
+
+       /* no occurences of needle found */
+       if(!list) {
+               return(strdup(str));
+       }
+       /* size of new string = size of old string + "number of occurences of 
needle"
+        * x "size difference between replace and needle" */
+       newsz = strlen(str) + 1 +
+               alpm_list_count(list) * (replacesz - needlesz);
+       newstr = malloc(newsz);
+       if(!newstr) {
+               return(NULL);
+       }
+       *newstr = '\0';
+
+       p = str;
+       newp = newstr;
+       for(i = list; i; i = alpm_list_next(i)) {
+               q = alpm_list_getdata(i);
+               if(q > p){
+                       /* add chars between this occurence and last occurence, 
if any */
+                       strncpy(newp, p, q - p);
+                       newp += q - p;
                }
+               strncpy(newp, replace, replacesz);
+               newp += replacesz;
+               p = q + needlesz;
+       }
+       alpm_list_free(list);
+
+       if(*p) {
+               /* add the rest of 'p' */
+               strcpy(newp, p);
+               newp += strlen(p);
        }
+       *newp = '\0';
 
-       return newstr;
+       return(newstr);
 }
 
 /** Splits a string into a list of strings using the chosen character as
-- 
1.6.4.2


Reply via email to