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