]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
utils: Add strreplace function
authorTobias Brunner <tobias@strongswan.org>
Fri, 22 Nov 2013 09:30:16 +0000 (10:30 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 23 Jan 2014 09:18:23 +0000 (10:18 +0100)
src/libstrongswan/tests/suites/test_utils.c
src/libstrongswan/utils/utils.c
src/libstrongswan/utils/utils.h

index 3ca0412b4b15962665ea7be49a6023fc89c52ebc..2d290f81e0ba2aeea4ff1a6916a7dec3caae433d 100644 (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));
index 4bacb5834d48e693cd1e8b58e28c0af252531be5..77d875445499a44a7ac8913dca537fce6300233f 100644 (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.
  */
index cda7edf08398028724b8fdf59636c51299cb5189..7e4bfb2de1d6c4958bba1d72906038b7a18f8327 100644 (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.
  *