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