xref: /DragonStub/apps/lib/string.c (revision 823f04931913f01ee1fc0dc0c7876156ad150388)
178b790faSLoGin 
278b790faSLoGin #include <dragonstub/dragonstub.h>
378b790faSLoGin 
skip_spaces(const char * str)478b790faSLoGin char *skip_spaces(const char *str)
578b790faSLoGin {
678b790faSLoGin 	while (isspace(*str))
778b790faSLoGin 		++str;
878b790faSLoGin 	return (char *)str;
978b790faSLoGin }
1078b790faSLoGin 
atou(const char * s)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 
simple_guess_base(const char * cp)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  */
strlen(const char * s)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  */
simple_strtoull(const char * cp,char ** endp,unsigned int base)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 
simple_strtol(const char * cp,char ** endp,unsigned int base)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 
strcmp(const char * str1,const char * str2)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 
strncmp(const char * cs,const char * ct,size_t count)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 
strnlen(const char * s,size_t maxlen)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 }
1293e6106c4SLoGin 
1303e6106c4SLoGin #define __ALIGN (sizeof(size_t))
1313e6106c4SLoGin #define ONES ((size_t)-1 / UCHAR_MAX)
1323e6106c4SLoGin #define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
1333e6106c4SLoGin #define HASZERO(x) ((x)-ONES & ~(x)&HIGHS)
1343e6106c4SLoGin 
__strchrnul(const char * s,int c)1353e6106c4SLoGin char *__strchrnul(const char *s, int c)
1363e6106c4SLoGin {
1373e6106c4SLoGin 	c = (unsigned char)c;
1383e6106c4SLoGin 	if (!c)
1393e6106c4SLoGin 		return (char *)s + strlen(s);
1403e6106c4SLoGin 
1413e6106c4SLoGin #ifdef __GNUC__
1423e6106c4SLoGin 	typedef size_t __attribute__((__may_alias__)) word;
1433e6106c4SLoGin 	const word *w;
1443e6106c4SLoGin 	for (; (uintptr_t)s % __ALIGN; s++)
1453e6106c4SLoGin 		if (!*s || *(unsigned char *)s == c)
1463e6106c4SLoGin 			return (char *)s;
1473e6106c4SLoGin 	size_t k = ONES * c;
1483e6106c4SLoGin 	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w ^ k); w++)
1493e6106c4SLoGin 		;
1503e6106c4SLoGin 	s = (void *)w;
1513e6106c4SLoGin #endif
1523e6106c4SLoGin 	for (; *s && *(unsigned char *)s != c; s++)
1533e6106c4SLoGin 		;
1543e6106c4SLoGin 	return (char *)s;
1553e6106c4SLoGin }
1563e6106c4SLoGin 
strrchr(const char * s,int c)1573e6106c4SLoGin char *strrchr(const char *s, int c)
1583e6106c4SLoGin {
1593e6106c4SLoGin 	return memrchr(s, c, strlen(s) + 1);
1603e6106c4SLoGin }
1613e6106c4SLoGin 
strchr(const char * s,int c)1623e6106c4SLoGin char *strchr(const char *s, int c)
1633e6106c4SLoGin {
1643e6106c4SLoGin 	char *r = __strchrnul(s, c);
1653e6106c4SLoGin 	return *(unsigned char *)r == (unsigned char)c ? r : 0;
1663e6106c4SLoGin }
167*823f0493SLoGin 
168*823f0493SLoGin /**
169*823f0493SLoGin  * strstr - Find the first substring in a %NUL terminated string
170*823f0493SLoGin  * @s1: The string to be searched
171*823f0493SLoGin  * @s2: The string to search for
172*823f0493SLoGin  */
strstr(const char * s1,const char * s2)173*823f0493SLoGin char *strstr(const char *s1, const char *s2)
174*823f0493SLoGin {
175*823f0493SLoGin 	size_t l1, l2;
176*823f0493SLoGin 
177*823f0493SLoGin 	l2 = strlen(s2);
178*823f0493SLoGin 	if (!l2)
179*823f0493SLoGin 		return (char *)s1;
180*823f0493SLoGin 	l1 = strlen(s1);
181*823f0493SLoGin 	while (l1 >= l2) {
182*823f0493SLoGin 		l1--;
183*823f0493SLoGin 		if (!memcmp(s1, s2, l2))
184*823f0493SLoGin 			return (char *)s1;
185*823f0493SLoGin 		s1++;
186*823f0493SLoGin 	}
187*823f0493SLoGin 	return NULL;
188*823f0493SLoGin }