utils: Add memrchr(3) replacement for platforms that don't support it
authorTobias Brunner <tobias@strongswan.org>
Tue, 25 Feb 2014 11:45:38 +0000 (12:45 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 26 Feb 2014 10:05:07 +0000 (11:05 +0100)
For instance, on Mac OS X memrchr(3) is not provided by the C library.

configure.ac
src/libstrongswan/tests/suites/test_utils.c
src/libstrongswan/utils/utils.c
src/libstrongswan/utils/utils.h

index a881b07..ea6b5ed 100644 (file)
@@ -533,7 +533,7 @@ AC_CHECK_FUNC(
 )
 
 AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r)
-AC_CHECK_FUNCS(fmemopen funopen mmap)
+AC_CHECK_FUNCS(fmemopen funopen mmap memrchr)
 
 AC_CHECK_HEADERS(sys/sockio.h glob.h net/if_tun.h linux/fib_rules.h)
 AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h)
index 92f6559..0260726 100644 (file)
@@ -346,6 +346,46 @@ START_TEST(test_memstr)
 END_TEST
 
 /*******************************************************************************
+ * utils_memrchr
+ */
+
+static struct {
+       char *s;
+       int c;
+       size_t n;
+       int offset;
+} memrchr_data[] = {
+       {NULL, 'f', 0, -1},
+       {NULL, 'f', 3, -1},
+       {"", 'f', 0, -1},
+       {"", '\0', 1, 0},
+       {"foo", '\0', 3, -1},
+       {"foo", '\0', 4, 3},
+       {"foo", 'f', 3, 0},
+       {"foo", 'o', 3, 2},
+       {"foo", 'o', 2, 1},
+       {"foo", 'o', 1, -1},
+       {"foo", 'o', 0, -1},
+       {"foo", 'x', 3, -1},
+};
+
+START_TEST(test_utils_memrchr)
+{
+       void *ret;
+
+       ret = utils_memrchr(memrchr_data[_i].s, memrchr_data[_i].c, memrchr_data[_i].n);
+       if (memrchr_data[_i].offset >= 0)
+       {
+               ck_assert(ret == memrchr_data[_i].s + memrchr_data[_i].offset);
+       }
+       else
+       {
+               ck_assert(ret == NULL);
+       }
+}
+END_TEST
+
+/*******************************************************************************
  * translate
  */
 
@@ -673,6 +713,10 @@ Suite *utils_suite_create()
        tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("utils_memrchr");
+       tcase_add_loop_test(tc, test_utils_memrchr, 0, countof(memrchr_data));
+       suite_add_tcase(s, tc);
+
        tc = tcase_create("translate");
        tcase_add_loop_test(tc, test_translate, 0, countof(translate_data));
        suite_add_tcase(s, tc);
index 406c5c8..fe80edb 100644 (file)
@@ -103,7 +103,7 @@ void memwipe_noinline(void *ptr, size_t n)
  */
 void *memstr(const void *haystack, const char *needle, size_t n)
 {
-       unsigned const char *pos = haystack;
+       const u_char *pos = haystack;
        size_t l;
 
        if (!haystack || !needle || (l = strlen(needle)) == 0)
@@ -123,6 +123,28 @@ void *memstr(const void *haystack, const char *needle, size_t n)
 /**
  * Described in header.
  */
+void *utils_memrchr(const void *s, int c, size_t n)
+{
+       const u_char *pos;
+
+       if (!s || !n)
+       {
+               return NULL;
+       }
+
+       for (pos = s + n - 1; pos >= (u_char*)s; pos--)
+       {
+               if (*pos == (u_char)c)
+               {
+                       return (void*)pos;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * Described in header.
+ */
 char* translate(char *str, const char *from, const char *to)
 {
        char *pos = str;
index 4c11390..a55e7d8 100644 (file)
@@ -465,6 +465,20 @@ static inline void memwipe(void *ptr, size_t n)
 void *memstr(const void *haystack, const char *needle, size_t n);
 
 /**
+ * Replacement for memrchr(3) if it is not provided by the C library.
+ *
+ * @param s            start of the memory area to search
+ * @param c            character to search
+ * @param n            length of memory area to search
+ * @return             pointer to the found character or NULL
+ */
+void *utils_memrchr(const void *s, int c, size_t n);
+
+#ifndef HAVE_MEMRCHR
+#define memrchr(s,c,n) utils_memrchr(s,c,n)
+#endif
+
+/**
  * Translates the characters in the given string, searching for characters
  * in 'from' and mapping them to characters in 'to'.
  * The two characters sets 'from' and 'to' must contain the same number of