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>
This commit is contained in:
parent
cb1d4195bf
commit
43e16b373b
1 changed files with 52 additions and 35 deletions
|
@ -335,48 +335,65 @@ char *strtrim(char *str)
|
||||||
return(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
|
/* Replace all occurances of 'needle' with 'replace' in 'str', returning
|
||||||
* a new string (must be free'd) */
|
* a new string (must be free'd) */
|
||||||
char *strreplace(const char *str, const char *needle, const char *replace)
|
char *strreplace(const char *str, const char *needle, const char *replace)
|
||||||
{
|
{
|
||||||
const char *p, *q;
|
const char *p = NULL, *q = NULL;
|
||||||
p = q = str;
|
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;
|
if(!str) {
|
||||||
unsigned int needlesz = strlen(needle),
|
return(NULL);
|
||||||
replacesz = strlen(replace);
|
}
|
||||||
|
|
||||||
while (1) {
|
p = str;
|
||||||
|
q = strstr(p, needle);
|
||||||
|
while(q) {
|
||||||
|
list = alpm_list_add(list, (char *)q);
|
||||||
|
p = q + needlesz;
|
||||||
q = strstr(p, needle);
|
q = strstr(p, needle);
|
||||||
if(!q) { /* not found */
|
|
||||||
if(*p) {
|
|
||||||
/* add the rest of 'p' */
|
|
||||||
_strnadd(&newstr, p, strlen(p));
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
} else { /* found match */
|
/* 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){
|
if(q > p){
|
||||||
/* add chars between this occurance and last occurance, if any */
|
/* add chars between this occurence and last occurence, if any */
|
||||||
_strnadd(&newstr, p, q - p);
|
strncpy(newp, p, q - p);
|
||||||
|
newp += q - p;
|
||||||
}
|
}
|
||||||
_strnadd(&newstr, replace, replacesz);
|
strncpy(newp, replace, replacesz);
|
||||||
|
newp += replacesz;
|
||||||
p = q + needlesz;
|
p = q + needlesz;
|
||||||
}
|
}
|
||||||
}
|
alpm_list_free(list);
|
||||||
|
|
||||||
return newstr;
|
if(*p) {
|
||||||
|
/* add the rest of 'p' */
|
||||||
|
strcpy(newp, p);
|
||||||
|
newp += strlen(p);
|
||||||
|
}
|
||||||
|
*newp = '\0';
|
||||||
|
|
||||||
|
return(newstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Splits a string into a list of strings using the chosen character as
|
/** Splits a string into a list of strings using the chosen character as
|
||||||
|
|
Loading…
Add table
Reference in a new issue