xref: /kvm-unit-tests/lib/string.c (revision 48d5952451de62a4db23cf73024f702cf1a64fc3)
1 /*
2  * libc string functions
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Library General Public License version 2.
6  */
7 
8 #include "libcflat.h"
9 #include "ctype.h"
10 #include "stdlib.h"
11 #include "linux/compiler.h"
12 
strlen(const char * buf)13 size_t strlen(const char *buf)
14 {
15 	size_t len = 0;
16 
17 	while (*buf++)
18 		++len;
19 	return len;
20 }
21 
strnlen(const char * buf,size_t maxlen)22 size_t strnlen(const char *buf, size_t maxlen)
23 {
24 	const char *sc;
25 
26 	for (sc = buf; maxlen-- && *sc != '\0'; ++sc)
27 		/* nothing */ ;
28 	return sc - buf;
29 }
30 
strcat(char * dest,const char * src)31 char *strcat(char *dest, const char *src)
32 {
33 	char *p = dest;
34 
35 	while (*p)
36 		++p;
37 	while ((*p++ = *src++) != 0)
38 		;
39 	return dest;
40 }
41 
strcpy(char * dest,const char * src)42 char *strcpy(char *dest, const char *src)
43 {
44 	*dest = 0;
45 	return strcat(dest, src);
46 }
47 
strncmp(const char * a,const char * b,size_t n)48 int strncmp(const char *a, const char *b, size_t n)
49 {
50 	for (; n--; ++a, ++b)
51 		if (*a != *b || *a == '\0')
52 			return *a - *b;
53 
54 	return 0;
55 }
56 
strncasecmp(const char * a,const char * b,size_t n)57 int strncasecmp(const char *a, const char *b, size_t n)
58 {
59 	for (; n--; ++a, ++b)
60 		if (tolower(*a) != tolower(*b) || *a == '\0')
61 			return tolower(*a) - tolower(*b);
62 
63 	return 0;
64 }
65 
strcmp(const char * a,const char * b)66 int strcmp(const char *a, const char *b)
67 {
68 	return strncmp(a, b, SIZE_MAX);
69 }
70 
strcasecmp(const char * a,const char * b)71 int strcasecmp(const char *a, const char *b)
72 {
73 	return strncasecmp(a, b, SIZE_MAX);
74 }
75 
strchr(const char * s,int c)76 char *strchr(const char *s, int c)
77 {
78 	while (*s != (char)c)
79 		if (*s++ == '\0')
80 			return NULL;
81 	return (char *)s;
82 }
83 
strrchr(const char * s,int c)84 char *strrchr(const char *s, int c)
85 {
86 	const char *last = NULL;
87 	do {
88 		if (*s == (char)c)
89 			last = s;
90 	} while (*s++);
91 	return (char *)last;
92 }
93 
strchrnul(const char * s,int c)94 char *strchrnul(const char *s, int c)
95 {
96 	while (*s && *s != (char)c)
97 		s++;
98 	return (char *)s;
99 }
100 
strstr(const char * s1,const char * s2)101 char *strstr(const char *s1, const char *s2)
102 {
103 	size_t l1, l2;
104 
105 	l2 = strlen(s2);
106 	if (!l2)
107 		return (char *)s1;
108 	l1 = strlen(s1);
109 	while (l1 >= l2) {
110 		l1--;
111 		if (!memcmp(s1, s2, l2))
112 			return (char *)s1;
113 		s1++;
114 	}
115 	return NULL;
116 }
117 
memset(void * s,int c,size_t n)118 void *memset(void *s, int c, size_t n)
119 {
120 	size_t i;
121 	char *a = s;
122 
123 	for (i = 0; i < n; ++i)
124 		a[i] = c;
125 
126 	return s;
127 }
128 
memcpy(void * dest,const void * src,size_t n)129 void *memcpy(void *dest, const void *src, size_t n)
130 {
131 	size_t i;
132 	char *a = dest;
133 	const char *b = src;
134 
135 	for (i = 0; i < n; ++i)
136 		a[i] = b[i];
137 
138 	return dest;
139 }
140 
memcmp(const void * s1,const void * s2,size_t n)141 int memcmp(const void *s1, const void *s2, size_t n)
142 {
143 	const unsigned char *a = s1, *b = s2;
144 	int ret = 0;
145 
146 	while (n--) {
147 		ret = *a - *b;
148 		if (ret)
149 			break;
150 		++a, ++b;
151 	}
152 	return ret;
153 }
154 
memmove(void * dest,const void * src,size_t n)155 void *memmove(void *dest, const void *src, size_t n)
156 {
157 	const unsigned char *s = src;
158 	unsigned char *d = dest;
159 
160 	if (d <= s) {
161 		while (n--)
162 			*d++ = *s++;
163 	} else {
164 		d += n, s += n;
165 		while (n--)
166 			*--d = *--s;
167 	}
168 	return dest;
169 }
170 
memchr(const void * s,int c,size_t n)171 void *memchr(const void *s, int c, size_t n)
172 {
173 	const unsigned char *str = s, chr = (unsigned char)c;
174 
175 	while (n--)
176 		if (*str++ == chr)
177 			return (void *)(str - 1);
178 	return NULL;
179 }
180 
__strtoll(const char * nptr,char ** endptr,int base,bool is_signed,bool is_longlong)181 static unsigned long long __strtoll(const char *nptr, char **endptr,
182 				    int base, bool is_signed, bool is_longlong)
183 {
184 	unsigned long long ull = 0;
185 	const char *s = nptr;
186 	int neg, c;
187 
188 	assert(base == 0 || (base >= 2 && base <= 36));
189 
190 	while (isspace(*s))
191 		s++;
192 
193 	if (*s == '-') {
194 		neg = 1;
195 		s++;
196 	} else {
197 		neg = 0;
198 		if (*s == '+')
199 			s++;
200 	}
201 
202 	if (base == 0 || base == 16) {
203 		if (*s == '0') {
204 			s++;
205 			if (*s == 'x' || *s == 'X') {
206 				s++;
207 				base = 16;
208 			} else if (base == 0)
209 				base = 8;
210 		} else if (base == 0)
211 			base = 10;
212 	}
213 
214 	while (*s) {
215 		if (*s >= '0' && *s < '0' + base && *s <= '9')
216 			c = *s - '0';
217 		else if (*s >= 'a' && *s < 'a' + base - 10)
218 			c = *s - 'a' + 10;
219 		else if (*s >= 'A' && *s < 'A' + base - 10)
220 			c = *s - 'A' + 10;
221 		else
222 			break;
223 
224 		if (!is_longlong) {
225 			if (is_signed) {
226 				long sl = (long)ull;
227 				assert(!check_mul_overflow(sl, base));
228 				assert(!check_add_overflow(sl * base, c));
229 			} else {
230 				unsigned long ul = (unsigned long)ull;
231 				assert(!check_mul_overflow(ul, base));
232 				assert(!check_add_overflow(ul * base, c));
233 			}
234 		} else {
235 			if (is_signed) {
236 				long long sll = (long long)ull;
237 				assert(!check_mul_overflow(sll, base));
238 				assert(!check_add_overflow(sll * base, c));
239 			} else {
240 				assert(!check_mul_overflow(ull, base));
241 				assert(!check_add_overflow(ull * base, c));
242 			}
243 		}
244 
245 		ull = ull * base + c;
246 		s++;
247 	}
248 
249 	if (neg)
250 		ull = -ull;
251 
252 	if (endptr)
253 		*endptr = (char *)s;
254 
255 	return ull;
256 }
257 
strtol(const char * nptr,char ** endptr,int base)258 long int strtol(const char *nptr, char **endptr, int base)
259 {
260 	return __strtoll(nptr, endptr, base, true, false);
261 }
262 
strtoul(const char * nptr,char ** endptr,int base)263 unsigned long int strtoul(const char *nptr, char **endptr, int base)
264 {
265 	return __strtoll(nptr, endptr, base, false, false);
266 }
267 
strtoll(const char * nptr,char ** endptr,int base)268 long long int strtoll(const char *nptr, char **endptr, int base)
269 {
270 	return __strtoll(nptr, endptr, base, true, true);
271 }
272 
strtoull(const char * nptr,char ** endptr,int base)273 unsigned long long int strtoull(const char *nptr, char **endptr, int base)
274 {
275 	return __strtoll(nptr, endptr, base, false, true);
276 }
277 
atol(const char * ptr)278 long atol(const char *ptr)
279 {
280 	return strtol(ptr, NULL, 10);
281 }
282 
283 extern char **environ;
284 
getenv(const char * name)285 char *getenv(const char *name)
286 {
287 	char **envp = environ, *delim;
288 	int len;
289 
290 	while (*envp) {
291 		delim = strchr(*envp, '=');
292 		assert(delim);
293 		len = delim - *envp;
294 		if (memcmp(name, *envp, len) == 0 && !name[len])
295 			return delim + 1;
296 		++envp;
297 	}
298 	return NULL;
299 }
300 
301 /* Very simple glob matching. Allows '*' at beginning and end of pattern. */
simple_glob(const char * text,const char * pattern)302 bool simple_glob(const char *text, const char *pattern)
303 {
304 	bool star_start = false;
305 	bool star_end = false;
306 	size_t n = strlen(pattern);
307 	char copy[n + 1];
308 
309 	if (pattern[0] == '*') {
310 		pattern += 1;
311 		n -= 1;
312 		star_start = true;
313 	}
314 
315 	strcpy(copy, pattern);
316 
317 	if (n > 0 && pattern[n - 1] == '*') {
318 		n -= 1;
319 		copy[n] = '\0';
320 		star_end = true;
321 	}
322 
323 	if (star_start && star_end)
324 		return strstr(text, copy);
325 
326 	if (star_end)
327 		return strstr(text, copy) == text;
328 
329 	if (star_start) {
330 		size_t text_len = strlen(text);
331 		const char *suffix;
332 
333 		if (n > text_len)
334 			return false;
335 		suffix = text + text_len - n;
336 		return !strcmp(suffix, copy);
337 	}
338 
339 	return !strcmp(text, copy);
340 }
341