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