[ccan] [PATCH 3/3] memfuncs: Implement memrchr()
David Gibson
david at gibson.dropbear.id.au
Sun Oct 19 23:07:46 AEDT 2014
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 memfuncs module,
when it's not available in the system C library.
Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
---
ccan/memfuncs/memfuncs.c | 14 ++++++++++++++
ccan/memfuncs/memfuncs.h | 4 ++++
ccan/memfuncs/test/run.c | 16 +++++++++++++++-
tools/configurator/configurator.c | 6 ++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/ccan/memfuncs/memfuncs.c b/ccan/memfuncs/memfuncs.c
index c80b862..2674f41 100644
--- a/ccan/memfuncs/memfuncs.c
+++ b/ccan/memfuncs/memfuncs.c
@@ -25,3 +25,17 @@ 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;
+ size_t i;
+
+ for (i = n - 1; i >= 0; i--)
+ if (p[i] == c)
+ return p + i;
+
+ return NULL;
+}
+#endif
diff --git a/ccan/memfuncs/memfuncs.h b/ccan/memfuncs/memfuncs.h
index bbc19c9..4b6d9fe 100644
--- a/ccan/memfuncs/memfuncs.h
+++ b/ccan/memfuncs/memfuncs.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_MEMFUNCS_H */
diff --git a/ccan/memfuncs/test/run.c b/ccan/memfuncs/test/run.c
index 0e2e903..b6f1833 100644
--- a/ccan/memfuncs/test/run.c
+++ b/ccan/memfuncs/test/run.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(17);
ok1(memmem(haystack1, sizeof(haystack1), needle1, 2) == haystack1);
ok1(memmem(haystack1, sizeof(haystack1), needle1, 3) == NULL);
@@ -20,6 +20,20 @@ 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(haystack2, 'a', sizeof(haystack2)) == haystack2 + 9);
+ ok1(memrchr(haystack2, 'b', sizeof(haystack2)) == haystack2 + 10);
+ ok1(memrchr(haystack2, '\0', sizeof(haystack2)) == haystack2 + 11);
+
/* This exits depending on whether all tests passed */
return exit_status();
}
diff --git a/tools/configurator/configurator.c b/tools/configurator/configurator.c
index d1aa5c6..0c4b0f1 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 <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"
--
1.9.3
More information about the ccan
mailing list