1 /* string.c - common string routines */
2 
3 /*
4  * Copyright (c) 2014 Wind River Systems, Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <string.h>
10 #include <stdint.h>
11 #include <sys/types.h>
12 
13 /**
14  *
15  * @brief Copy a string
16  *
17  * @return pointer to destination buffer <d>
18  */
19 
strcpy(char * _MLIBC_RESTRICT d,const char * _MLIBC_RESTRICT s)20 char *strcpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s)
21 {
22 	char *dest = d;
23 
24 	while (*s != '\0') {
25 		*d = *s;
26 		d++;
27 		s++;
28 	}
29 
30 	*d = '\0';
31 
32 	return dest;
33 }
34 
35 /**
36  *
37  * @brief Copy part of a string
38  *
39  * @return pointer to destination buffer <d>
40  */
41 
strncpy(char * _MLIBC_RESTRICT d,const char * _MLIBC_RESTRICT s,size_t n)42 char *strncpy(char *_MLIBC_RESTRICT d, const char *_MLIBC_RESTRICT s, size_t n)
43 {
44 	char *dest = d;
45 
46 	while ((n > 0) && *s != '\0') {
47 		*d = *s;
48 		s++;
49 		d++;
50 		n--;
51 	}
52 
53 	while (n > 0) {
54 		*d = '\0';
55 		d++;
56 		n--;
57 	}
58 
59 	return dest;
60 }
61 
62 /**
63  *
64  * @brief String scanning operation
65  *
66  * @return pointer to 1st instance of found byte, or NULL if not found
67  */
68 
strchr(const char * s,int c)69 char *strchr(const char *s, int c)
70 {
71 	char tmp = (char) c;
72 
73 	while ((*s != tmp) && (*s != '\0')) {
74 		s++;
75 	}
76 
77 	return (*s == tmp) ? (char *) s : NULL;
78 }
79 
80 /**
81  *
82  * @brief String scanning operation
83  *
84  * @return pointer to last instance of found byte, or NULL if not found
85  */
86 
strrchr(const char * s,int c)87 char *strrchr(const char *s, int c)
88 {
89 	char *match = NULL;
90 
91 	do {
92 		if (*s == (char)c) {
93 			match = (char *)s;
94 		}
95 	} while (*s++);
96 
97 	return match;
98 }
99 
100 /**
101  *
102  * @brief Get string length
103  *
104  * @return number of bytes in string <s>
105  */
106 
strlen(const char * s)107 size_t strlen(const char *s)
108 {
109 	size_t n = 0;
110 
111 	while (*s != '\0') {
112 		s++;
113 		n++;
114 	}
115 
116 	return n;
117 }
118 
119 /**
120  *
121  * @brief Get fixed-size string length
122  *
123  * @return number of bytes in fixed-size string <s>
124  */
125 
strnlen(const char * s,size_t maxlen)126 size_t strnlen(const char *s, size_t maxlen)
127 {
128 	size_t n = 0;
129 
130 	while (*s != '\0' && n < maxlen) {
131 		s++;
132 		n++;
133 	}
134 
135 	return n;
136 }
137 
138 /**
139  *
140  * @brief Compare two strings
141  *
142  * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
143  */
144 
strcmp(const char * s1,const char * s2)145 int strcmp(const char *s1, const char *s2)
146 {
147 	while ((*s1 == *s2) && (*s1 != '\0')) {
148 		s1++;
149 		s2++;
150 	}
151 
152 	return *s1 - *s2;
153 }
154 
155 /**
156  *
157  * @brief Compare part of two strings
158  *
159  * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
160  */
161 
strncmp(const char * s1,const char * s2,size_t n)162 int strncmp(const char *s1, const char *s2, size_t n)
163 {
164 	while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
165 		s1++;
166 		s2++;
167 		n--;
168 	}
169 
170 	return (n == 0) ? 0 : (*s1 - *s2);
171 }
172 
173 /**
174  * @brief Separate `str` by any char in `sep` and return NULL terminated
175  * sections. Consecutive `sep` chars in `str` are treated as a single
176  * separator.
177  *
178  * @return pointer to NULL terminated string or NULL on errors.
179  */
strtok_r(char * str,const char * sep,char ** state)180 char *strtok_r(char *str, const char *sep, char **state)
181 {
182 	char *start, *end;
183 
184 	start = str ? str : *state;
185 
186 	/* skip leading delimiters */
187 	while (*start && strchr(sep, *start)) {
188 		start++;
189 	}
190 
191 	if (*start == '\0') {
192 		*state = start;
193 		return NULL;
194 	}
195 
196 	/* look for token chars */
197 	end = start;
198 	while (*end && !strchr(sep, *end)) {
199 		end++;
200 	}
201 
202 	if (*end != '\0') {
203 		*end = '\0';
204 		*state = end + 1;
205 	} else {
206 		*state = end;
207 	}
208 
209 	return start;
210 }
211 
strcat(char * _MLIBC_RESTRICT dest,const char * _MLIBC_RESTRICT src)212 char *strcat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src)
213 {
214 	strcpy(dest + strlen(dest), src);
215 	return dest;
216 }
217 
strncat(char * _MLIBC_RESTRICT dest,const char * _MLIBC_RESTRICT src,size_t n)218 char *strncat(char *_MLIBC_RESTRICT dest, const char *_MLIBC_RESTRICT src,
219 	      size_t n)
220 {
221 	char *orig_dest = dest;
222 	size_t len = strlen(dest);
223 
224 	dest += len;
225 	while ((n-- > 0) && (*src != '\0')) {
226 		*dest++ = *src++;
227 	}
228 	*dest = '\0';
229 
230 	return orig_dest;
231 }
232 
233 /**
234  *
235  * @brief Compare two memory areas
236  *
237  * @return negative # if <m1> < <m2>, 0 if <m1> == <m2>, else positive #
238  */
memcmp(const void * m1,const void * m2,size_t n)239 int memcmp(const void *m1, const void *m2, size_t n)
240 {
241 	const char *c1 = m1;
242 	const char *c2 = m2;
243 
244 	if (!n) {
245 		return 0;
246 	}
247 
248 	while ((--n > 0) && (*c1 == *c2)) {
249 		c1++;
250 		c2++;
251 	}
252 
253 	return *c1 - *c2;
254 }
255 
256 /**
257  *
258  * @brief Copy bytes in memory with overlapping areas
259  *
260  * @return pointer to destination buffer <d>
261  */
262 
memmove(void * d,const void * s,size_t n)263 void *memmove(void *d, const void *s, size_t n)
264 {
265 	char *dest = d;
266 	const char *src  = s;
267 
268 	if ((size_t) (dest - src) < n) {
269 		/*
270 		 * The <src> buffer overlaps with the start of the <dest> buffer.
271 		 * Copy backwards to prevent the premature corruption of <src>.
272 		 */
273 
274 		while (n > 0) {
275 			n--;
276 			dest[n] = src[n];
277 		}
278 	} else {
279 		/* It is safe to perform a forward-copy */
280 		while (n > 0) {
281 			*dest = *src;
282 			dest++;
283 			src++;
284 			n--;
285 		}
286 	}
287 
288 	return d;
289 }
290 
291 /**
292  *
293  * @brief Copy bytes in memory
294  *
295  * @return pointer to start of destination buffer
296  */
297 
memcpy(void * _MLIBC_RESTRICT d,const void * _MLIBC_RESTRICT s,size_t n)298 void *memcpy(void *_MLIBC_RESTRICT d, const void *_MLIBC_RESTRICT s, size_t n)
299 {
300 	/* attempt word-sized copying only if buffers have identical alignment */
301 
302 	unsigned char *d_byte = (unsigned char *)d;
303 	const unsigned char *s_byte = (const unsigned char *)s;
304 
305 #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
306 	const uintptr_t mask = sizeof(mem_word_t) - 1;
307 
308 	if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
309 
310 		/* do byte-sized copying until word-aligned or finished */
311 
312 		while (((uintptr_t)d_byte) & mask) {
313 			if (n == 0) {
314 				return d;
315 			}
316 			*(d_byte++) = *(s_byte++);
317 			n--;
318 		}
319 
320 		/* do word-sized copying as long as possible */
321 
322 		mem_word_t *d_word = (mem_word_t *)d_byte;
323 		const mem_word_t *s_word = (const mem_word_t *)s_byte;
324 
325 		while (n >= sizeof(mem_word_t)) {
326 			*(d_word++) = *(s_word++);
327 			n -= sizeof(mem_word_t);
328 		}
329 
330 		d_byte = (unsigned char *)d_word;
331 		s_byte = (unsigned char *)s_word;
332 	}
333 #endif
334 
335 	/* do byte-sized copying until finished */
336 
337 	while (n > 0) {
338 		*(d_byte++) = *(s_byte++);
339 		n--;
340 	}
341 
342 	return d;
343 }
344 
345 /**
346  *
347  * @brief Set bytes in memory
348  *
349  * @return pointer to start of buffer
350  */
351 
memset(void * buf,int c,size_t n)352 void *memset(void *buf, int c, size_t n)
353 {
354 	/* do byte-sized initialization until word-aligned or finished */
355 
356 	unsigned char *d_byte = (unsigned char *)buf;
357 	unsigned char c_byte = (unsigned char)c;
358 
359 #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
360 	while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
361 		if (n == 0) {
362 			return buf;
363 		}
364 		*(d_byte++) = c_byte;
365 		n--;
366 	}
367 
368 	/* do word-sized initialization as long as possible */
369 
370 	mem_word_t *d_word = (mem_word_t *)d_byte;
371 	mem_word_t c_word = (mem_word_t)c_byte;
372 
373 	c_word |= c_word << 8;
374 	c_word |= c_word << 16;
375 #if Z_MEM_WORD_T_WIDTH > 32
376 	c_word |= c_word << 32;
377 #endif
378 
379 	while (n >= sizeof(mem_word_t)) {
380 		*(d_word++) = c_word;
381 		n -= sizeof(mem_word_t);
382 	}
383 
384 	/* do byte-sized initialization until finished */
385 
386 	d_byte = (unsigned char *)d_word;
387 #endif
388 
389 	while (n > 0) {
390 		*(d_byte++) = c_byte;
391 		n--;
392 	}
393 
394 	return buf;
395 }
396 
397 /**
398  *
399  * @brief Scan byte in memory
400  *
401  * @return pointer to start of found byte
402  */
403 
memchr(const void * s,int c,size_t n)404 void *memchr(const void *s, int c, size_t n)
405 {
406 	if (n != 0) {
407 		const unsigned char *p = s;
408 
409 		do {
410 			if (*p++ == (unsigned char)c) {
411 				return ((void *)(p - 1));
412 			}
413 
414 		} while (--n != 0);
415 	}
416 
417 	return NULL;
418 }
419