diff options
author | Xavier Chantry <shiningxc@gmail.com> | 2009-09-07 01:15:39 +0200 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2009-09-07 15:16:50 -0500 |
commit | 43e16b373be50ca142e2b39055906194049c3686 (patch) | |
tree | 156519aa952d8b8f04bb89dea2335ef5279be7e7 | |
parent | cb1d4195bf7436240dbcc865113f3be19354aa34 (diff) |
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.c | 81 |
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 |