1/*
2 * strspn, strcspn
3 */
4
5#include <string.h>
6#include <stddef.h>
7#include <inttypes.h>
8#include <limits.h>
9
10#ifndef LONG_BIT
11#define LONG_BIT (CHAR_BIT*sizeof(long))
12#endif
13
14static void set_bit(unsigned long *bitmap, unsigned int bit)
15{
16    bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
17}
18
19static int test_bit(unsigned long *bitmap, unsigned int bit)
20{
21    return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1;
22}
23
24static size_t strxspn(const char *s, const char *map, int parity)
25{
26    unsigned long matchmap[((1 << CHAR_BIT) + LONG_BIT - 1) / LONG_BIT];
27    size_t n = 0;
28
29    /* Create bitmap */
30    memset(matchmap, 0, sizeof matchmap);
31    while (*map)
32	set_bit(matchmap, (unsigned char)*map++);
33
34    /* Make sure the null character never matches */
35    if (parity)
36	set_bit(matchmap, 0);
37
38    /* Calculate span length */
39    while (test_bit(matchmap, (unsigned char)*s++) ^ parity)
40	n++;
41
42    return n;
43}
44
45size_t strspn(const char *s, const char *accept)
46{
47    return strxspn(s, accept, 0);
48}
49
50size_t strcspn(const char *s, const char *reject)
51{
52    return strxspn(s, reject, 1);
53}
54
55char *strpbrk(const char *s, const char *accept)
56{
57    const char *ss = s + strxspn(s, accept, 1);
58
59    return *ss ? (char *)ss : NULL;
60}
61