From: David Gibson Date: Wed, 22 Oct 2014 11:56:53 +0000 (+0200) Subject: mem: Implement memrchr() X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=40b45c4cfbf110a8e790366302ff43fa94dc8daa mem: Implement memrchr() 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 --- diff --git a/ccan/mem/mem.c b/ccan/mem/mem.c index ce675ff0..853f975d 100644 --- a/ccan/mem/mem.c +++ b/ccan/mem/mem.c @@ -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 diff --git a/ccan/mem/mem.h b/ccan/mem/mem.h index 771d0527..dcb44b86 100644 --- a/ccan/mem/mem.h +++ b/ccan/mem/mem.h @@ -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 */ diff --git a/ccan/mem/test/api.c b/ccan/mem/test/api.c index a7cfb9a1..2ee15c58 100644 --- a/ccan/mem/test/api.c +++ b/ccan/mem/test/api.c @@ -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(); } diff --git a/tools/configurator/configurator.c b/tools/configurator/configurator.c index 51ac8fbf..dd5587c3 100644 --- a/tools/configurator/configurator.c +++ b/tools/configurator/configurator.c @@ -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 \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 \n" "static void *func(int fd) {\n"