xref: /DragonStub/apps/lib/string.c (revision 3e6106c4d60a23aae3c0740979c5e6fb728b63c3)
178b790faSLoGin 
278b790faSLoGin #include <dragonstub/dragonstub.h>
378b790faSLoGin 
478b790faSLoGin char *skip_spaces(const char *str)
578b790faSLoGin {
678b790faSLoGin 	while (isspace(*str))
778b790faSLoGin 		++str;
878b790faSLoGin 	return (char *)str;
978b790faSLoGin }
1078b790faSLoGin 
1178b790faSLoGin unsigned int atou(const char *s)
1278b790faSLoGin {
1378b790faSLoGin 	unsigned int i = 0;
1478b790faSLoGin 	while (isdigit(*s))
1578b790faSLoGin 		i = i * 10 + (*s++ - '0');
1678b790faSLoGin 	return i;
1778b790faSLoGin }
1878b790faSLoGin 
1978b790faSLoGin /* Works only for digits and letters, but small and fast */
2078b790faSLoGin #define TOLOWER(x) ((x) | 0x20)
2178b790faSLoGin 
2278b790faSLoGin static unsigned int simple_guess_base(const char *cp)
2378b790faSLoGin {
2478b790faSLoGin 	if (cp[0] == '0') {
2578b790faSLoGin 		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
2678b790faSLoGin 			return 16;
2778b790faSLoGin 		else
2878b790faSLoGin 			return 8;
2978b790faSLoGin 	} else {
3078b790faSLoGin 		return 10;
3178b790faSLoGin 	}
3278b790faSLoGin }
3378b790faSLoGin 
3478b790faSLoGin /**
3578b790faSLoGin  * strlen - Find the length of a string
3678b790faSLoGin  * @s: The string to be sized
3778b790faSLoGin  */
3878b790faSLoGin size_t strlen(const char *s)
3978b790faSLoGin {
4078b790faSLoGin 	const char *sc;
4178b790faSLoGin 
4278b790faSLoGin 	for (sc = s; *sc != '\0'; ++sc)
4378b790faSLoGin 		/* nothing */;
4478b790faSLoGin 	return sc - s;
4578b790faSLoGin }
4678b790faSLoGin 
4778b790faSLoGin /**
4878b790faSLoGin  * simple_strtoull - convert a string to an unsigned long long
4978b790faSLoGin  * @cp: The start of the string
5078b790faSLoGin  * @endp: A pointer to the end of the parsed string will be placed here
5178b790faSLoGin  * @base: The number base to use
5278b790faSLoGin  */
5378b790faSLoGin unsigned long long simple_strtoull(const char *cp, char **endp,
5478b790faSLoGin 				   unsigned int base)
5578b790faSLoGin {
5678b790faSLoGin 	unsigned long long result = 0;
5778b790faSLoGin 
5878b790faSLoGin 	if (!base)
5978b790faSLoGin 		base = simple_guess_base(cp);
6078b790faSLoGin 
6178b790faSLoGin 	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
6278b790faSLoGin 		cp += 2;
6378b790faSLoGin 
6478b790faSLoGin 	while (isxdigit(*cp)) {
6578b790faSLoGin 		unsigned int value;
6678b790faSLoGin 
6778b790faSLoGin 		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
6878b790faSLoGin 		if (value >= base)
6978b790faSLoGin 			break;
7078b790faSLoGin 		result = result * base + value;
7178b790faSLoGin 		cp++;
7278b790faSLoGin 	}
7378b790faSLoGin 	if (endp)
7478b790faSLoGin 		*endp = (char *)cp;
7578b790faSLoGin 
7678b790faSLoGin 	return result;
7778b790faSLoGin }
7878b790faSLoGin 
7978b790faSLoGin long simple_strtol(const char *cp, char **endp, unsigned int base)
8078b790faSLoGin {
8178b790faSLoGin 	if (*cp == '-')
8278b790faSLoGin 		return -simple_strtoull(cp + 1, endp, base);
8378b790faSLoGin 
8478b790faSLoGin 	return simple_strtoull(cp, endp, base);
8578b790faSLoGin }
8678b790faSLoGin 
8778b790faSLoGin int strcmp(const char *str1, const char *str2)
8878b790faSLoGin {
8978b790faSLoGin 	const unsigned char *s1 = (const unsigned char *)str1;
9078b790faSLoGin 	const unsigned char *s2 = (const unsigned char *)str2;
9178b790faSLoGin 	int delta = 0;
9278b790faSLoGin 
9378b790faSLoGin 	while (*s1 || *s2) {
9478b790faSLoGin 		delta = *s1 - *s2;
9578b790faSLoGin 		if (delta)
9678b790faSLoGin 			return delta;
9778b790faSLoGin 		s1++;
9878b790faSLoGin 		s2++;
9978b790faSLoGin 	}
10078b790faSLoGin 	return 0;
10178b790faSLoGin }
10278b790faSLoGin 
10378b790faSLoGin int strncmp(const char *cs, const char *ct, size_t count)
10478b790faSLoGin {
10578b790faSLoGin 	unsigned char c1, c2;
10678b790faSLoGin 
10778b790faSLoGin 	while (count) {
10878b790faSLoGin 		c1 = *cs++;
10978b790faSLoGin 		c2 = *ct++;
11078b790faSLoGin 		if (c1 != c2)
11178b790faSLoGin 			return c1 < c2 ? -1 : 1;
11278b790faSLoGin 		if (!c1)
11378b790faSLoGin 			break;
11478b790faSLoGin 		count--;
11578b790faSLoGin 	}
11678b790faSLoGin 	return 0;
11778b790faSLoGin }
11878b790faSLoGin 
11978b790faSLoGin size_t strnlen(const char *s, size_t maxlen)
12078b790faSLoGin {
12178b790faSLoGin 	const char *es = s;
12278b790faSLoGin 	while (*es && maxlen) {
12378b790faSLoGin 		es++;
12478b790faSLoGin 		maxlen--;
12578b790faSLoGin 	}
12678b790faSLoGin 
12778b790faSLoGin 	return (es - s);
12878b790faSLoGin }
129*3e6106c4SLoGin 
130*3e6106c4SLoGin #define __ALIGN (sizeof(size_t))
131*3e6106c4SLoGin #define ONES ((size_t)-1 / UCHAR_MAX)
132*3e6106c4SLoGin #define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
133*3e6106c4SLoGin #define HASZERO(x) ((x)-ONES & ~(x)&HIGHS)
134*3e6106c4SLoGin 
135*3e6106c4SLoGin char *__strchrnul(const char *s, int c)
136*3e6106c4SLoGin {
137*3e6106c4SLoGin 	c = (unsigned char)c;
138*3e6106c4SLoGin 	if (!c)
139*3e6106c4SLoGin 		return (char *)s + strlen(s);
140*3e6106c4SLoGin 
141*3e6106c4SLoGin #ifdef __GNUC__
142*3e6106c4SLoGin 	typedef size_t __attribute__((__may_alias__)) word;
143*3e6106c4SLoGin 	const word *w;
144*3e6106c4SLoGin 	for (; (uintptr_t)s % __ALIGN; s++)
145*3e6106c4SLoGin 		if (!*s || *(unsigned char *)s == c)
146*3e6106c4SLoGin 			return (char *)s;
147*3e6106c4SLoGin 	size_t k = ONES * c;
148*3e6106c4SLoGin 	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w ^ k); w++)
149*3e6106c4SLoGin 		;
150*3e6106c4SLoGin 	s = (void *)w;
151*3e6106c4SLoGin #endif
152*3e6106c4SLoGin 	for (; *s && *(unsigned char *)s != c; s++)
153*3e6106c4SLoGin 		;
154*3e6106c4SLoGin 	return (char *)s;
155*3e6106c4SLoGin }
156*3e6106c4SLoGin 
157*3e6106c4SLoGin char *strrchr(const char *s, int c)
158*3e6106c4SLoGin {
159*3e6106c4SLoGin 	return memrchr(s, c, strlen(s) + 1);
160*3e6106c4SLoGin }
161*3e6106c4SLoGin 
162*3e6106c4SLoGin char *strchr(const char *s, int c)
163*3e6106c4SLoGin {
164*3e6106c4SLoGin 	char *r = __strchrnul(s, c);
165*3e6106c4SLoGin 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
166*3e6106c4SLoGin }