Files
mango/libc/string/strtok.c
2024-11-02 11:31:51 +00:00

145 lines
3.2 KiB
C

#include <limits.h>
#include <mango/libc/string.h>
#define ALIGN (sizeof(size_t))
#define ONES ((size_t)-1 / UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
#define HASZERO(X) (((X)-ONES) & ~(X)&HIGHS)
#define BITOP(A, B, OP) \
((A)[(size_t)(B) / (8 * sizeof *(A))] OP(size_t) 1 \
<< ((size_t)(B) % (8 * sizeof *(A))))
char *strchrnul(const char *s, int c) {
size_t *w;
size_t k;
c = (unsigned char)c;
if (!c) {
return (char *)s + strlen(s);
}
for (; (uintptr_t)s % ALIGN; s++) {
if (!*s || *(unsigned char *)s == c) {
return (char *)s;
}
}
k = ONES * c;
for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w ^ k); w++)
;
for (s = (void *)w; *s && *(unsigned char *)s != c; s++)
;
return (char *)s;
}
char *strchr(const char *s, int c) {
char *r = strchrnul(s, c);
return *(unsigned char *)r == (unsigned char)c ? r : 0;
}
size_t lfind(const char *str, const char accept) {
return (size_t)strchr(str, accept);
}
size_t strspn(const char *s, const char *c) {
const char *a = s;
size_t byteset[32 / sizeof(size_t)] = {0};
if (!c[0]) {
return 0;
}
if (!c[1]) {
for (; *s == *c; s++) {
return s - a;
}
}
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++)
;
for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++)
;
return s - a;
}
size_t strcspn(const char *s, const char *c) {
const char *a = s;
if (c[0] && c[1]) {
size_t byteset[32 / sizeof(size_t)] = {0};
for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++)
;
for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++)
;
return s - a;
}
return strchrnul(s, *c) - a;
}
char *strpbrk(const char *s, const char *b) {
s += strcspn(s, b);
return *s ? (char *)s : 0;
}
char *strtok_r(char *str, const char *delim, char **sp) {
int i = 0;
int len = strlen(delim);
/* Were we given any delimiters? */
if (len == 0) {
return NULL;
}
/* If we weren't given a string, and save pointer is NULL, return. */
if (!str && !sp) {
return NULL;
}
/* If we were given a string, initialise sp for subsequent calls. */
if (str) {
*sp = str;
}
/* Go to the start of the substring, skipping any delimiters. */
char *p_start = *sp;
while (1) {
for (i = 0; i < len; i++) {
if (*p_start == delim[i]) {
p_start++;
break;
}
}
if (i == len) {
*sp = p_start;
break;
}
}
/* Are we at the end of the string? */
if (**sp == '\0') {
*sp = NULL;
return *sp;
}
/* Find the end of the substring, and
replace the delimiter with null */
while (**sp != '\0') {
for (i = 0; i < len; i++) {
if (**sp == delim[i]) {
**sp = '\0';
break;
}
}
(*sp)++;
if (i < len) {
break;
}
}
return p_start;
}