diff options
-rw-r--r-- | src/libstrongswan/tests/suites/test_utils.c | 87 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils.c | 54 | ||||
-rw-r--r-- | src/libstrongswan/utils/utils.h | 16 |
3 files changed, 155 insertions, 2 deletions
diff --git a/src/libstrongswan/tests/suites/test_utils.c b/src/libstrongswan/tests/suites/test_utils.c index 3ca0412b4..2d290f81e 100644 --- a/src/libstrongswan/tests/suites/test_utils.c +++ b/src/libstrongswan/tests/suites/test_utils.c @@ -385,6 +385,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)); diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index 4bacb5834..77d875445 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -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 * @@ -144,6 +144,58 @@ char* translate(char *str, const char *from, const char *to) /** * 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. + */ bool mkdir_p(const char *path, mode_t mode) { int len; diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index cda7edf08..7e4bfb2de 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -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 * @@ -472,6 +472,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. * * @param path path to the new directory |