xref: /kvm-unit-tests/lib/string.c (revision 48d5952451de62a4db23cf73024f702cf1a64fc3)
14b6da826SThomas Huth /*
24b6da826SThomas Huth  * libc string functions
34b6da826SThomas Huth  *
44b6da826SThomas Huth  * This code is free software; you can redistribute it and/or modify it
54b6da826SThomas Huth  * under the terms of the GNU Library General Public License version 2.
64b6da826SThomas Huth  */
74b6da826SThomas Huth 
87d36db35SAvi Kivity #include "libcflat.h"
95927d1c2SAndrew Jones #include "ctype.h"
10b5501ed0SNikos Nikoleris #include "stdlib.h"
11b5501ed0SNikos Nikoleris #include "linux/compiler.h"
127d36db35SAvi Kivity 
strlen(const char * buf)13b5501ed0SNikos Nikoleris size_t strlen(const char *buf)
147d36db35SAvi Kivity {
15b5501ed0SNikos Nikoleris 	size_t len = 0;
167d36db35SAvi Kivity 
177d36db35SAvi Kivity 	while (*buf++)
187d36db35SAvi Kivity 		++len;
197d36db35SAvi Kivity 	return len;
207d36db35SAvi Kivity }
217d36db35SAvi Kivity 
strnlen(const char * buf,size_t maxlen)22b5501ed0SNikos Nikoleris size_t strnlen(const char *buf, size_t maxlen)
23b5501ed0SNikos Nikoleris {
24b5501ed0SNikos Nikoleris 	const char *sc;
25b5501ed0SNikos Nikoleris 
26b5501ed0SNikos Nikoleris 	for (sc = buf; maxlen-- && *sc != '\0'; ++sc)
27b5501ed0SNikos Nikoleris 		/* nothing */ ;
28b5501ed0SNikos Nikoleris 	return sc - buf;
29b5501ed0SNikos Nikoleris }
30b5501ed0SNikos Nikoleris 
strcat(char * dest,const char * src)317d36db35SAvi Kivity char *strcat(char *dest, const char *src)
327d36db35SAvi Kivity {
337d36db35SAvi Kivity 	char *p = dest;
347d36db35SAvi Kivity 
357d36db35SAvi Kivity 	while (*p)
367d36db35SAvi Kivity 		++p;
377d36db35SAvi Kivity 	while ((*p++ = *src++) != 0)
387d36db35SAvi Kivity 		;
397d36db35SAvi Kivity 	return dest;
407d36db35SAvi Kivity }
417d36db35SAvi Kivity 
strcpy(char * dest,const char * src)42782ebe33SAndrew Jones char *strcpy(char *dest, const char *src)
43782ebe33SAndrew Jones {
44782ebe33SAndrew Jones 	*dest = 0;
45782ebe33SAndrew Jones 	return strcat(dest, src);
46782ebe33SAndrew Jones }
47782ebe33SAndrew Jones 
strncmp(const char * a,const char * b,size_t n)484fd53297SRadim Krčmář int strncmp(const char *a, const char *b, size_t n)
494fd53297SRadim Krčmář {
504fd53297SRadim Krčmář 	for (; n--; ++a, ++b)
514fd53297SRadim Krčmář 		if (*a != *b || *a == '\0')
524fd53297SRadim Krčmář 			return *a - *b;
534fd53297SRadim Krčmář 
544fd53297SRadim Krčmář 	return 0;
554fd53297SRadim Krčmář }
564fd53297SRadim Krčmář 
strncasecmp(const char * a,const char * b,size_t n)57*24aec76aSAndrew Jones int strncasecmp(const char *a, const char *b, size_t n)
58*24aec76aSAndrew Jones {
59*24aec76aSAndrew Jones 	for (; n--; ++a, ++b)
60*24aec76aSAndrew Jones 		if (tolower(*a) != tolower(*b) || *a == '\0')
61*24aec76aSAndrew Jones 			return tolower(*a) - tolower(*b);
62*24aec76aSAndrew Jones 
63*24aec76aSAndrew Jones 	return 0;
64*24aec76aSAndrew Jones }
65*24aec76aSAndrew Jones 
strcmp(const char * a,const char * b)6669da6c87SAvi Kivity int strcmp(const char *a, const char *b)
6769da6c87SAvi Kivity {
684fd53297SRadim Krčmář 	return strncmp(a, b, SIZE_MAX);
6969da6c87SAvi Kivity }
7069da6c87SAvi Kivity 
strcasecmp(const char * a,const char * b)71*24aec76aSAndrew Jones int strcasecmp(const char *a, const char *b)
72*24aec76aSAndrew Jones {
73*24aec76aSAndrew Jones 	return strncasecmp(a, b, SIZE_MAX);
74*24aec76aSAndrew Jones }
75*24aec76aSAndrew Jones 
strchr(const char * s,int c)76782ebe33SAndrew Jones char *strchr(const char *s, int c)
77782ebe33SAndrew Jones {
78782ebe33SAndrew Jones 	while (*s != (char)c)
79782ebe33SAndrew Jones 		if (*s++ == '\0')
80782ebe33SAndrew Jones 			return NULL;
81782ebe33SAndrew Jones 	return (char *)s;
82782ebe33SAndrew Jones }
83782ebe33SAndrew Jones 
strrchr(const char * s,int c)84b5501ed0SNikos Nikoleris char *strrchr(const char *s, int c)
85b5501ed0SNikos Nikoleris {
86b5501ed0SNikos Nikoleris 	const char *last = NULL;
87b5501ed0SNikos Nikoleris 	do {
88b5501ed0SNikos Nikoleris 		if (*s == (char)c)
89b5501ed0SNikos Nikoleris 			last = s;
90b5501ed0SNikos Nikoleris 	} while (*s++);
91b5501ed0SNikos Nikoleris 	return (char *)last;
92b5501ed0SNikos Nikoleris }
93b5501ed0SNikos Nikoleris 
strchrnul(const char * s,int c)94546914b4SNikos Nikoleris char *strchrnul(const char *s, int c)
95546914b4SNikos Nikoleris {
96546914b4SNikos Nikoleris 	while (*s && *s != (char)c)
97546914b4SNikos Nikoleris 		s++;
98546914b4SNikos Nikoleris 	return (char *)s;
99546914b4SNikos Nikoleris }
100546914b4SNikos Nikoleris 
strstr(const char * s1,const char * s2)10153da5cc0SAndrew Jones char *strstr(const char *s1, const char *s2)
10253da5cc0SAndrew Jones {
10353da5cc0SAndrew Jones 	size_t l1, l2;
10453da5cc0SAndrew Jones 
10553da5cc0SAndrew Jones 	l2 = strlen(s2);
10653da5cc0SAndrew Jones 	if (!l2)
10753da5cc0SAndrew Jones 		return (char *)s1;
10853da5cc0SAndrew Jones 	l1 = strlen(s1);
10953da5cc0SAndrew Jones 	while (l1 >= l2) {
11053da5cc0SAndrew Jones 		l1--;
11153da5cc0SAndrew Jones 		if (!memcmp(s1, s2, l2))
11253da5cc0SAndrew Jones 			return (char *)s1;
11353da5cc0SAndrew Jones 		s1++;
11453da5cc0SAndrew Jones 	}
11553da5cc0SAndrew Jones 	return NULL;
11653da5cc0SAndrew Jones }
11753da5cc0SAndrew Jones 
memset(void * s,int c,size_t n)1187d36db35SAvi Kivity void *memset(void *s, int c, size_t n)
1197d36db35SAvi Kivity {
1207d36db35SAvi Kivity 	size_t i;
1217d36db35SAvi Kivity 	char *a = s;
1227d36db35SAvi Kivity 
1237d36db35SAvi Kivity 	for (i = 0; i < n; ++i)
1247d36db35SAvi Kivity 		a[i] = c;
1257d36db35SAvi Kivity 
1267d36db35SAvi Kivity 	return s;
1277d36db35SAvi Kivity }
1281b708e8cSJason Wang 
memcpy(void * dest,const void * src,size_t n)1298d68030eSArthur Chunqi Li void *memcpy(void *dest, const void *src, size_t n)
1308d68030eSArthur Chunqi Li {
1318d68030eSArthur Chunqi Li 	size_t i;
1328d68030eSArthur Chunqi Li 	char *a = dest;
1338d68030eSArthur Chunqi Li 	const char *b = src;
1348d68030eSArthur Chunqi Li 
1358d68030eSArthur Chunqi Li 	for (i = 0; i < n; ++i)
1368d68030eSArthur Chunqi Li 		a[i] = b[i];
1378d68030eSArthur Chunqi Li 
1388d68030eSArthur Chunqi Li 	return dest;
1398d68030eSArthur Chunqi Li }
1408d68030eSArthur Chunqi Li 
memcmp(const void * s1,const void * s2,size_t n)141782ebe33SAndrew Jones int memcmp(const void *s1, const void *s2, size_t n)
142782ebe33SAndrew Jones {
143782ebe33SAndrew Jones 	const unsigned char *a = s1, *b = s2;
144782ebe33SAndrew Jones 	int ret = 0;
145782ebe33SAndrew Jones 
146782ebe33SAndrew Jones 	while (n--) {
147782ebe33SAndrew Jones 		ret = *a - *b;
148782ebe33SAndrew Jones 		if (ret)
149782ebe33SAndrew Jones 			break;
150782ebe33SAndrew Jones 		++a, ++b;
151782ebe33SAndrew Jones 	}
152782ebe33SAndrew Jones 	return ret;
153782ebe33SAndrew Jones }
154782ebe33SAndrew Jones 
memmove(void * dest,const void * src,size_t n)155782ebe33SAndrew Jones void *memmove(void *dest, const void *src, size_t n)
156782ebe33SAndrew Jones {
157782ebe33SAndrew Jones 	const unsigned char *s = src;
158782ebe33SAndrew Jones 	unsigned char *d = dest;
159782ebe33SAndrew Jones 
160782ebe33SAndrew Jones 	if (d <= s) {
161782ebe33SAndrew Jones 		while (n--)
162782ebe33SAndrew Jones 			*d++ = *s++;
163782ebe33SAndrew Jones 	} else {
164782ebe33SAndrew Jones 		d += n, s += n;
165782ebe33SAndrew Jones 		while (n--)
166782ebe33SAndrew Jones 			*--d = *--s;
167782ebe33SAndrew Jones 	}
168782ebe33SAndrew Jones 	return dest;
169782ebe33SAndrew Jones }
170782ebe33SAndrew Jones 
memchr(const void * s,int c,size_t n)171782ebe33SAndrew Jones void *memchr(const void *s, int c, size_t n)
172782ebe33SAndrew Jones {
173782ebe33SAndrew Jones 	const unsigned char *str = s, chr = (unsigned char)c;
174782ebe33SAndrew Jones 
175782ebe33SAndrew Jones 	while (n--)
176782ebe33SAndrew Jones 		if (*str++ == chr)
177782ebe33SAndrew Jones 			return (void *)(str - 1);
178782ebe33SAndrew Jones 	return NULL;
179782ebe33SAndrew Jones }
180782ebe33SAndrew Jones 
__strtoll(const char * nptr,char ** endptr,int base,bool is_signed,bool is_longlong)1817f1ca26cSAndrew Jones static unsigned long long __strtoll(const char *nptr, char **endptr,
1820e981298SAndrew Jones 				    int base, bool is_signed, bool is_longlong)
1830e981298SAndrew Jones {
1847f1ca26cSAndrew Jones 	unsigned long long ull = 0;
185b5501ed0SNikos Nikoleris 	const char *s = nptr;
1861b708e8cSJason Wang 	int neg, c;
1871b708e8cSJason Wang 
188b5501ed0SNikos Nikoleris 	assert(base == 0 || (base >= 2 && base <= 36));
189b5501ed0SNikos Nikoleris 
190b5501ed0SNikos Nikoleris 	while (isspace(*s))
1911b708e8cSJason Wang 		s++;
192b5501ed0SNikos Nikoleris 
1931b708e8cSJason Wang 	if (*s == '-') {
1941b708e8cSJason Wang 		neg = 1;
1951b708e8cSJason Wang 		s++;
1961b708e8cSJason Wang 	} else {
1971b708e8cSJason Wang 		neg = 0;
1981b708e8cSJason Wang 		if (*s == '+')
1991b708e8cSJason Wang 			s++;
2001b708e8cSJason Wang 	}
2011b708e8cSJason Wang 
202b5501ed0SNikos Nikoleris 	if (base == 0 || base == 16) {
203b5501ed0SNikos Nikoleris 		if (*s == '0') {
204b5501ed0SNikos Nikoleris 			s++;
205b5501ed0SNikos Nikoleris 			if (*s == 'x' || *s == 'X') {
206b5501ed0SNikos Nikoleris 				s++;
207b5501ed0SNikos Nikoleris 				base = 16;
208b5501ed0SNikos Nikoleris 			} else if (base == 0)
209b5501ed0SNikos Nikoleris 				base = 8;
210b5501ed0SNikos Nikoleris 		} else if (base == 0)
211b5501ed0SNikos Nikoleris 			base = 10;
212b5501ed0SNikos Nikoleris 	}
213b5501ed0SNikos Nikoleris 
2141b708e8cSJason Wang 	while (*s) {
215b5501ed0SNikos Nikoleris 		if (*s >= '0' && *s < '0' + base && *s <= '9')
2161b708e8cSJason Wang 			c = *s - '0';
217b5501ed0SNikos Nikoleris 		else if (*s >= 'a' && *s < 'a' + base - 10)
218b5501ed0SNikos Nikoleris 			c = *s - 'a' + 10;
219b5501ed0SNikos Nikoleris 		else if (*s >= 'A' && *s < 'A' + base - 10)
220b5501ed0SNikos Nikoleris 			c = *s - 'A' + 10;
221b5501ed0SNikos Nikoleris 		else
222b5501ed0SNikos Nikoleris 			break;
223b5501ed0SNikos Nikoleris 
2247f1ca26cSAndrew Jones 		if (!is_longlong) {
225b5501ed0SNikos Nikoleris 			if (is_signed) {
2267f1ca26cSAndrew Jones 				long sl = (long)ull;
2277f1ca26cSAndrew Jones 				assert(!check_mul_overflow(sl, base));
2287f1ca26cSAndrew Jones 				assert(!check_add_overflow(sl * base, c));
229b5501ed0SNikos Nikoleris 			} else {
2307f1ca26cSAndrew Jones 				unsigned long ul = (unsigned long)ull;
2317f1ca26cSAndrew Jones 				assert(!check_mul_overflow(ul, base));
2327f1ca26cSAndrew Jones 				assert(!check_add_overflow(ul * base, c));
2337f1ca26cSAndrew Jones 			}
2347f1ca26cSAndrew Jones 		} else {
2357f1ca26cSAndrew Jones 			if (is_signed) {
2367f1ca26cSAndrew Jones 				long long sll = (long long)ull;
2377f1ca26cSAndrew Jones 				assert(!check_mul_overflow(sll, base));
2387f1ca26cSAndrew Jones 				assert(!check_add_overflow(sll * base, c));
2397f1ca26cSAndrew Jones 			} else {
2407f1ca26cSAndrew Jones 				assert(!check_mul_overflow(ull, base));
2417f1ca26cSAndrew Jones 				assert(!check_add_overflow(ull * base, c));
2427f1ca26cSAndrew Jones 			}
243b5501ed0SNikos Nikoleris 		}
244b5501ed0SNikos Nikoleris 
2457f1ca26cSAndrew Jones 		ull = ull * base + c;
2461b708e8cSJason Wang 		s++;
2471b708e8cSJason Wang 	}
2481b708e8cSJason Wang 
2491b708e8cSJason Wang 	if (neg)
2507f1ca26cSAndrew Jones 		ull = -ull;
2511b708e8cSJason Wang 
252b5501ed0SNikos Nikoleris 	if (endptr)
253b5501ed0SNikos Nikoleris 		*endptr = (char *)s;
254b5501ed0SNikos Nikoleris 
2557f1ca26cSAndrew Jones 	return ull;
2561b708e8cSJason Wang }
25769205bf1SAndrew Jones 
strtol(const char * nptr,char ** endptr,int base)258b5501ed0SNikos Nikoleris long int strtol(const char *nptr, char **endptr, int base)
259b5501ed0SNikos Nikoleris {
2607f1ca26cSAndrew Jones 	return __strtoll(nptr, endptr, base, true, false);
261b5501ed0SNikos Nikoleris }
262b5501ed0SNikos Nikoleris 
strtoul(const char * nptr,char ** endptr,int base)263b5501ed0SNikos Nikoleris unsigned long int strtoul(const char *nptr, char **endptr, int base)
264b5501ed0SNikos Nikoleris {
2657f1ca26cSAndrew Jones 	return __strtoll(nptr, endptr, base, false, false);
2667f1ca26cSAndrew Jones }
2677f1ca26cSAndrew Jones 
strtoll(const char * nptr,char ** endptr,int base)2687f1ca26cSAndrew Jones long long int strtoll(const char *nptr, char **endptr, int base)
2697f1ca26cSAndrew Jones {
2707f1ca26cSAndrew Jones 	return __strtoll(nptr, endptr, base, true, true);
2717f1ca26cSAndrew Jones }
2727f1ca26cSAndrew Jones 
strtoull(const char * nptr,char ** endptr,int base)2737f1ca26cSAndrew Jones unsigned long long int strtoull(const char *nptr, char **endptr, int base)
2747f1ca26cSAndrew Jones {
2757f1ca26cSAndrew Jones 	return __strtoll(nptr, endptr, base, false, true);
276b5501ed0SNikos Nikoleris }
277b5501ed0SNikos Nikoleris 
atol(const char * ptr)278b5501ed0SNikos Nikoleris long atol(const char *ptr)
279b5501ed0SNikos Nikoleris {
280b5501ed0SNikos Nikoleris 	return strtol(ptr, NULL, 10);
281b5501ed0SNikos Nikoleris }
282b5501ed0SNikos Nikoleris 
28369205bf1SAndrew Jones extern char **environ;
28469205bf1SAndrew Jones 
getenv(const char * name)28569205bf1SAndrew Jones char *getenv(const char *name)
28669205bf1SAndrew Jones {
28769205bf1SAndrew Jones 	char **envp = environ, *delim;
2884837df6eSAndrew Jones 	int len;
28969205bf1SAndrew Jones 
29069205bf1SAndrew Jones 	while (*envp) {
29169205bf1SAndrew Jones 		delim = strchr(*envp, '=');
2924837df6eSAndrew Jones 		assert(delim);
2934837df6eSAndrew Jones 		len = delim - *envp;
2944837df6eSAndrew Jones 		if (memcmp(name, *envp, len) == 0 && !name[len])
29569205bf1SAndrew Jones 			return delim + 1;
29669205bf1SAndrew Jones 		++envp;
29769205bf1SAndrew Jones 	}
29869205bf1SAndrew Jones 	return NULL;
29969205bf1SAndrew Jones }
300875b97b3SPeter Feiner 
301875b97b3SPeter Feiner /* Very simple glob matching. Allows '*' at beginning and end of pattern. */
simple_glob(const char * text,const char * pattern)302875b97b3SPeter Feiner bool simple_glob(const char *text, const char *pattern)
303875b97b3SPeter Feiner {
304875b97b3SPeter Feiner 	bool star_start = false;
305875b97b3SPeter Feiner 	bool star_end = false;
306875b97b3SPeter Feiner 	size_t n = strlen(pattern);
307875b97b3SPeter Feiner 	char copy[n + 1];
308875b97b3SPeter Feiner 
309875b97b3SPeter Feiner 	if (pattern[0] == '*') {
310875b97b3SPeter Feiner 		pattern += 1;
311875b97b3SPeter Feiner 		n -= 1;
312875b97b3SPeter Feiner 		star_start = true;
313875b97b3SPeter Feiner 	}
314875b97b3SPeter Feiner 
315875b97b3SPeter Feiner 	strcpy(copy, pattern);
316875b97b3SPeter Feiner 
317875b97b3SPeter Feiner 	if (n > 0 && pattern[n - 1] == '*') {
318875b97b3SPeter Feiner 		n -= 1;
319875b97b3SPeter Feiner 		copy[n] = '\0';
320875b97b3SPeter Feiner 		star_end = true;
321875b97b3SPeter Feiner 	}
322875b97b3SPeter Feiner 
323875b97b3SPeter Feiner 	if (star_start && star_end)
324875b97b3SPeter Feiner 		return strstr(text, copy);
325875b97b3SPeter Feiner 
326875b97b3SPeter Feiner 	if (star_end)
327875b97b3SPeter Feiner 		return strstr(text, copy) == text;
328875b97b3SPeter Feiner 
329875b97b3SPeter Feiner 	if (star_start) {
330875b97b3SPeter Feiner 		size_t text_len = strlen(text);
331875b97b3SPeter Feiner 		const char *suffix;
332875b97b3SPeter Feiner 
333875b97b3SPeter Feiner 		if (n > text_len)
334875b97b3SPeter Feiner 			return false;
335875b97b3SPeter Feiner 		suffix = text + text_len - n;
336875b97b3SPeter Feiner 		return !strcmp(suffix, copy);
337875b97b3SPeter Feiner 	}
338875b97b3SPeter Feiner 
339875b97b3SPeter Feiner 	return !strcmp(text, copy);
340875b97b3SPeter Feiner }
341