end:;
}
+/*
+ * memmem
+ */
+
+static int zmemm(const char *s, const char *q)
+{
+ char *r = memmem(s, strlen(s), q, strlen(q));
+ return r ? (r - s) : -1;
+}
+
+static void test_memmem(void *p)
+{
+ int_check(zmemm("qwe", ""), 0);
+ int_check(zmemm("qwe", "q"), 0);
+ int_check(zmemm("qwe", "w"), 1);
+ int_check(zmemm("qwe", "e"), 2);
+ int_check(zmemm("qwe", "x"), -1);
+ int_check(zmemm("qwe", "qw"), 0);
+ int_check(zmemm("qwe", "we"), 1);
+ int_check(zmemm("qwe", "qx"), -1);
+ int_check(zmemm("qwe", "wx"), -1);
+ int_check(zmemm("qwe", "ex"), -1);
+ int_check(zmemm("qwe", "qwe"), 0);
+ int_check(zmemm("qwe", "qwx"), -1);
+ int_check(zmemm("qwe", "qxe"), -1);
+ int_check(zmemm("qwe", "xwe"), -1);
+ int_check(zmemm("qweqweza", "qweza"), 3);
+ int_check(zmemm("qweqweza", "weza"), 4);
+ int_check(zmemm("qweqweza", "eza"), 5);
+ int_check(zmemm("qweqweza", "za"), 6);
+ int_check(zmemm("qweqweza", "a"), 7);
+ int_check(zmemm("qweqweza", "qwez"), 3);
+ int_check(zmemm("qweqweza", "wez"), 4);
+ int_check(zmemm("qweqweza", "ez"), 5);
+ int_check(zmemm("qweqweza", "z"), 6);
+ int_check(zmemm("qweqwez", "qweza"), -1);
+ int_check(zmemm("qweqwez", "weza"), -1);
+ int_check(zmemm("qweqwez", "eza"), -1);
+ int_check(zmemm("qweqwez", "za"), -1);
+ int_check(zmemm("qweqwez", "a"), -1);
+end:;
+}
+
/*
* basename
*/
end:;
}
+static void test_mempbrk(void *z)
+{
+ const char *p = "0123456789";
+ tt_assert(mempbrk(p, 10, "", 0) == NULL);
+ tt_assert(mempbrk(p, 10, "a", 0) == NULL);
+ tt_assert(mempbrk(p, 10, "ab", 0) == NULL);
+ tt_assert(mempbrk(p, 10, "abc", 0) == NULL);
+ tt_assert(mempbrk(p, 10, "1", 1) == p+1);
+ tt_assert(mempbrk(p, 10, "12", 2) == p+1);
+ tt_assert(mempbrk(p, 10, "21", 2) == p+1);
+ tt_assert(mempbrk(p, 10, "123", 3) == p+1);
+ tt_assert(mempbrk(p, 10, "321", 3) == p+1);
+ tt_assert(mempbrk(p, 11, "abc\0", 4) == p+10);
+end:;
+}
+
+static void test_memcspn(void *z)
+{
+ int_check(memcspn("qwe", 3, "", 0), 3);
+ int_check(memcspn("qwe", 3, "w", 1), 1);
+ int_check(memcspn("qwe", 3, "z", 1), 3);
+ int_check(memcspn("qwe", 3, "we", 2), 1);
+ int_check(memcspn("qwe", 3, "eq", 2), 0);
+ int_check(memcspn("qwe", 3, "zx", 2), 3);
+ int_check(memcspn("qwe", 3, "wez", 3), 1);
+ int_check(memcspn("qwe", 3, "ewz", 3), 1);
+ int_check(memcspn("qwe", 3, "zxa", 3), 3);
+ int_check(memcspn("qwe", 3, "weza", 4), 1);
+ int_check(memcspn("qwe", 3, "azew", 4), 1);
+ int_check(memcspn("qwe", 3, "zxab", 4), 3);
+end:;
+}
+
+static void test_memspn(void *z)
+{
+ const char *d = "0123456789";
+ int_check(memspn(d, 10, "", 0), 0);
+ int_check(memspn(d, 10, "0", 1), 1);
+ int_check(memspn(d, 10, "1", 1), 0);
+ int_check(memspn(d, 10, "23", 2), 0);
+ int_check(memspn(d, 10, "01", 2), 2);
+ int_check(memspn(d, 10, "456", 3), 0);
+ int_check(memspn(d, 10, "012", 3), 3);
+ int_check(memspn(d, 10, "4567", 4), 0);
+ int_check(memspn(d, 10, "0123", 4), 4);
+ int_check(memspn(d, 10, d, 10), 10);
+ int_check(memspn(d, 11, d, 11), 11);
+end:;
+}
+
/*
* Describe
*/
{ "strlcat", test_strlcat },
{ "strerror_r", test_strerror_r },
{ "memrchr", test_memrchr },
+ { "memmem", test_memmem },
+ { "mempbrk", test_mempbrk },
+ { "memcspn", test_memcspn },
+ { "memspn", test_memspn},
{ "basename", test_basename },
{ "dirname", test_dirname },
{ "strlist", test_strlist },
--- /dev/null
+/*
+ * byte map
+ *
+ * Copyright (c) 2014 Marko Kreen
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * Map 256 byte values to bit or int.
+ */
+#ifndef _USUAL_BYTEMAP_H_
+#define _USUAL_BYTEMAP_H_
+
+#define BITMAP256_SHIFT 5
+#define BITMAP256_MASK ((1 << BITMAP256_SHIFT) - 1)
+
+/**
+ * Bitmap of 256 bits.
+ */
+struct Bitmap256 {
+ uint32_t bmap[256 / 32];
+};
+
+/**
+ * Clear bitmap.
+ */
+static inline void bitmap256_init(struct Bitmap256 *bmap)
+{
+ memset(bmap, 0, sizeof(*bmap));
+}
+
+/**
+ * Set one bit.
+ */
+static inline void bitmap256_set(struct Bitmap256 *bmap, uint8_t byte)
+{
+ bmap->bmap[byte >> BITMAP256_SHIFT] |= 1 << (byte & BITMAP256_MASK);
+}
+
+/**
+ * Check if bit is set.
+ */
+static inline bool bitmap256_is_set(const struct Bitmap256 *bmap, uint8_t byte)
+{
+ return bmap->bmap[byte >> BITMAP256_SHIFT] & (1 << (byte & BITMAP256_MASK));
+}
+
+/*
+ * Declare const value of bytemap
+ */
+
+/**
+ * Use C preprocessor to fill Bitmap256.
+ *
+ * Usage:
+ * @code
+ * #define check_isdigit(c) ((c) >= '0' && (c) <= '9')
+ * static const struct Bitmap256 map_isdigit = BITMAP256_CONST(check_isdigit);
+ * @endcode
+ */
+#define BITMAP256_CONST(check) {{ \
+ _BMAP256_V32(check,0), _BMAP256_V32(check,32), _BMAP256_V32(check,64), _BMAP256_V32(check,96), \
+ _BMAP256_V32(check,128), _BMAP256_V32(check,160), _BMAP256_V32(check,192), _BMAP256_V32(check,224) }}
+#define _BMAP256_V32(ck,p) \
+ _BMAP256_V8(ck,(p)+0) | _BMAP256_V8(ck,(p)+8) | _BMAP256_V8(ck,(p)+16) | _BMAP256_V8(ck,(p)+24)
+#define _BMAP256_V8(ck,p) \
+ _BMAP256_BIT(ck,(p)+0) | _BMAP256_BIT(ck,(p)+1) | _BMAP256_BIT(ck,(p)+2) | _BMAP256_BIT(ck,(p)+3) | \
+ _BMAP256_BIT(ck,(p)+4) | _BMAP256_BIT(ck,(p)+5) | _BMAP256_BIT(ck,(p)+6) | _BMAP256_BIT(ck,(p)+7)
+#define _BMAP256_BIT(ck,p) (ck(p) ? (1 << ((p) & BMAP256_MASK)) : 0)
+
+/**
+ * Use C preprocessor to generate array of 256 values.
+ *
+ * Usage:
+ * @code
+ * #define my_hexval(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ( \
+ * ((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : ( \
+ * ((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : -1 )))
+ * static const int map_hexval[] = INTMAP256_CONST(my_hexval);
+ * @endcode
+ */
+#define INTMAP256_CONST(map_value) { _INTMAP_V128(map_value,0), _INTMAP_V128(map_value,128) }
+#define _INTMAP_V128(mf,n) _INTMAP_V32(mf,(n)+0*32), _INTMAP_V32(mf,(n)+1*32), _INTMAP_V32(mf,(n)+2*32), _INTMAP_V32(mf,(n)+3*32)
+#define _INTMAP_V32(mf,n) _INTMAP_V8(mf,(n)+0*8), _INTMAP_V8(mf,(n)+1*8), _INTMAP_V8(mf,(n)+2*8), _INTMAP_V8(mf,(n)+3*8)
+#define _INTMAP_V8(mf,n) mf((n)+0), mf((n)+1), mf((n)+2), mf((n)+3), mf((n)+4), mf((n)+5), mf((n)+6), mf((n)+7)
+
+
+#endif
+
#include <usual/mbuf.h>
#include <usual/statlist.h>
#include <usual/ctype.h>
+#include <usual/bytemap.h>
#include <errno.h>
}
#endif
+#ifndef HAVE_MEMMEM
+void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
+{
+ const uint8_t *s = haystack;
+ const uint8_t *q = needle;
+ const uint8_t *s2;
+ size_t i;
+
+ if (nlen == 0)
+ return (void *)haystack;
+ if (nlen > hlen)
+ return NULL;
+ s2 = memchr(haystack, *q, hlen);
+ if (!s2 || nlen == 1)
+ return (void *)s2;
+ for (i = s2 - s; i <= hlen - nlen; i++) {
+ if (s[i] == q[0] && s[i+1] == q[1]) {
+ if (memcmp(s + i + 2, q + 2, nlen - 2) == 0)
+ return (void *)(s + i);
+ }
+ }
+ return NULL;
+}
+#endif
+
#ifndef HAVE_BASENAME
const char *basename(const char *path)
{
return dst;
}
+void *mempbrk(const void *data, size_t dlen, const void *find, size_t flen)
+{
+ const uint8_t *s = data;
+ const uint8_t *fb = find;
+ size_t i;
+ struct Bitmap256 bmap;
+
+ if (flen == 0)
+ return NULL;
+ if (flen == 1)
+ return memchr(data, fb[0], dlen);
+
+ bitmap256_init(&bmap);
+ for (i = 0; i < flen; i++)
+ bitmap256_set(&bmap, fb[i]);
+ for (i = 0; i < dlen; i++) {
+ if (bitmap256_is_set(&bmap, s[i]))
+ return (void *)(s + i);
+ }
+ return NULL;
+}
+
+size_t memspn(const void *data, size_t dlen, const void *accept, size_t alen)
+{
+ const uint8_t *s = data;
+ const uint8_t *fb = accept;
+ size_t i;
+ struct Bitmap256 bmap;
+
+ if (alen == 0)
+ return 0;
+ if (alen == 1) {
+ for (i = 0; i < dlen; i++)
+ if (s[i] != fb[0])
+ break;
+ return i;
+ }
+
+ bitmap256_init(&bmap);
+ for (i = 0; i < alen; i++)
+ bitmap256_set(&bmap, fb[i]);
+ for (i = 0; i < dlen; i++) {
+ if (!bitmap256_is_set(&bmap, s[i]))
+ break;
+ }
+ return i;
+}
+
+size_t memcspn(const void *data, size_t dlen, const void *reject, size_t rlen)
+{
+ const void *p;
+
+ p = mempbrk(data, dlen, reject, rlen);
+ if (p != NULL)
+ return (char *)p - (char *)data;
+ return dlen;
+}