Branch data Line data Source code
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 : :
20 : : char *strcpy(char *ZRESTRICT d, const char *ZRESTRICT s)
21 : : {
22 : 0 : char *dest = d;
23 : :
24 [ # # ]: 0 : while (*s != '\0') {
25 : 0 : *d = *s;
26 : 0 : d++;
27 : 0 : s++;
28 : : }
29 : :
30 : 0 : *d = '\0';
31 : :
32 : 0 : return dest;
33 : : }
34 : :
35 : : /**
36 : : *
37 : : * @brief Copy part of a string
38 : : *
39 : : * @return pointer to destination buffer <d>
40 : : */
41 : :
42 : : char *strncpy(char *ZRESTRICT d, const char *ZRESTRICT s, size_t n)
43 : : {
44 : 3 : char *dest = d;
45 : :
46 [ + - + + ]: 21 : while ((n > 0) && *s != '\0') {
47 : 18 : *d = *s;
48 : 18 : s++;
49 : 18 : d++;
50 : 18 : n--;
51 : : }
52 : :
53 [ + + ]: 78 : while (n > 0) {
54 : 75 : *d = '\0';
55 : 75 : d++;
56 : 75 : n--;
57 : : }
58 : :
59 : 3 : 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 : :
69 : : char *strchr(const char *s, int c)
70 : : {
71 : 0 : char tmp = (char) c;
72 : :
73 [ # # # # ]: 0 : while ((*s != tmp) && (*s != '\0')) {
74 : 0 : s++;
75 : : }
76 : :
77 [ # # ]: 0 : 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 : :
87 : : char *strrchr(const char *s, int c)
88 : : {
89 : 0 : char *match = NULL;
90 : :
91 : : do {
92 [ # # ]: 0 : if (*s == (char)c) {
93 : 0 : match = (char *)s;
94 : : }
95 [ # # ]: 0 : } while (*s++);
96 : :
97 : 0 : return match;
98 : : }
99 : :
100 : : /**
101 : : *
102 : : * @brief Get string length
103 : : *
104 : : * @return number of bytes in string <s>
105 : : */
106 : :
107 : : size_t strlen(const char *s)
108 : : {
109 : 8 : size_t n = 0;
110 : :
111 [ + + ]: 64 : while (*s != '\0') {
112 : 56 : s++;
113 : 56 : n++;
114 : : }
115 : :
116 : 8 : 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 : :
126 : : size_t strnlen(const char *s, size_t maxlen)
127 : : {
128 : 0 : size_t n = 0;
129 : :
130 [ # # # # ]: 0 : while (*s != '\0' && n < maxlen) {
131 : 0 : s++;
132 : 0 : n++;
133 : : }
134 : :
135 : 0 : 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 : :
145 : : int strcmp(const char *s1, const char *s2)
146 : : {
147 [ + - + + ]: 12 : while ((*s1 == *s2) && (*s1 != '\0')) {
148 : 10 : s1++;
149 : 10 : s2++;
150 : : }
151 : :
152 : 2 : 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 : :
162 : : int strncmp(const char *s1, const char *s2, size_t n)
163 : : {
164 [ # # # # : 0 : while ((n > 0) && (*s1 == *s2) && (*s1 != '\0')) {
# # ]
165 : 0 : s1++;
166 : 0 : s2++;
167 : 0 : n--;
168 : : }
169 : :
170 [ # # ]: 0 : 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 : : */
180 : : char *strtok_r(char *str, const char *sep, char **state)
181 : : {
182 : : char *start, *end;
183 : :
184 [ # # ]: 0 : start = str ? str : *state;
185 : :
186 : : /* skip leading delimiters */
187 [ # # # # ]: 0 : while (*start && strchr(sep, *start)) {
188 : 0 : start++;
189 : : }
190 : :
191 [ # # ]: 0 : if (*start == '\0') {
192 : 0 : *state = start;
193 : 0 : return NULL;
194 : : }
195 : :
196 : : /* look for token chars */
197 : 0 : end = start;
198 [ # # # # ]: 0 : while (*end && !strchr(sep, *end)) {
199 : 0 : end++;
200 : : }
201 : :
202 [ # # ]: 0 : if (*end != '\0') {
203 : 0 : *end = '\0';
204 : 0 : *state = end + 1;
205 : : } else {
206 : 0 : *state = end;
207 : : }
208 : :
209 : 0 : return start;
210 : : }
211 : :
212 : : char *strcat(char *ZRESTRICT dest, const char *ZRESTRICT src)
213 : : {
214 : 0 : strcpy(dest + strlen(dest), src);
215 : 0 : return dest;
216 : : }
217 : :
218 : : char *strncat(char *ZRESTRICT dest, const char *ZRESTRICT src,
219 : : size_t n)
220 : : {
221 : 0 : char *orig_dest = dest;
222 : 0 : size_t len = strlen(dest);
223 : :
224 : 0 : dest += len;
225 [ # # # # ]: 0 : while ((n-- > 0) && (*src != '\0')) {
226 : 0 : *dest++ = *src++;
227 : : }
228 : 0 : *dest = '\0';
229 : :
230 : 0 : 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 : : */
239 : : int memcmp(const void *m1, const void *m2, size_t n)
240 : : {
241 : 0 : const char *c1 = m1;
242 : 0 : const char *c2 = m2;
243 : :
244 [ # # ]: 0 : if (!n) {
245 : 0 : return 0;
246 : : }
247 : :
248 [ # # # # ]: 0 : while ((--n > 0) && (*c1 == *c2)) {
249 : 0 : c1++;
250 : 0 : c2++;
251 : : }
252 : :
253 : 0 : 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 : :
263 : : void *memmove(void *d, const void *s, size_t n)
264 : : {
265 : 0 : char *dest = d;
266 : 0 : const char *src = s;
267 : :
268 [ # # ]: 0 : 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 [ # # ]: 0 : while (n > 0) {
275 : 0 : n--;
276 : 0 : dest[n] = src[n];
277 : : }
278 : : } else {
279 : : /* It is safe to perform a forward-copy */
280 [ # # ]: 0 : while (n > 0) {
281 : 0 : *dest = *src;
282 : 0 : dest++;
283 : 0 : src++;
284 : 0 : n--;
285 : : }
286 : : }
287 : :
288 : 0 : return d;
289 : : }
290 : :
291 : : /**
292 : : *
293 : : * @brief Copy bytes in memory
294 : : *
295 : : * @return pointer to start of destination buffer
296 : : */
297 : :
298 : : void *memcpy(void *ZRESTRICT d, const void *ZRESTRICT s, size_t n)
299 : : {
300 : : /* attempt word-sized copying only if buffers have identical alignment */
301 : :
302 : 2 : unsigned char *d_byte = (unsigned char *)d;
303 : 2 : const unsigned char *s_byte = (const unsigned char *)s;
304 : :
305 : : #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
306 : 2 : const uintptr_t mask = sizeof(mem_word_t) - 1;
307 : :
308 [ + - ]: 2 : if ((((uintptr_t)d ^ (uintptr_t)s_byte) & mask) == 0) {
309 : :
310 : : /* do byte-sized copying until word-aligned or finished */
311 : :
312 [ - + ]: 2 : while (((uintptr_t)d_byte) & mask) {
313 [ # # ]: 0 : if (n == 0) {
314 : 0 : return d;
315 : : }
316 : 0 : *(d_byte++) = *(s_byte++);
317 : 0 : n--;
318 : : }
319 : :
320 : : /* do word-sized copying as long as possible */
321 : :
322 : 2 : mem_word_t *d_word = (mem_word_t *)d_byte;
323 : 2 : const mem_word_t *s_word = (const mem_word_t *)s_byte;
324 : :
325 [ + + ]: 17648 : while (n >= sizeof(mem_word_t)) {
326 : 17646 : *(d_word++) = *(s_word++);
327 : 17646 : n -= sizeof(mem_word_t);
328 : : }
329 : :
330 : 2 : d_byte = (unsigned char *)d_word;
331 : 2 : s_byte = (unsigned char *)s_word;
332 : : }
333 : : #endif
334 : :
335 : : /* do byte-sized copying until finished */
336 : :
337 [ - + ]: 2 : while (n > 0) {
338 : 0 : *(d_byte++) = *(s_byte++);
339 : 0 : n--;
340 : : }
341 : :
342 : 2 : return d;
343 : : }
344 : :
345 : : /**
346 : : *
347 : : * @brief Set bytes in memory
348 : : *
349 : : * @return pointer to start of buffer
350 : : */
351 : :
352 : : void *memset(void *buf, int c, size_t n)
353 : : {
354 : : /* do byte-sized initialization until word-aligned or finished */
355 : :
356 : 5 : unsigned char *d_byte = (unsigned char *)buf;
357 : 5 : unsigned char c_byte = (unsigned char)c;
358 : :
359 : : #if !defined(CONFIG_MINIMAL_LIBC_OPTIMIZE_STRING_FOR_SIZE)
360 [ - + ]: 5 : while (((uintptr_t)d_byte) & (sizeof(mem_word_t) - 1)) {
361 [ # # ]: 0 : if (n == 0) {
362 : 0 : return buf;
363 : : }
364 : 0 : *(d_byte++) = c_byte;
365 : 0 : n--;
366 : : }
367 : :
368 : : /* do word-sized initialization as long as possible */
369 : :
370 : 5 : mem_word_t *d_word = (mem_word_t *)d_byte;
371 : 5 : mem_word_t c_word = (mem_word_t)c_byte;
372 : :
373 : 5 : c_word |= c_word << 8;
374 : 5 : c_word |= c_word << 16;
375 : : #if Z_MEM_WORD_T_WIDTH > 32
376 : : c_word |= c_word << 32;
377 : : #endif
378 : :
379 [ + + ]: 10381 : while (n >= sizeof(mem_word_t)) {
380 : 10376 : *(d_word++) = c_word;
381 : 10376 : n -= sizeof(mem_word_t);
382 : : }
383 : :
384 : : /* do byte-sized initialization until finished */
385 : :
386 : 5 : d_byte = (unsigned char *)d_word;
387 : : #endif
388 : :
389 [ - + ]: 5 : while (n > 0) {
390 : 0 : *(d_byte++) = c_byte;
391 : 0 : n--;
392 : : }
393 : :
394 : 5 : return buf;
395 : : }
396 : :
397 : : /**
398 : : *
399 : : * @brief Scan byte in memory
400 : : *
401 : : * @return pointer to start of found byte
402 : : */
403 : :
404 : : void *memchr(const void *s, int c, size_t n)
405 : : {
406 [ # # ]: 0 : if (n != 0) {
407 : 0 : const unsigned char *p = s;
408 : :
409 : : do {
410 [ # # ]: 0 : if (*p++ == (unsigned char)c) {
411 : 0 : return ((void *)(p - 1));
412 : : }
413 : :
414 [ # # ]: 0 : } while (--n != 0);
415 : : }
416 : :
417 : 0 : return NULL;
418 : : }
|