xref: /kvm-unit-tests/lib/string.c (revision 4837df6e6f89b1d9b57a0a8c95c4f35385d63f16)
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 
10 unsigned long strlen(const char *buf)
11 {
12     unsigned long len = 0;
13 
14     while (*buf++)
15 	++len;
16     return len;
17 }
18 
19 char *strcat(char *dest, const char *src)
20 {
21     char *p = dest;
22 
23     while (*p)
24 	++p;
25     while ((*p++ = *src++) != 0)
26 	;
27     return dest;
28 }
29 
30 char *strcpy(char *dest, const char *src)
31 {
32     *dest = 0;
33     return strcat(dest, src);
34 }
35 
36 int strncmp(const char *a, const char *b, size_t n)
37 {
38     for (; n--; ++a, ++b)
39         if (*a != *b || *a == '\0')
40             return *a - *b;
41 
42     return 0;
43 }
44 
45 int strcmp(const char *a, const char *b)
46 {
47     return strncmp(a, b, SIZE_MAX);
48 }
49 
50 char *strchr(const char *s, int c)
51 {
52     while (*s != (char)c)
53 	if (*s++ == '\0')
54 	    return NULL;
55     return (char *)s;
56 }
57 
58 char *strstr(const char *s1, const char *s2)
59 {
60     size_t l1, l2;
61 
62     l2 = strlen(s2);
63     if (!l2)
64 	return (char *)s1;
65     l1 = strlen(s1);
66     while (l1 >= l2) {
67 	l1--;
68 	if (!memcmp(s1, s2, l2))
69 	    return (char *)s1;
70 	s1++;
71     }
72     return NULL;
73 }
74 
75 void *memset(void *s, int c, size_t n)
76 {
77     size_t i;
78     char *a = s;
79 
80     for (i = 0; i < n; ++i)
81         a[i] = c;
82 
83     return s;
84 }
85 
86 void *memcpy(void *dest, const void *src, size_t n)
87 {
88     size_t i;
89     char *a = dest;
90     const char *b = src;
91 
92     for (i = 0; i < n; ++i)
93         a[i] = b[i];
94 
95     return dest;
96 }
97 
98 int memcmp(const void *s1, const void *s2, size_t n)
99 {
100     const unsigned char *a = s1, *b = s2;
101     int ret = 0;
102 
103     while (n--) {
104 	ret = *a - *b;
105 	if (ret)
106 	    break;
107 	++a, ++b;
108     }
109     return ret;
110 }
111 
112 void *memmove(void *dest, const void *src, size_t n)
113 {
114     const unsigned char *s = src;
115     unsigned char *d = dest;
116 
117     if (d <= s) {
118 	while (n--)
119 	    *d++ = *s++;
120     } else {
121 	d += n, s += n;
122 	while (n--)
123 	    *--d = *--s;
124     }
125     return dest;
126 }
127 
128 void *memchr(const void *s, int c, size_t n)
129 {
130     const unsigned char *str = s, chr = (unsigned char)c;
131 
132     while (n--)
133 	if (*str++ == chr)
134 	    return (void *)(str - 1);
135     return NULL;
136 }
137 
138 long atol(const char *ptr)
139 {
140     long acc = 0;
141     const char *s = ptr;
142     int neg, c;
143 
144     while (*s == ' ' || *s == '\t')
145         s++;
146     if (*s == '-'){
147         neg = 1;
148         s++;
149     } else {
150         neg = 0;
151         if (*s == '+')
152             s++;
153     }
154 
155     while (*s) {
156         if (*s < '0' || *s > '9')
157             break;
158         c = *s - '0';
159         acc = acc * 10 + c;
160         s++;
161     }
162 
163     if (neg)
164         acc = -acc;
165 
166     return acc;
167 }
168 
169 extern char **environ;
170 
171 char *getenv(const char *name)
172 {
173     char **envp = environ, *delim;
174     int len;
175 
176     while (*envp) {
177         delim = strchr(*envp, '=');
178         assert(delim);
179         len = delim - *envp;
180         if (memcmp(name, *envp, len) == 0 && !name[len])
181             return delim + 1;
182         ++envp;
183     }
184     return NULL;
185 }
186 
187 /* Very simple glob matching. Allows '*' at beginning and end of pattern. */
188 bool simple_glob(const char *text, const char *pattern)
189 {
190 	bool star_start = false;
191 	bool star_end = false;
192 	size_t n = strlen(pattern);
193 	char copy[n + 1];
194 
195 	if (pattern[0] == '*') {
196 		pattern += 1;
197 		n -= 1;
198 		star_start = true;
199 	}
200 
201 	strcpy(copy, pattern);
202 
203 	if (n > 0 && pattern[n - 1] == '*') {
204 		n -= 1;
205 		copy[n] = '\0';
206 		star_end = true;
207 	}
208 
209 	if (star_start && star_end)
210 		return strstr(text, copy);
211 
212 	if (star_end)
213 		return strstr(text, copy) == text;
214 
215 	if (star_start) {
216 		size_t text_len = strlen(text);
217 		const char *suffix;
218 
219 		if (n > text_len)
220 			return false;
221 		suffix = text + text_len - n;
222 		return !strcmp(suffix, copy);
223 	}
224 
225 	return !strcmp(text, copy);
226 }
227