mem: Implement memrchr()
authorDavid Gibson <david@gibson.dropbear.id.au>
Wed, 22 Oct 2014 11:56:53 +0000 (13:56 +0200)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 27 Oct 2014 05:43:16 +0000 (16:13 +1030)
The memrchr() function, which works like memchr(), but searches from the
back of the region to the front is implemented in the GNU C library, but
isn't standard.

This patch adds an implementation of the function to the mem module, when
it's not available in the system C library.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
ccan/mem/mem.c
ccan/mem/mem.h
ccan/mem/test/api.c
tools/configurator/configurator.c

index ce675ff0db4238b6840fcdd98bff736ba90b508c..853f975db15c1e0c096387c53973a7bdf3b14095 100644 (file)
@@ -25,3 +25,18 @@ void *memmem(const void *haystack, size_t haystacklen,
        return NULL;
 }
 #endif
+
+#if !HAVE_MEMRCHR
+void *memrchr(const void *s, int c, size_t n)
+{
+       unsigned char *p = (unsigned char *)s;
+
+       while (n) {
+               if (p[n-1] == c)
+                       return p + n - 1;
+               n--;
+       }
+
+       return NULL;
+}
+#endif
index 771d05273bc08518df0bf044c0029842d3eb0ce0..dcb44b86c59779c0990b47c72ff037b6b67daea4 100644 (file)
@@ -11,4 +11,8 @@ void *memmem(const void *haystack, size_t haystacklen,
             const void *needle, size_t needlelen);
 #endif
 
+#if !HAVE_MEMRCHR
+void *memrchr(const void *s, int c, size_t n);
+#endif
+
 #endif /* CCAN_MEM_H */
index a7cfb9a11737b9048727dd12d15ba9d8d6851f3f..2ee15c58e37f15aab439655648aa22b6655ccba9 100644 (file)
@@ -10,7 +10,7 @@ int main(void)
        char needle2[] = "d\0e";
 
        /* This is how many tests you plan to run */
-       plan_tests(5);
+       plan_tests(19);
 
        ok1(memmem(haystack1, sizeof(haystack1), needle1, 2) == haystack1);
        ok1(memmem(haystack1, sizeof(haystack1), needle1, 3) == NULL);
@@ -20,6 +20,23 @@ int main(void)
            == haystack2);
        ok1(memmem(haystack2, sizeof(haystack2), needle2, 3) == NULL);
 
+       ok1(memrchr(haystack1, 'a', sizeof(haystack1)) == haystack1);
+       ok1(memrchr(haystack1, 'b', sizeof(haystack1)) == haystack1 + 1);
+       ok1(memrchr(haystack1, 'c', sizeof(haystack1)) == haystack1 + 2);
+       ok1(memrchr(haystack1, 'd', sizeof(haystack1)) == haystack1 + 3);
+       ok1(memrchr(haystack1, 'e', sizeof(haystack1)) == haystack1 + 5);
+       ok1(memrchr(haystack1, 'f', sizeof(haystack1)) == haystack1 + 6);
+       ok1(memrchr(haystack1, 'g', sizeof(haystack1)) == haystack1 + 7);
+       ok1(memrchr(haystack1, 'h', sizeof(haystack1)) == haystack1 + 8);
+       ok1(memrchr(haystack1, '\0', sizeof(haystack1)) == haystack1 + 9);
+       ok1(memrchr(haystack1, 'i', sizeof(haystack1)) == NULL);
+
+       ok1(memrchr(haystack2, 'a', sizeof(haystack2)) == haystack2 + 9);
+       ok1(memrchr(haystack2, 'b', sizeof(haystack2)) == haystack2 + 10);
+       ok1(memrchr(haystack2, '\0', sizeof(haystack2)) == haystack2 + 11);
+
+       ok1(memrchr(needle1, '\0', 2) == NULL);
+
        /* This exits depending on whether all tests passed */
        return exit_status();
 }
index 51ac8fbfeba777577cb607d48518818f74aa9ed8..dd5587c3b556c31eaa6b2a5887e684d375530e0f 100644 (file)
@@ -214,6 +214,12 @@ static struct test tests[] = {
          "static void *func(void *h, size_t hl, void *n, size_t nl) {\n"
          "return memmem(h, hl, n, nl);"
          "}\n", },
+       { "HAVE_MEMRCHR", DEFINES_FUNC, NULL, NULL,
+         "#define _GNU_SOURCE\n"
+         "#include <string.h>\n"
+         "static void *func(void *s, int c, size_t n) {\n"
+         "return memrchr(s, c, n);"
+         "}\n", },
        { "HAVE_MMAP", DEFINES_FUNC, NULL, NULL,
          "#include <sys/mman.h>\n"
          "static void *func(int fd) {\n"