[pacman-dev] [PATCH 5/6] rewrite strreplace

Xavier Chantry shiningxc at gmail.com
Mon Sep 7 14:34:28 EDT 2009


* 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 <shiningxc at gmail.com>
---
 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



More information about the pacman-dev mailing list