aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--README10
-rw-r--r--TODO5
-rw-r--r--libsimple.h21
-rw-r--r--memrmem.c57
-rw-r--r--strrcasestr.c75
-rw-r--r--strrstr.c70
7 files changed, 239 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 2ffbaad..ae5830b 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ OBJ =\
memends.o\
memmem.o\
memrchr.o\
+ memrmem.o\
memstarts.o\
multimespec.o\
multimeval.o\
@@ -39,6 +40,8 @@ OBJ =\
strchrnul.o\
strends.o\
strndup.o\
+ strrcasestr.o\
+ strrstr.o\
strstarts.o\
strtotimespec.o\
strtotimeval.o\
diff --git a/README b/README
index 28dfac8..5310275 100644
--- a/README
+++ b/README
@@ -123,6 +123,10 @@ The following functions are defined (some as inline functions):
Finds the first occurrence of `t` in `s`.
Length of `s` is `sn`. Length of `t` is `tn`.
+ void *libsimple_memrmem(const void *s, size_t sn, const void *t, size_t tn)
+ Finds the last occurrence of `t` in `s`.
+ Length of `s` is `sn`. Length of `t` is `tn`.
+
int libsimple_memstarts(const void *s, size_t sn, const void *t, size_t tn)
Returns 1 if `s` starts with `t`, 0 otherwise.
Length of `s` is `sn`. Length of `t` is `tn`.
@@ -131,6 +135,9 @@ The following functions are defined (some as inline functions):
Returns 1 if `s` ends with `t`, 0 otherwise.
Length of `s` is `sn`. Length of `t` is `tn`.
+ char *libsimple_strrstr(const char *s, const char *t)
+ Finds the last occurrence of `t` in `s`.
+
int libsimple_strstarts(const char *s, const char *t)
Returns 1 if `s` starts with `t`, 0 otherwise.
@@ -146,6 +153,9 @@ The following functions are defined (some as inline functions):
char *libsimple_strcasestr(const char *, const char *)
Like strstr except case-insensitive.
+ char *libsimple_strrcasestr(const char *, const char *)
+ Like strrstr except case-insensitive.
+
int libsimple_streq(const char *a, const char *b)
!strncmp(a, b)
diff --git a/TODO b/TODO
index 2f0feae..2b24a41 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
-memrmem
-strrstr
strnstr
+strrnstr
+strncasestr
+strrncasestr
diff --git a/libsimple.h b/libsimple.h
index 8a6395f..85f741f 100644
--- a/libsimple.h
+++ b/libsimple.h
@@ -674,6 +674,13 @@ void *libsimple_memmem(const void *, size_t, const void *, size_t);
_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__)))
+void *libsimple_memrmem(const void *, size_t, const void *, size_t);
+#ifndef memrmem
+# define memrmem libsimple_memrmem
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__)))
int libsimple_memstarts(const void *, size_t, const void *, size_t);
#ifndef memstarts
# define memstarts libsimple_memstarts
@@ -688,6 +695,13 @@ int libsimple_memends(const void *, size_t, const void *, size_t);
_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__)))
+char *libsimple_strrstr(const char *, const char *);
+#ifndef strrstr
+# define strrstr libsimple_strrstr
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__)))
int libsimple_strstarts(const char *, const char *);
#ifndef strstarts
# define strstarts libsimple_strstarts
@@ -723,6 +737,13 @@ char *libsimple_strcasestr(const char *, const char *);
_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__)))
+char *libsimple_strrcasestr(const char *, const char *);
+#ifndef strrcasestr
+# define strrcasestr libsimple_strrcasestr
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__)))
static inline int streq(const char *__a, const char *__b) { return !strcmp(__a, __b); } /* TODO test */
diff --git a/memrmem.c b/memrmem.c
new file mode 100644
index 0000000..713ba34
--- /dev/null
+++ b/memrmem.c
@@ -0,0 +1,57 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsimple.h"
+
+
+void *
+libsimple_memrmem(const void *hay_, size_t hayn, const void *sub_, size_t subn)
+{
+ char *hay = (void *)hay_, *start;
+ const char *sub = sub_;
+
+ if (!subn)
+ return hay;
+ if (hayn < subn)
+ return NULL;
+ if (subn == 1)
+ return libsimple_memrchr(hay, *sub, hayn);
+
+ start = hay;
+ hay = &hay[hayn - subn];
+ do {
+ if (*hay == *sub && !memcmp(hay, sub, subn))
+ return hay;
+ } while (hay-- != start);
+
+ return NULL;
+}
+
+
+#ifdef TEST
+#include <assert.h>
+
+int
+main(void)
+{
+ assert(!strcmp(libsimple_memrmem("test", 4, "test", 4), "test"));
+ assert(!strcmp(libsimple_memrmem("", 0, "", 0), ""));
+ assert(!strcmp(libsimple_memrmem("test", 4, "", 0), ""));
+ assert(!libsimple_memrmem("", 0, "test", 4));
+ assert(!libsimple_memrmem("t", 1, "test", 4));
+ assert(!strcmp(libsimple_memrmem("test", 4, "t", 1), "t"));
+ assert(!strcmp(libsimple_memrmem("test", 4, "e", 1), "est"));
+ assert(!strcmp(libsimple_memrmem("test", 4, "s", 1), "st"));
+ assert(!libsimple_memrmem("test", 4, "x", 1));
+ assert(!strcmp(libsimple_memrmem("test", 4, "te", 2), "test"));
+ assert(!strcmp(libsimple_memrmem("test", 4, "es", 2), "est"));
+ assert(!strcmp(libsimple_memrmem("test", 4, "st", 2), "st"));
+ assert(!strcmp(libsimple_memrmem("test", 5, "t", 2), "t"));
+ assert(!libsimple_memrmem("test", 4, "xx", 2));
+ assert(!strcmp(libsimple_memrmem("abc", 3, "c", 1), "c"));
+ assert(!strcmp(libsimple_memrmem("abc", 3, "bc", 2), "bc"));
+ assert(!strcmp(libsimple_memrmem("abc", 3, "abc", 3), "abc"));
+ assert(!libsimple_memrmem("abc", 3, "abc", 4));
+ assert(!strcmp(libsimple_memrmem("abcabc", 6, "bc", 2), "bc"));
+ return 0;
+}
+
+#endif
diff --git a/strrcasestr.c b/strrcasestr.c
new file mode 100644
index 0000000..9bd40b3
--- /dev/null
+++ b/strrcasestr.c
@@ -0,0 +1,75 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsimple.h"
+
+
+char *
+libsimple_strrcasestr(const char *h_, const char *n)
+{
+ char *h = *(char **)(void *)&h_;
+ size_t hn = strlen(h);
+ size_t nn = strlen(n);
+ if (hn < nn)
+ return NULL;
+ for (h += hn -= nn; hn--; h--)
+ if (!strcasecmp(h, n))
+ return h;
+ return NULL;
+}
+
+
+#ifdef TEST
+#include <assert.h>
+
+int
+main(void)
+{
+ assert(!strcmp(libsimple_strrcasestr("", ""), ""));
+ assert(!strcmp(libsimple_strrcasestr("test", ""), ""));
+ assert(!libsimple_strrcasestr("", ""));
+ assert(!libsimple_strrcasestr("t", "t"));
+ assert(!strcmp(libsimple_strrcasestr("test", "t"), "t"));
+ assert(!strcmp(libsimple_strrcasestr("test", "e"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "s"), "st"));
+ assert(!libsimple_strrcasestr("test", "x"));
+ assert(!strcmp(libsimple_strrcasestr("test", "te"), "test"));
+ assert(!strcmp(libsimple_strrcasestr("test", "es"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "st"), "st"));
+ assert(!libsimple_strrcasestr("test", "xx"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "c"), "c"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "bc"), "bc"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "abc"), "abc"));
+ assert(!strcmp(libsimple_strrcasestr("abcabc", "bc"), "bc"));
+
+ assert(!strcmp(libsimple_strrcasestr("TEST", ""), ""));
+ assert(!libsimple_strrcasestr("T", "test"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "t"), "T"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "e"), "EST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "s"), "ST"));
+ assert(!libsimple_strrcasestr("TEST", "x"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "te"), "TEST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "es"), "EST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "st"), "ST"));
+ assert(!libsimple_strrcasestr("TEST", "xx"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "c"), "C"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "bc"), "BC"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "abc"), "ABC"));
+ assert(!strcmp(libsimple_strrcasestr("ABCABC", "bc"), "BC"));
+
+ assert(!libsimple_strrcasestr("", "TEST"));
+ assert(!libsimple_strrcasestr("t", "TEST"));
+ assert(!strcmp(libsimple_strrcasestr("test", "T"), "t"));
+ assert(!strcmp(libsimple_strrcasestr("test", "E"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "S"), "st"));
+ assert(!libsimple_strrcasestr("test", "X"));
+ assert(!strcmp(libsimple_strrcasestr("test", "TE"), "test"));
+ assert(!strcmp(libsimple_strrcasestr("test", "ES"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "ST"), "st"));
+ assert(!libsimple_strrcasestr("test", "XX"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "C"), "c"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "BC"), "bc"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "ABC"), "abc"));
+ assert(!strcmp(libsimple_strrcasestr("abcabc", "BC"), "bc"));
+ return 0;
+}
+
+#endif
diff --git a/strrstr.c b/strrstr.c
new file mode 100644
index 0000000..5d64744
--- /dev/null
+++ b/strrstr.c
@@ -0,0 +1,70 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsimple.h"
+
+
+char *
+libsimple_strrstr(const char *hay, const char *sub)
+{
+ return libsimple_memrmem(hay, strlen(hay), sub, strlen(sub));
+}
+
+
+#ifdef TEST
+#include <assert.h>
+
+int
+main(void)
+{
+ assert(!strcmp(libsimple_strrstr("test", "test"), "test"));
+ assert(!strcmp(libsimple_strrstr("", ""), ""));
+ assert(!strcmp(libsimple_strrstr("test", ""), ""));
+ assert(!libsimple_strrstr("", "test"));
+ assert(!libsimple_strrstr("t", "test"));
+ assert(!strcmp(libsimple_strrstr("test", "t"), "t"));
+ assert(!strcmp(libsimple_strrstr("test", "e"), "est"));
+ assert(!strcmp(libsimple_strrstr("test", "s"), "st"));
+ assert(!libsimple_strrstr("test", "x"));
+ assert(!strcmp(libsimple_strrstr("test", "te"), "test"));
+ assert(!strcmp(libsimple_strrstr("test", "es"), "est"));
+ assert(!strcmp(libsimple_strrstr("test", "st"), "st"));
+ assert(!libsimple_strrstr("test", "xx"));
+ assert(!strcmp(libsimple_strrstr("abc", "c"), "c"));
+ assert(!strcmp(libsimple_strrstr("abc", "bc"), "bc"));
+ assert(!strcmp(libsimple_strrstr("abc", "abc"), "abc"));
+ assert(!strcmp(libsimple_strrstr("abcabc", "bc"), "bc"));
+
+ assert(!strcmp(libsimple_strrcasestr("TEST", "test"), "TEST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", ""), ""));
+ assert(!libsimple_strrcasestr("T", "test"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "t"), "T"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "e"), "EST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "s"), "ST"));
+ assert(!libsimple_strrcasestr("TEST", "x"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "te"), "TEST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "es"), "EST"));
+ assert(!strcmp(libsimple_strrcasestr("TEST", "st"), "ST"));
+ assert(!libsimple_strrcasestr("TEST", "xx"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "c"), "C"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "bc"), "BC"));
+ assert(!strcmp(libsimple_strrcasestr("ABC", "abc"), "ABC"));
+ assert(!strcmp(libsimple_strrcasestr("ABCABC", "bc"), "BC"));
+
+ assert(!strcmp(libsimple_strrcasestr("test", "TEST"), "test"));
+ assert(!libsimple_strrcasestr("", "TEST"));
+ assert(!libsimple_strrcasestr("t", "TEST"));
+ assert(!strcmp(libsimple_strrcasestr("test", "T"), "t"));
+ assert(!strcmp(libsimple_strrcasestr("test", "E"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "S"), "st"));
+ assert(!libsimple_strrcasestr("test", "X"));
+ assert(!strcmp(libsimple_strrcasestr("test", "TE"), "test"));
+ assert(!strcmp(libsimple_strrcasestr("test", "ES"), "est"));
+ assert(!strcmp(libsimple_strrcasestr("test", "ST"), "st"));
+ assert(!libsimple_strrcasestr("test", "XX"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "C"), "c"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "BC"), "bc"));
+ assert(!strcmp(libsimple_strrcasestr("abc", "ABC"), "abc"));
+ assert(!strcmp(libsimple_strrcasestr("abcabc", "BC"), "bc"));
+ return 0;
+}
+
+#endif