utils: Add strreplace function

This commit is contained in:
Tobias Brunner 2013-11-22 10:30:16 +01:00
parent f44b1eb444
commit ccb6758e5b
3 changed files with 155 additions and 2 deletions

View File

@ -384,6 +384,89 @@ START_TEST(test_translate)
}
END_TEST
/*******************************************************************************
* strreplace
*/
static struct {
char *in;
char *out;
char *search;
char *replace;
bool allocated;
} strreplace_data[] = {
/* invalid arguments */
{NULL, NULL, NULL, NULL, FALSE},
{"", "", NULL, NULL, FALSE},
{"", "", "", NULL, FALSE},
{"", "", NULL, "", FALSE},
{"", "", "", "", FALSE},
{"", "", "", "asdf", FALSE},
{"", "", "asdf", "", FALSE},
{"asdf", "asdf", NULL, NULL, FALSE},
{"asdf", "asdf", "", NULL, FALSE},
{"asdf", "asdf", NULL, "", FALSE},
{"asdf", "asdf", "", "", FALSE},
{"asdf", "asdf", "", "asdf", FALSE},
{"asdf", "asdf", "asdf", NULL, FALSE},
{"qwer", "qwer", "", "asdf", FALSE},
/* replacement shorter */
{"asdf", "", "asdf", "", TRUE},
{"asdfasdf", "", "asdf", "", TRUE},
{"asasdfdf", "asdf", "asdf", "", TRUE},
{"asdf", "df", "as", "", TRUE},
{"asdf", "as", "df", "", TRUE},
{"qwer", "qwer", "asdf", "", FALSE},
/* replacement same length */
{"a", "b", "a", "b", TRUE},
{"aaa", "bbb", "a", "b", TRUE},
{"aaa", "bbb", "aaa", "bbb", TRUE},
{"asdf", "asdf", "asdf", "asdf", TRUE},
{"qwer", "qwer", "asdf", "asdf", FALSE},
/* replacement longer */
{"asdf", "asdf", "", "asdf", FALSE},
{"asdf", "asdfasdf", "asdf", "asdfasdf", TRUE},
{"asdf", "asdfsdf", "a", "asdf", TRUE},
{"asdf", "asdasdf", "f", "asdf", TRUE},
{"aaa", "asdfasdfasdf", "a", "asdf", TRUE},
{"qwer", "qwer", "asdf", "asdfasdf", FALSE},
/* real examples */
{"http://x.org/no/spaces", "http://x.org/no/spaces", " ", "%20", FALSE},
{"http://x.org/end ", "http://x.org/end%20", " ", "%20", TRUE},
{" http://x.org/start", "%20http://x.org/start", " ", "%20", TRUE},
{" http://x.org/both ", "%20http://x.org/both%20", " ", "%20", TRUE},
{"http://x.org/ /slash", "http://x.org/%20/slash", " ", "%20", TRUE},
{"http://x.org/ /three", "http://x.org/%20%20%20/three", " ", "%20", TRUE},
{"http://x.org/ ", "http://x.org/%20%20%20%20%20%20", " ", "%20", TRUE},
{"http://x.org/%20/encoded", "http://x.org/%20/encoded", " ", "%20", FALSE},
};
START_TEST(test_strreplace)
{
char *ret;
ret = strreplace(strreplace_data[_i].in, strreplace_data[_i].search,
strreplace_data[_i].replace);
if (ret && strreplace_data[_i].out)
{
ck_assert_str_eq(ret, strreplace_data[_i].out);
}
else
{
ck_assert(ret == strreplace_data[_i].out);
}
if (strreplace_data[_i].allocated)
{
ck_assert(ret != strreplace_data[_i].in);
free(ret);
}
else
{
ck_assert(ret == strreplace_data[_i].in);
}
}
END_TEST
/*******************************************************************************
* time_printf_hook
*/
@ -543,6 +626,10 @@ Suite *utils_suite_create()
tcase_add_loop_test(tc, test_translate, 0, countof(translate_data));
suite_add_tcase(s, tc);
tc = tcase_create("strreplace");
tcase_add_loop_test(tc, test_strreplace, 0, countof(strreplace_data));
suite_add_tcase(s, tc);
tc = tcase_create("printf_hooks");
tcase_add_loop_test(tc, test_time_printf_hook, 0, countof(time_data));
tcase_add_loop_test(tc, test_time_delta_printf_hook, 0, countof(time_delta_data));

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@ -141,6 +141,58 @@ char* translate(char *str, const char *from, const char *to)
return str;
}
/**
* Described in header.
*/
char* strreplace(const char *str, const char *search, const char *replace)
{
size_t len, slen, rlen, count = 0;
char *res, *pos, *found, *dst;
if (!str || !*str || !search || !*search || !replace)
{
return (char*)str;
}
slen = strlen(search);
rlen = strlen(replace);
if (slen != rlen)
{
for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
{
found = pos;
count++;
}
if (!count)
{
return (char*)str;
}
len = (found - str) + strlen(found) + count * (rlen - slen);
}
else
{
len = strlen(str);
}
found = strstr(str, search);
if (!found)
{
return (char*)str;
}
dst = res = malloc(len + 1);
pos = (char*)str;
do
{
len = found - pos;
memcpy(dst, pos, len);
dst += len;
memcpy(dst, replace, rlen);
dst += rlen;
pos = found + slen;
}
while ((found = strstr(pos, search)));
strcpy(dst, pos);
return res;
}
/**
* Described in header.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2012 Tobias Brunner
* Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@ -471,6 +471,20 @@ void *memstr(const void *haystack, const char *needle, size_t n);
*/
char *translate(char *str, const char *from, const char *to);
/**
* Replaces all occurences of search in the given string with replace.
*
* Allocates memory only if anything is replaced in the string. The original
* string is also returned if any of the arguments are invalid (e.g. if search
* is empty or any of them are NULL).
*
* @param str original string
* @param search string to search for and replace
* @param replace string to replace found occurences with
* @return allocated string, if anything got replaced, str otherwise
*/
char *strreplace(const char *str, const char *search, const char *replace);
/**
* Creates a directory and all required parent directories.
*