summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Chantry <shiningxc@gmail.com>2009-09-07 01:15:39 +0200
committerDan McGee <dan@archlinux.org>2009-09-07 15:16:50 -0500
commit43e16b373be50ca142e2b39055906194049c3686 (patch)
tree156519aa952d8b8f04bb89dea2335ef5279be7e7
parentcb1d4195bf7436240dbcc865113f3be19354aa34 (diff)
downloadpacman-43e16b373be50ca142e2b39055906194049c3686.tar.xz
rewrite strreplace
* 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@gmail.com> Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--src/pacman/util.c81
1 files changed, 49 insertions, 32 deletions
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 6af82290..1e8515c6 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