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 * ZRESTRICT d,const char * ZRESTRICT s)20 char *strcpy(char *ZRESTRICT d, const char *ZRESTRICT 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 * ZRESTRICT d,const char * ZRESTRICT s,size_t n)42 char *strncpy(char *ZRESTRICT d, const char *ZRESTRICT 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++ != '\0');
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 Compare two strings
122  *
123  * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
124  */
125 
strcmp(const char * s1,const char * s2)126 int strcmp(const char *s1, const char *s2)
127 {
128 	while ((*s1 == *s2) && (*s1 != '\0')) {
129 		s1++;
130 		s2++;
131 	}
132 
133 	return *s1 - *s2;
134 }
135 
136 /**
137  *
138  * @brief Compare part of two strings
139  *
140  * @return negative # if <s1> < <s2>, 0 if <s1> == <s2>, else positive #
141  */
142 
strncmp(const char * s1,const char * s2,size_t n)143 int strncmp(const char *s1, const char *s2, size_t n)
144 {
145 	while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
146 		s1++;
147 		s2++;
148 		n--;
149 	}
150 
151 	return (n == 0) ? 0 : (*s1 - *s2);
152 }
153 
154 /**
155  * @brief Separate `str` by any char in `sep` and return NULL terminated
156  * sections. Consecutive `sep` chars in `str` are treated as a single
157  * separator.
158  *
159  * @return pointer to NULL terminated string or NULL on errors.
160  */
strtok_r(char * str,const char * sep,char ** state)161 char *strtok_r(char *str, const char *sep, char **state)
162 {
163 	char *start, *end;
164 
165 	start = str ? str : *state;
166 
167 	/* skip leading delimiters */
168 	while (*start && strchr(sep, *start)) {
169 		start++;
170 	}
171 
172 	if (*start == '\0') {
173 		*state = start;
174 		return NULL;
175 	}
176 
177 	/* look for token chars */
178 	end = start;
179 	while (*end && !strchr(sep, *end)) {
180 		end++;
181 	}
182 
183 	if (*end != '\0') {
184 		*end = '\0';
185 		*state = end + 1;
186 	} else {
187 		*state = end;
188 	}
189 
190 	return start;
191 }
192 
strcat(char * ZRESTRICT dest,const char * ZRESTRICT src)193 char *strcat(char *ZRESTRICT dest, const char *ZRESTRICT src)
194 {
195 	strcpy(dest + strlen(dest), src);
196 	return dest;
197 }
198 
strncat(char * ZRESTRICT dest,const char * ZRESTRICT src,size_t n)199 char *strncat(char *ZRESTRICT dest, const char *ZRESTRICT src,
200 	      size_t n)
201 {
202 	char *orig_dest = dest;
203 	size_t len = strlen(dest);
204 
205 	dest += len;
206 	while ((n-- > 0) && (*src != '\0')) {
207 		*dest++ = *src++;
208 	}
209 	*dest = '\0';
210 
211 	return orig_dest;
212 }
213 
214 /**
215  *
216  * @brief Compare two memory areas
217  *
218  * @return negative # if <m1> < <m2>, 0 if <m1> == <m2>, else positive #
219  */
memcmp(const void * m1,const void * m2,size_t n)220 int memcmp(const void *m1, const void *m2, size_t n)
221 {
222 	const char *c1 = m1;
223 	const char *c2 = m2;
224 
225 	if (!n) {
226 		return 0;
227 	}
228 
229 	while ((--n > 0) && (*c1 == *c2)) {
230 		c1++;
231 		c2++;
232 	}
233 
234 	return *c1 - *c2;
235 }
236 
237 /**
238  *
239  * @brief Copy bytes in memory with overlapping areas
240  *
241  * @return pointer to destination buffer <d>
242  */
243 
memmove(void * d,const void * s,size_t n)244 void *memmove(void *d, const void *s, size_t n)
245 {
246 	char *dest = d;
247 	const char *src  = s;
248 
249 	if ((size_t) (dest - src) < n) {
250 		/*
251 		 * The <src> buffer overlaps with the start of the <dest> buffer.
252 		 * Copy backwards to prevent the premature corruption of <src>.
253 		 */
254 
255 		while (n > 0) {
256 			n--;
257 			dest[n] = src[n];
258 		}
259 	} else {
260 		/* It is safe to perform a forward-copy */
261 		while (n > 0) {
262 			*dest = *src;
263 			dest++;
264 			src++;
265 			n--;
266 		}
267 	}
268 
269 	return d;
270 }
271 
272 /**
273  *
274  * @brief Copy bytes in memory
275  *
276  * @return pointer to start of destination buffer
277  */
278 
memcpy(void * ZRESTRICT d,const void * ZRESTRICT s,size_t n)279 void *memcpy(void *ZRESTRICT d, const void *ZRESTRICT s, size_t n)
280 {
281 	/* attempt word-sized copying only if buffers have identical alignment */
282 
283 	unsigned char *d_byte = (unsigned char *)d;
284 	const unsigned char *s_byte = (const unsigned char *)s;
285 
286 #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
287 	const uintptr_t mask = sizeof(mem_word_t) - 1;
288 
289 	if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
290 
291 		/* do byte-sized copying until word-aligned or finished */
292 
293 		while (((uintptr_t)d_byte) & mask) {
294 			if (n == 0) {
295 				return d;
296 			}
297 			*(d_byte++) = *(s_byte++);
298 			n--;
299 		}
300 
301 		/* do word-sized copying as long as possible */
302 
303 		mem_word_t *d_word = (mem_word_t *)d_byte;
304 		const mem_word_t *s_word = (const mem_word_t *)s_byte;
305 
306 		while (n >= sizeof(mem_word_t)) {
307 			*(d_word++) = *(s_word++);
308 			n -= sizeof(mem_word_t);
309 		}
310 
311 		d_byte = (unsigned char *)d_word;
312 		s_byte = (unsigned char *)s_word;
313 	}
314 #endif
315 
316 	/* do byte-sized copying until finished */
317 
318 	while (n > 0) {
319 		*(d_byte++) = *(s_byte++);
320 		n--;
321 	}
322 
323 	return d;
324 }
325 
326 /**
327  *
328  * @brief Set bytes in memory
329  *
330  * @return pointer to start of buffer
331  */
332 
memset(void * buf,int c,size_t n)333 void *memset(void *buf, int c, size_t n)
334 {
335 	/* do byte-sized initialization until word-aligned or finished */
336 
337 	unsigned char *d_byte = (unsigned char *)buf;
338 	unsigned char c_byte = (unsigned char)c;
339 
340 #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
341 	while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
342 		if (n == 0) {
343 			return buf;
344 		}
345 		*(d_byte++) = c_byte;
346 		n--;
347 	}
348 
349 	/* do word-sized initialization as long as possible */
350 
351 	mem_word_t *d_word = (mem_word_t *)d_byte;
352 	mem_word_t c_word = (mem_word_t)c_byte;
353 
354 	c_word |= c_word << 8;
355 	c_word |= c_word << 16;
356 #if Z_MEM_WORD_T_WIDTH > 32
357 	c_word |= c_word << 32;
358 #endif
359 
360 	while (n >= sizeof(mem_word_t)) {
361 		*(d_word++) = c_word;
362 		n -= sizeof(mem_word_t);
363 	}
364 
365 	/* do byte-sized initialization until finished */
366 
367 	d_byte = (unsigned char *)d_word;
368 #endif
369 
370 	while (n > 0) {
371 		*(d_byte++) = c_byte;
372 		n--;
373 	}
374 
375 	return buf;
376 }
377 
378 /**
379  *
380  * @brief Scan byte in memory
381  *
382  * @return pointer to start of found byte
383  */
384 
memchr(const void * s,int c,size_t n)385 void *memchr(const void *s, int c, size_t n)
386 {
387 	if (n != 0) {
388 		const unsigned char *p = s;
389 
390 		do {
391 			if (*p++ == (unsigned char)c) {
392 				return ((void *)(p - 1));
393 			}
394 
395 		} while (--n != 0);
396 	}
397 
398 	return NULL;
399 }
400