diff options
| -rw-r--r-- | close_range.c | 2 | ||||
| -rw-r--r-- | config.mk | 4 | ||||
| -rw-r--r-- | libsimple.h | 34 | ||||
| -rw-r--r-- | libsimple/definitions.h | 24 | ||||
| -rw-r--r-- | memcasemem.c | 26 | ||||
| -rw-r--r-- | memmem.c | 33 |
6 files changed, 108 insertions, 15 deletions
diff --git a/close_range.c b/close_range.c index 29602c9..096aa56 100644 --- a/close_range.c +++ b/close_range.c @@ -128,7 +128,7 @@ fallback: } while (first++ < last); out: - (next) + if (next) *next = last + (last < LIBSIMPLE_CLOSE_RANGE_MAX); errno = saved_errno; return 0; @@ -1,8 +1,8 @@ PREFIX = /usr MANPREFIX = $(PREFIX)/share/man -CC = cc +CC = cc -std=c11 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -CFLAGS = -std=c11 -Wall -Wextra -O2 +CFLAGS = -Wall -Wextra -O2 LDFLAGS = -s -lm diff --git a/libsimple.h b/libsimple.h index 6d1867e..6e5f170 100644 --- a/libsimple.h +++ b/libsimple.h @@ -125,6 +125,40 @@ #endif +/* TODO doc, man, since 1.8, check which are supported by clang */ +#if defined(__GNUC__) && !defined(__clang__) +# define LIBSIMPLE_PURE __attribute__((pure)) +# define LIBSIMPLE_CONST __attribute__((const)) +# define LIBSIMPLE_NONNULL_RETURN __attribute__((returns_nonnull)) +# define LIBSIMPLE_USE_RETURN __attribute__((warn_unused_result)) +# define LIBSIMPLE_NONNULL_ARGS(...) __attribute__((nonnull__(__VA_ARGS__))) +# define LIBSIMPLE_NO_NULL_ARGS __attribute__((nonnull)) +# define LIBSIMPLE_RETURNS_TWICE __attribute__((returns_twice)) +# define LIBSIMPLE_UNREACHABLE __builtin_unreachable() +# define LIBSIMPLE_EXPECT(V, LIKELY) __builtin_expect((V), (LIKELY)) +# define LIBSIMPLE_ALIGNED(P) __builtin_assume_aligned((P), sizeof(*(P))) +# define LIBSIMPLE_ALIGNED_TO(P, A) __builtin_assume_aligned((P), (A)) +# define LIBSIMPLE_MISALIGNED(P, OFF) __builtin_assume_aligned((P), sizeof(*(P)), 0) +# define LIBSIMPLE_MISALIGNED_FROM(P, A, OFF) __builtin_assume_aligned((P), (A), 0) +#else +# define LIBSIMPLE_PURE +# define LIBSIMPLE_CONST +# define LIBSIMPLE_NONNULL_RETURN +# define LIBSIMPLE_USE_RETURN +# define LIBSIMPLE_NONNULL_ARGS(...) +# define LIBSIMPLE_NO_NULL_ARGS +# define LIBSIMPLE_RETURNS_TWICE +# define LIBSIMPLE_UNREACHABLE abort() +# define LIBSIMPLE_EXPECT(V, LIKELY) (V) +# define LIBSIMPLE_ALIGNED(P) (P) +# define LIBSIMPLE_ALIGNED_TO(P, A) (P) +# define LIBSIMPLE_MISALIGNED(P, OFF) (P) +# define LIBSIMPLE_MISALIGNED_FROM(P, A, OFF) (P) +#endif +#define LIBSIMPLE_LIKELY(V) LIBSIMPLE_EXPECT(!!(V), 1) +#define LIBSIMPLE_UNLIKELY(V) LIBSIMPLE_EXPECT(!!(V), 0) + + #include "libsimple/overflow.h" #include "libsimple/printf.h" #include "libsimple/definitions.h" diff --git a/libsimple/definitions.h b/libsimple/definitions.h index 98c3a15..e5dca61 100644 --- a/libsimple/definitions.h +++ b/libsimple/definitions.h @@ -218,13 +218,13 @@ * * This macro does not support the wide-character strings * - * @param STR:const char [] The string, must be a literal - * @return :size_t The value of `strlen(STR)` as a constant expression + * @param STR:string literal The string (must be a literal) + * @return :size_t The value of `strlen(STR)` as a constant expression * * @since 1.0 */ #ifndef STRLEN -# define STRLEN(STR) (sizeof(STR) - 1) +# define STRLEN(STR) (sizeof(STR) - 1U) #endif @@ -381,6 +381,24 @@ #endif +/* TODO man, doc, since 1.8 */ +#define LIBSIMPLE_0_TO_7 "01234567" +#define LIBSIMPLE_0_TO_9 "0123456789" +#define LIBSIMPLE_a_TO_f "abcdef" +#define LIBSIMPLE_A_TO_F "ABCDEF" +#define LIBSIMPLE_a_TO_z "abcdefghijklmnopqrstuvwxyz" +#define LIBSIMPLE_A_TO_Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define LIBSIMPLE_0_TO_f LIBSIMPLE_0_TO_9 LIBSIMPLE_a_TO_f +#define LIBSIMPLE_0_TO_F LIBSIMPLE_0_TO_9 LIBSIMPLE_A_TO_F + + +/* TODO man, doc, since 1.8 */ +#define LIBSIMPLE_SIZEOF_MEMBER(STRUCT, MEMBER) (sizeof(((STRUCT *)NULL)->MEMBER)) +#ifndef sizeof_member +#define sizeof_member(STRUCT, MEMBER) LIBSIMPLE_SIZEOF_MEMBER(STRUCT, MEMBER) +#endif + + /* --- Maximum values (since 1.0) --- */ #ifndef BLKCNT64_MAX diff --git a/memcasemem.c b/memcasemem.c index b3ea476..d883b62 100644 --- a/memcasemem.c +++ b/memcasemem.c @@ -8,7 +8,7 @@ libsimple_memcasemem(const void *hay_, size_t hayn, const void *sub_, size_t sub { const char *hay = hay_; const char *sub = sub_; - const char *end; + size_t *next, i, j; if (!subn) return REMOVE_CONST(hay, char *); @@ -17,9 +17,29 @@ libsimple_memcasemem(const void *hay_, size_t hayn, const void *sub_, size_t sub if (subn == 1) return libsimple_memcasechr(hay, *sub, hayn); - for (end = &hay[hayn - subn + 1]; hay != end; hay++) - if (tolower(*hay) == tolower(*sub) && !libsimple_memcasecmp(hay, sub, subn)) + next = alloca((subn + 1U) * sizeof(*next)); + i = 0, j = SIZE_MAX; + goto beginning; + for (; i < subn; i++, j++) { + if (tolower(sub[i]) == tolower(sub[j])) { + next[i] = next[j]; + } else { + beginning: + next[i] = j; + while (j != SIZE_MAX && tolower(sub[i]) != tolower(sub[j])) + j = next[j]; + } + } + + for (i = j = 0; i < hayn;) { + while (j != SIZE_MAX && tolower(sub[j]) != tolower(hay[i])) + j = next[j]; + i++; + if (++j == subn) { + hay = &hay[i - j]; return REMOVE_CONST(hay, char *); + } + } return NULL; } @@ -6,19 +6,40 @@ void * libsimple_memmem(const void *hay_, size_t hayn, const void *sub_, size_t subn) { - const char *hay = hay_, *end; - const char *sub = sub_; + const unsigned char *hay = hay_; + const unsigned char *sub = sub_; + size_t *next, i, j; if (!subn) - return REMOVE_CONST(hay, char *); + return REMOVE_CONST(hay, unsigned char *); if (hayn < subn) return NULL; if (subn == 1) return memchr(hay, *sub, hayn); - for (end = &hay[hayn - subn + 1]; hay != end; hay++) - if (*hay == *sub && !memcmp(hay, sub, subn)) - return REMOVE_CONST(hay, char *); + next = alloca((subn + 1U) * sizeof(*next)); + i = 0, j = SIZE_MAX; + goto beginning; + for (; i < subn; i++, j++) { + if (sub[i] == sub[j]) { + next[i] = next[j]; + } else { + beginning: + next[i] = j; + while (j != SIZE_MAX && sub[i] != sub[j]) + j = next[j]; + } + } + + for (i = j = 0; i < hayn;) { + while (j != SIZE_MAX && sub[j] != hay[i]) + j = next[j]; + i++; + if (++j == subn) { + hay = &hay[i - j]; + return REMOVE_CONST(hay, unsigned char *); + } + } return NULL; } |
