blob: feae9519f2f62e4b959a4a9d28fdb279f370808d [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * linux/lib/string.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
7/*
8 * stupid library routines.. The optimized versions should generally be found
9 * as inline code in <asm-xx/string.h>
10 *
11 * These are buggy as well..
12 *
13 * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
14 * - Added strsep() which will replace strtok() soon (because strsep() is
15 * reentrant and should be faster). Use only strsep() in new code, please.
16 */
17
Simon Glass43e571d2018-11-06 15:21:38 -070018#include <config.h>
Marek BehĂșncde69782021-05-20 13:23:55 +020019#include <linux/compiler.h>
wdenkc6097192002-11-03 00:24:07 +000020#include <linux/types.h>
21#include <linux/string.h>
22#include <linux/ctype.h>
23#include <malloc.h>
24
wdenkc6097192002-11-03 00:24:07 +000025/**
Simon Glass459af692012-12-05 14:46:35 +000026 * strncasecmp - Case insensitive, length-limited string comparison
wdenkc6097192002-11-03 00:24:07 +000027 * @s1: One string
28 * @s2: The other string
29 * @len: the maximum number of characters to compare
30 */
Simon Glass459af692012-12-05 14:46:35 +000031int strncasecmp(const char *s1, const char *s2, size_t len)
wdenkc6097192002-11-03 00:24:07 +000032{
33 /* Yes, Virginia, it had better be unsigned */
34 unsigned char c1, c2;
35
36 c1 = 0; c2 = 0;
37 if (len) {
38 do {
39 c1 = *s1; c2 = *s2;
40 s1++; s2++;
41 if (!c1)
42 break;
43 if (!c2)
44 break;
45 if (c1 == c2)
46 continue;
47 c1 = tolower(c1);
48 c2 = tolower(c2);
49 if (c1 != c2)
50 break;
51 } while (--len);
52 }
53 return (int)c1 - (int)c2;
54}
Simon Glass459af692012-12-05 14:46:35 +000055
56/**
57 * strcasecmp - Case insensitive string comparison
58 * @s1: One string
59 * @s2: The other string
60 */
61int strcasecmp(const char *s1, const char *s2)
62{
63 return strncasecmp(s1, s2, -1U);
64}
wdenkc6097192002-11-03 00:24:07 +000065
66char * ___strtok;
67
68#ifndef __HAVE_ARCH_STRCPY
69/**
70 * strcpy - Copy a %NUL terminated string
71 * @dest: Where to copy the string to
72 * @src: Where to copy the string from
73 */
74char * strcpy(char * dest,const char *src)
75{
76 char *tmp = dest;
77
78 while ((*dest++ = *src++) != '\0')
79 /* nothing */;
80 return tmp;
81}
82#endif
83
84#ifndef __HAVE_ARCH_STRNCPY
85/**
86 * strncpy - Copy a length-limited, %NUL-terminated string
87 * @dest: Where to copy the string to
88 * @src: Where to copy the string from
89 * @count: The maximum number of bytes to copy
90 *
91 * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
92 * However, the result is not %NUL-terminated if the source exceeds
93 * @count bytes.
94 */
95char * strncpy(char * dest,const char *src,size_t count)
96{
97 char *tmp = dest;
98
99 while (count-- && (*dest++ = *src++) != '\0')
100 /* nothing */;
101
102 return tmp;
103}
104#endif
105
Masahiro Yamada0588ce12014-11-20 21:20:32 +0900106#ifndef __HAVE_ARCH_STRLCPY
107/**
108 * strlcpy - Copy a C-string into a sized buffer
109 * @dest: Where to copy the string to
110 * @src: Where to copy the string from
111 * @size: size of destination buffer
112 *
113 * Compatible with *BSD: the result is always a valid
114 * NUL-terminated string that fits in the buffer (unless,
115 * of course, the buffer size is zero). It does not pad
116 * out the result like strncpy() does.
Sean Anderson2f512572021-03-11 00:15:41 -0500117 *
Matthias Schiffer02482ee2023-07-14 13:24:50 +0200118 * Return: strlen(src)
Masahiro Yamada0588ce12014-11-20 21:20:32 +0900119 */
120size_t strlcpy(char *dest, const char *src, size_t size)
121{
Matthias Schiffer02482ee2023-07-14 13:24:50 +0200122 size_t ret = strlen(src);
Sean Anderson2f512572021-03-11 00:15:41 -0500123
Matthias Schiffer02482ee2023-07-14 13:24:50 +0200124 if (size) {
125 size_t len = (ret >= size) ? size - 1 : ret;
Masahiro Yamada0588ce12014-11-20 21:20:32 +0900126 memcpy(dest, src, len);
127 dest[len] = '\0';
128 }
Matthias Schiffer02482ee2023-07-14 13:24:50 +0200129 return ret;
Masahiro Yamada0588ce12014-11-20 21:20:32 +0900130}
131#endif
132
wdenkc6097192002-11-03 00:24:07 +0000133#ifndef __HAVE_ARCH_STRCAT
134/**
135 * strcat - Append one %NUL-terminated string to another
136 * @dest: The string to be appended to
137 * @src: The string to append to it
138 */
139char * strcat(char * dest, const char * src)
140{
141 char *tmp = dest;
142
143 while (*dest)
144 dest++;
145 while ((*dest++ = *src++) != '\0')
146 ;
147
148 return tmp;
149}
150#endif
151
152#ifndef __HAVE_ARCH_STRNCAT
153/**
154 * strncat - Append a length-limited, %NUL-terminated string to another
155 * @dest: The string to be appended to
156 * @src: The string to append to it
157 * @count: The maximum numbers of bytes to copy
158 *
159 * Note that in contrast to strncpy, strncat ensures the result is
160 * terminated.
161 */
162char * strncat(char *dest, const char *src, size_t count)
163{
164 char *tmp = dest;
165
166 if (count) {
167 while (*dest)
168 dest++;
169 while ((*dest++ = *src++)) {
170 if (--count == 0) {
171 *dest = '\0';
172 break;
173 }
174 }
175 }
176
177 return tmp;
178}
179#endif
180
Sean Anderson9297a7f2021-03-11 00:15:42 -0500181#ifndef __HAVE_ARCH_STRLCAT
182/**
183 * strlcat - Append a length-limited, %NUL-terminated string to another
184 * @dest: The string to be appended to
185 * @src: The string to append to it
186 * @size: The size of @dest
187 *
188 * Compatible with *BSD: the result is always a valid NUL-terminated string that
189 * fits in the buffer (unless, of course, the buffer size is zero). It does not
190 * write past @size like strncat() does.
Matthias Schiffer02482ee2023-07-14 13:24:50 +0200191 *
192 * Return: min(strlen(dest), size) + strlen(src)
Sean Anderson9297a7f2021-03-11 00:15:42 -0500193 */
194size_t strlcat(char *dest, const char *src, size_t size)
195{
196 size_t len = strnlen(dest, size);
197
198 return len + strlcpy(dest + len, src, size - len);
199}
200#endif
201
wdenkc6097192002-11-03 00:24:07 +0000202#ifndef __HAVE_ARCH_STRCMP
203/**
204 * strcmp - Compare two strings
205 * @cs: One string
206 * @ct: Another string
207 */
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200208int strcmp(const char *cs, const char *ct)
wdenkc6097192002-11-03 00:24:07 +0000209{
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200210 int ret;
wdenkc6097192002-11-03 00:24:07 +0000211
212 while (1) {
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200213 unsigned char a = *cs++;
214 unsigned char b = *ct++;
215
216 ret = a - b;
217 if (ret || !b)
wdenkc6097192002-11-03 00:24:07 +0000218 break;
219 }
220
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200221 return ret;
wdenkc6097192002-11-03 00:24:07 +0000222}
223#endif
224
225#ifndef __HAVE_ARCH_STRNCMP
226/**
227 * strncmp - Compare two length-limited strings
228 * @cs: One string
229 * @ct: Another string
230 * @count: The maximum number of bytes to compare
231 */
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200232int strncmp(const char *cs, const char *ct, size_t count)
wdenkc6097192002-11-03 00:24:07 +0000233{
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200234 int ret = 0;
wdenkc6097192002-11-03 00:24:07 +0000235
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200236 while (count--) {
237 unsigned char a = *cs++;
238 unsigned char b = *ct++;
239
240 ret = a - b;
241 if (ret || !b)
wdenkc6097192002-11-03 00:24:07 +0000242 break;
wdenkc6097192002-11-03 00:24:07 +0000243 }
244
Rasmus Villemoesb540ec92022-10-05 11:09:25 +0200245 return ret;
wdenkc6097192002-11-03 00:24:07 +0000246}
247#endif
248
249#ifndef __HAVE_ARCH_STRCHR
250/**
251 * strchr - Find the first occurrence of a character in a string
252 * @s: The string to be searched
253 * @c: The character to search for
254 */
255char * strchr(const char * s, int c)
256{
257 for(; *s != (char) c; ++s)
258 if (*s == '\0')
259 return NULL;
260 return (char *) s;
261}
262#endif
263
Simon Glass4355d422017-05-18 20:09:28 -0600264const char *strchrnul(const char *s, int c)
265{
266 for (; *s != (char)c; ++s)
267 if (*s == '\0')
268 break;
269 return s;
270}
271
wdenkc6097192002-11-03 00:24:07 +0000272#ifndef __HAVE_ARCH_STRRCHR
273/**
274 * strrchr - Find the last occurrence of a character in a string
275 * @s: The string to be searched
276 * @c: The character to search for
277 */
278char * strrchr(const char * s, int c)
279{
280 const char *p = s + strlen(s);
281 do {
wdenk57b2d802003-06-27 21:31:46 +0000282 if (*p == (char)c)
283 return (char *)p;
wdenkc6097192002-11-03 00:24:07 +0000284 } while (--p >= s);
285 return NULL;
286}
287#endif
288
289#ifndef __HAVE_ARCH_STRLEN
290/**
291 * strlen - Find the length of a string
292 * @s: The string to be sized
293 */
294size_t strlen(const char * s)
295{
296 const char *sc;
297
298 for (sc = s; *sc != '\0'; ++sc)
299 /* nothing */;
300 return sc - s;
301}
302#endif
303
304#ifndef __HAVE_ARCH_STRNLEN
305/**
306 * strnlen - Find the length of a length-limited string
307 * @s: The string to be sized
308 * @count: The maximum number of bytes to search
309 */
310size_t strnlen(const char * s, size_t count)
311{
312 const char *sc;
313
314 for (sc = s; count-- && *sc != '\0'; ++sc)
315 /* nothing */;
316 return sc - s;
317}
318#endif
319
Simon Glass0d0e3c92017-05-18 20:09:29 -0600320#ifndef __HAVE_ARCH_STRCSPN
321/**
322 * strcspn - Calculate the length of the initial substring of @s which does
323 * not contain letters in @reject
324 * @s: The string to be searched
325 * @reject: The string to avoid
326 */
327size_t strcspn(const char *s, const char *reject)
328{
329 const char *p;
330 const char *r;
331 size_t count = 0;
332
333 for (p = s; *p != '\0'; ++p) {
334 for (r = reject; *r != '\0'; ++r) {
335 if (*p == *r)
336 return count;
337 }
338 ++count;
339 }
340 return count;
341}
342#endif
343
wdenkc6097192002-11-03 00:24:07 +0000344#ifndef __HAVE_ARCH_STRDUP
345char * strdup(const char *s)
346{
347 char *new;
348
349 if ((s == NULL) ||
350 ((new = malloc (strlen(s) + 1)) == NULL) ) {
351 return NULL;
352 }
353
354 strcpy (new, s);
355 return new;
356}
wdenkc6097192002-11-03 00:24:07 +0000357
Thierry Redingf0561822019-04-15 11:32:14 +0200358char * strndup(const char *s, size_t n)
359{
360 size_t len;
361 char *new;
362
363 if (s == NULL)
364 return NULL;
365
366 len = strlen(s);
367
368 if (n < len)
369 len = n;
370
371 new = malloc(len + 1);
372 if (new == NULL)
373 return NULL;
374
375 strncpy(new, s, len);
376 new[len] = '\0';
377
378 return new;
379}
Simon Glass9e8f6d62020-02-03 07:36:00 -0700380#endif
Thierry Redingf0561822019-04-15 11:32:14 +0200381
wdenkc6097192002-11-03 00:24:07 +0000382#ifndef __HAVE_ARCH_STRSPN
383/**
384 * strspn - Calculate the length of the initial substring of @s which only
Wolfgang Denka1be4762008-05-20 16:00:29 +0200385 * contain letters in @accept
wdenkc6097192002-11-03 00:24:07 +0000386 * @s: The string to be searched
387 * @accept: The string to search for
388 */
389size_t strspn(const char *s, const char *accept)
390{
391 const char *p;
392 const char *a;
393 size_t count = 0;
394
395 for (p = s; *p != '\0'; ++p) {
396 for (a = accept; *a != '\0'; ++a) {
397 if (*p == *a)
398 break;
399 }
400 if (*a == '\0')
401 return count;
402 ++count;
403 }
404
405 return count;
406}
407#endif
408
409#ifndef __HAVE_ARCH_STRPBRK
410/**
411 * strpbrk - Find the first occurrence of a set of characters
412 * @cs: The string to be searched
413 * @ct: The characters to search for
414 */
415char * strpbrk(const char * cs,const char * ct)
416{
417 const char *sc1,*sc2;
418
419 for( sc1 = cs; *sc1 != '\0'; ++sc1) {
420 for( sc2 = ct; *sc2 != '\0'; ++sc2) {
421 if (*sc1 == *sc2)
422 return (char *) sc1;
423 }
424 }
425 return NULL;
426}
427#endif
428
429#ifndef __HAVE_ARCH_STRTOK
430/**
431 * strtok - Split a string into tokens
432 * @s: The string to be searched
433 * @ct: The characters to search for
434 *
435 * WARNING: strtok is deprecated, use strsep instead.
436 */
437char * strtok(char * s,const char * ct)
438{
439 char *sbegin, *send;
440
441 sbegin = s ? s : ___strtok;
442 if (!sbegin) {
443 return NULL;
444 }
445 sbegin += strspn(sbegin,ct);
446 if (*sbegin == '\0') {
447 ___strtok = NULL;
448 return( NULL );
449 }
450 send = strpbrk( sbegin, ct);
451 if (send && *send != '\0')
452 *send++ = '\0';
453 ___strtok = send;
454 return (sbegin);
455}
456#endif
457
458#ifndef __HAVE_ARCH_STRSEP
459/**
460 * strsep - Split a string into tokens
461 * @s: The string to be searched
462 * @ct: The characters to search for
463 *
464 * strsep() updates @s to point after the token, ready for the next call.
465 *
466 * It returns empty tokens, too, behaving exactly like the libc function
467 * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
468 * Same semantics, slimmer shape. ;)
469 */
470char * strsep(char **s, const char *ct)
471{
472 char *sbegin = *s, *end;
473
474 if (sbegin == NULL)
475 return NULL;
476
477 end = strpbrk(sbegin, ct);
478 if (end)
479 *end++ = '\0';
480 *s = end;
481
482 return sbegin;
483}
484#endif
485
wdenkacd9b102004-03-14 00:59:59 +0000486#ifndef __HAVE_ARCH_STRSWAB
487/**
488 * strswab - swap adjacent even and odd bytes in %NUL-terminated string
489 * s: address of the string
490 *
491 * returns the address of the swapped string or NULL on error. If
492 * string length is odd, last byte is untouched.
493 */
494char *strswab(const char *s)
495{
Wolfgang Denkc7ca7cf2005-09-25 16:15:17 +0200496 char *p, *q;
wdenkacd9b102004-03-14 00:59:59 +0000497
498 if ((NULL == s) || ('\0' == *s)) {
499 return (NULL);
500 }
501
Wolfgang Denkdf70a422005-10-04 23:38:07 +0200502 for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) {
wdenkacd9b102004-03-14 00:59:59 +0000503 char tmp;
Wolfgang Denkc7ca7cf2005-09-25 16:15:17 +0200504
505 tmp = *p;
506 *p = *q;
507 *q = tmp;
wdenkacd9b102004-03-14 00:59:59 +0000508 }
509
510 return (char *) s;
511}
512#endif
513
wdenkc6097192002-11-03 00:24:07 +0000514#ifndef __HAVE_ARCH_MEMSET
515/**
516 * memset - Fill a region of memory with the given value
517 * @s: Pointer to the start of the area.
518 * @c: The byte to fill the area with
519 * @count: The size of the area.
520 *
521 * Do not use memset() to access IO space, use memset_io() instead.
522 */
Marek BehĂșncde69782021-05-20 13:23:55 +0200523__used void * memset(void * s,int c,size_t count)
wdenkc6097192002-11-03 00:24:07 +0000524{
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200525 unsigned long *sl = (unsigned long *) s;
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200526 char *s8;
Simon Glasse2f94ae2017-04-02 09:50:28 -0600527
528#if !CONFIG_IS_ENABLED(TINY_MEMSET)
529 unsigned long cl = 0;
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200530 int i;
wdenkc6097192002-11-03 00:24:07 +0000531
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200532 /* do it one word at a time (32 bits or 64 bits) while possible */
533 if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
534 for (i = 0; i < sizeof(*sl); i++) {
535 cl <<= 8;
536 cl |= c & 0xff;
537 }
538 while (count >= sizeof(*sl)) {
539 *sl++ = cl;
540 count -= sizeof(*sl);
541 }
542 }
Simon Glasse2f94ae2017-04-02 09:50:28 -0600543#endif /* fill 8 bits at a time */
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200544 s8 = (char *)sl;
wdenkc6097192002-11-03 00:24:07 +0000545 while (count--)
Alessandro Rubinife1a2fb2009-10-10 11:51:16 +0200546 *s8++ = c;
wdenkc6097192002-11-03 00:24:07 +0000547
548 return s;
549}
550#endif
551
wdenkc6097192002-11-03 00:24:07 +0000552#ifndef __HAVE_ARCH_MEMCPY
553/**
554 * memcpy - Copy one area of memory to another
555 * @dest: Where to copy to
556 * @src: Where to copy from
557 * @count: The size of the area.
558 *
559 * You should not use this function to access IO space, use memcpy_toio()
560 * or memcpy_fromio() instead.
561 */
Marek BehĂșncde69782021-05-20 13:23:55 +0200562__used void * memcpy(void *dest, const void *src, size_t count)
wdenkc6097192002-11-03 00:24:07 +0000563{
Alessandro Rubinif881b542009-10-10 11:51:05 +0200564 unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
565 char *d8, *s8;
wdenkc6097192002-11-03 00:24:07 +0000566
Matthias Weisser5bf63482011-05-22 23:03:55 +0000567 if (src == dest)
568 return dest;
569
Alessandro Rubinif881b542009-10-10 11:51:05 +0200570 /* while all data is aligned (common case), copy a word at a time */
571 if ( (((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) {
572 while (count >= sizeof(*dl)) {
573 *dl++ = *sl++;
574 count -= sizeof(*dl);
575 }
576 }
577 /* copy the reset one byte at a time */
578 d8 = (char *)dl;
579 s8 = (char *)sl;
wdenkc6097192002-11-03 00:24:07 +0000580 while (count--)
Alessandro Rubinif881b542009-10-10 11:51:05 +0200581 *d8++ = *s8++;
wdenkc6097192002-11-03 00:24:07 +0000582
583 return dest;
584}
585#endif
586
587#ifndef __HAVE_ARCH_MEMMOVE
588/**
589 * memmove - Copy one area of memory to another
590 * @dest: Where to copy to
591 * @src: Where to copy from
592 * @count: The size of the area.
593 *
594 * Unlike memcpy(), memmove() copes with overlapping areas.
595 */
Marek BehĂșncde69782021-05-20 13:23:55 +0200596__used void * memmove(void * dest,const void *src,size_t count)
wdenkc6097192002-11-03 00:24:07 +0000597{
598 char *tmp, *s;
599
Patrick Delaunay26b66a32020-12-11 14:59:23 +0100600 if (dest <= src || (src + count) <= dest) {
601 /*
602 * Use the fast memcpy implementation (ARCH optimized or lib/string.c) when it is possible:
603 * - when dest is before src (assuming that memcpy is doing forward-copying)
604 * - when destination don't overlap the source buffer (src + count <= dest)
605 *
606 * WARNING: the first optimisation cause an issue, when __HAVE_ARCH_MEMCPY is defined,
607 * __HAVE_ARCH_MEMMOVE is not defined and if the memcpy ARCH-specific
608 * implementation is not doing a forward-copying.
609 *
610 * No issue today because memcpy is doing a forward-copying in lib/string.c and for ARM32
611 * architecture; no other arches use __HAVE_ARCH_MEMCPY without __HAVE_ARCH_MEMMOVE.
612 */
Simon Glass03f827e2017-04-05 16:23:31 -0600613 memcpy(dest, src, count);
614 } else {
wdenkc6097192002-11-03 00:24:07 +0000615 tmp = (char *) dest + count;
616 s = (char *) src + count;
617 while (count--)
618 *--tmp = *--s;
619 }
620
621 return dest;
622}
623#endif
624
625#ifndef __HAVE_ARCH_MEMCMP
626/**
627 * memcmp - Compare two areas of memory
628 * @cs: One area of memory
629 * @ct: Another area of memory
630 * @count: The size of the area.
631 */
Marek BehĂșncde69782021-05-20 13:23:55 +0200632__used int memcmp(const void * cs,const void * ct,size_t count)
wdenkc6097192002-11-03 00:24:07 +0000633{
634 const unsigned char *su1, *su2;
635 int res = 0;
636
637 for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
638 if ((res = *su1 - *su2) != 0)
639 break;
640 return res;
641}
642#endif
643
644#ifndef __HAVE_ARCH_MEMSCAN
645/**
646 * memscan - Find a character in an area of memory.
647 * @addr: The memory area
648 * @c: The byte to search for
649 * @size: The size of the area.
650 *
651 * returns the address of the first occurrence of @c, or 1 byte past
652 * the area if @c is not found
653 */
654void * memscan(void * addr, int c, size_t size)
655{
656 unsigned char * p = (unsigned char *) addr;
657
658 while (size) {
659 if (*p == c)
660 return (void *) p;
661 p++;
662 size--;
663 }
wdenk57b2d802003-06-27 21:31:46 +0000664 return (void *) p;
wdenkc6097192002-11-03 00:24:07 +0000665}
666#endif
667
Simon Glass4b2a18b2021-09-25 07:03:06 -0600668char *memdup(const void *src, size_t len)
669{
670 char *p;
671
672 p = malloc(len);
673 if (!p)
674 return NULL;
675
676 memcpy(p, src, len);
677
678 return p;
679}
680
wdenkc6097192002-11-03 00:24:07 +0000681#ifndef __HAVE_ARCH_STRSTR
682/**
683 * strstr - Find the first substring in a %NUL terminated string
684 * @s1: The string to be searched
685 * @s2: The string to search for
686 */
687char * strstr(const char * s1,const char * s2)
688{
689 int l1, l2;
690
691 l2 = strlen(s2);
692 if (!l2)
693 return (char *) s1;
694 l1 = strlen(s1);
695 while (l1 >= l2) {
696 l1--;
697 if (!memcmp(s1,s2,l2))
698 return (char *) s1;
699 s1++;
700 }
701 return NULL;
702}
703#endif
704
705#ifndef __HAVE_ARCH_MEMCHR
706/**
707 * memchr - Find a character in an area of memory.
708 * @s: The memory area
709 * @c: The byte to search for
710 * @n: The size of the area.
711 *
712 * returns the address of the first occurrence of @c, or %NULL
713 * if @c is not found
714 */
715void *memchr(const void *s, int c, size_t n)
716{
717 const unsigned char *p = s;
718 while (n-- != 0) {
wdenk57b2d802003-06-27 21:31:46 +0000719 if ((unsigned char)c == *p++) {
wdenkc6097192002-11-03 00:24:07 +0000720 return (void *)(p-1);
721 }
722 }
723 return NULL;
724}
725
726#endif
Sergey Lapin3a38a552013-01-14 03:46:50 +0000727#ifndef __HAVE_ARCH_MEMCHR_INV
728static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
729{
730 while (bytes) {
731 if (*start != value)
732 return (void *)start;
733 start++;
734 bytes--;
735 }
736 return NULL;
737}
738/**
739 * memchr_inv - Find an unmatching character in an area of memory.
740 * @start: The memory area
741 * @c: Find a character other than c
742 * @bytes: The size of the area.
743 *
744 * returns the address of the first character other than @c, or %NULL
745 * if the whole buffer contains just @c.
746 */
747void *memchr_inv(const void *start, int c, size_t bytes)
748{
749 u8 value = c;
750 u64 value64;
751 unsigned int words, prefix;
752
753 if (bytes <= 16)
754 return check_bytes8(start, value, bytes);
755
756 value64 = value;
757 value64 |= value64 << 8;
758 value64 |= value64 << 16;
759 value64 |= value64 << 32;
760
761 prefix = (unsigned long)start % 8;
762 if (prefix) {
763 u8 *r;
764
765 prefix = 8 - prefix;
766 r = check_bytes8(start, value, prefix);
767 if (r)
768 return r;
769 start += prefix;
770 bytes -= prefix;
771 }
772
773 words = bytes / 8;
774
775 while (words) {
776 if (*(u64 *)start != value64)
777 return check_bytes8(start, value, 8);
778 start += 8;
779 words--;
780 }
781
782 return check_bytes8(start, value, bytes % 8);
783}
784#endif