diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | README | 10 | ||||
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | libsimple.h | 21 | ||||
-rw-r--r-- | memrmem.c | 57 | ||||
-rw-r--r-- | strrcasestr.c | 75 | ||||
-rw-r--r-- | strrstr.c | 70 |
7 files changed, 239 insertions, 2 deletions
@@ -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\ @@ -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) @@ -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 |