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
set_bit(unsigned long * bitmap,unsigned int bit)14 static void set_bit(unsigned long *bitmap, unsigned int bit)
15 {
16 bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
17 }
18
test_bit(unsigned long * bitmap,unsigned int bit)19 static int test_bit(unsigned long *bitmap, unsigned int bit)
20 {
21 return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1;
22 }
23
strxspn(const char * s,const char * map,int parity)24 static 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
strspn(const char * s,const char * accept)45 size_t strspn(const char *s, const char *accept)
46 {
47 return strxspn(s, accept, 0);
48 }
49
strcspn(const char * s,const char * reject)50 size_t strcspn(const char *s, const char *reject)
51 {
52 return strxspn(s, reject, 1);
53 }
54
strpbrk(const char * s,const char * accept)55 char *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