Implemented some basic libc functions and a text console
This commit is contained in:
144
libc/string/strtok.c
Normal file
144
libc/string/strtok.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <limits.h>
|
||||
#include <socks/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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user