]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
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 <[email protected]> | |
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 | * * Sat Feb 09 2002, Jason Thomas <[email protected]>, | |
18 | * Matthew Hawkins <[email protected]> | |
19 | * - Kissed strtok() goodbye | |
20 | */ | |
21 | ||
22 | #include <linux/types.h> | |
23 | #include <linux/string.h> | |
24 | #include <linux/ctype.h> | |
25 | #include <linux/module.h> | |
26 | ||
27 | #ifndef __HAVE_ARCH_STRNICMP | |
28 | /** | |
29 | * strnicmp - Case insensitive, length-limited string comparison | |
30 | * @s1: One string | |
31 | * @s2: The other string | |
32 | * @len: the maximum number of characters to compare | |
33 | */ | |
34 | int strnicmp(const char *s1, const char *s2, size_t len) | |
35 | { | |
36 | /* Yes, Virginia, it had better be unsigned */ | |
37 | unsigned char c1, c2; | |
38 | ||
a11d2b64 AGR |
39 | if (!len) |
40 | return 0; | |
41 | ||
42 | do { | |
43 | c1 = *s1++; | |
44 | c2 = *s2++; | |
45 | if (!c1 || !c2) | |
46 | break; | |
47 | if (c1 == c2) | |
48 | continue; | |
49 | c1 = tolower(c1); | |
50 | c2 = tolower(c2); | |
51 | if (c1 != c2) | |
52 | break; | |
53 | } while (--len); | |
1da177e4 LT |
54 | return (int)c1 - (int)c2; |
55 | } | |
1da177e4 LT |
56 | EXPORT_SYMBOL(strnicmp); |
57 | #endif | |
58 | ||
ded220bd DM |
59 | #ifndef __HAVE_ARCH_STRCASECMP |
60 | int strcasecmp(const char *s1, const char *s2) | |
61 | { | |
62 | int c1, c2; | |
63 | ||
64 | do { | |
65 | c1 = tolower(*s1++); | |
66 | c2 = tolower(*s2++); | |
67 | } while (c1 == c2 && c1 != 0); | |
68 | return c1 - c2; | |
69 | } | |
70 | EXPORT_SYMBOL(strcasecmp); | |
71 | #endif | |
72 | ||
73 | #ifndef __HAVE_ARCH_STRNCASECMP | |
74 | int strncasecmp(const char *s1, const char *s2, size_t n) | |
75 | { | |
76 | int c1, c2; | |
77 | ||
78 | do { | |
79 | c1 = tolower(*s1++); | |
80 | c2 = tolower(*s2++); | |
81 | } while ((--n > 0) && c1 == c2 && c1 != 0); | |
82 | return c1 - c2; | |
83 | } | |
84 | EXPORT_SYMBOL(strncasecmp); | |
85 | #endif | |
86 | ||
1da177e4 LT |
87 | #ifndef __HAVE_ARCH_STRCPY |
88 | /** | |
89 | * strcpy - Copy a %NUL terminated string | |
90 | * @dest: Where to copy the string to | |
91 | * @src: Where to copy the string from | |
92 | */ | |
0c28130b | 93 | #undef strcpy |
51a0f0f6 | 94 | char *strcpy(char *dest, const char *src) |
1da177e4 LT |
95 | { |
96 | char *tmp = dest; | |
97 | ||
98 | while ((*dest++ = *src++) != '\0') | |
99 | /* nothing */; | |
100 | return tmp; | |
101 | } | |
102 | EXPORT_SYMBOL(strcpy); | |
103 | #endif | |
104 | ||
105 | #ifndef __HAVE_ARCH_STRNCPY | |
106 | /** | |
107 | * strncpy - Copy a length-limited, %NUL-terminated string | |
108 | * @dest: Where to copy the string to | |
109 | * @src: Where to copy the string from | |
110 | * @count: The maximum number of bytes to copy | |
111 | * | |
112 | * The result is not %NUL-terminated if the source exceeds | |
113 | * @count bytes. | |
25279526 | 114 | * |
115 | * In the case where the length of @src is less than that of | |
116 | * count, the remainder of @dest will be padded with %NUL. | |
117 | * | |
1da177e4 | 118 | */ |
51a0f0f6 | 119 | char *strncpy(char *dest, const char *src, size_t count) |
1da177e4 LT |
120 | { |
121 | char *tmp = dest; | |
122 | ||
123 | while (count) { | |
51a0f0f6 JJ |
124 | if ((*tmp = *src) != 0) |
125 | src++; | |
1da177e4 LT |
126 | tmp++; |
127 | count--; | |
128 | } | |
129 | return dest; | |
130 | } | |
131 | EXPORT_SYMBOL(strncpy); | |
132 | #endif | |
133 | ||
134 | #ifndef __HAVE_ARCH_STRLCPY | |
135 | /** | |
136 | * strlcpy - Copy a %NUL terminated string into a sized buffer | |
137 | * @dest: Where to copy the string to | |
138 | * @src: Where to copy the string from | |
139 | * @size: size of destination buffer | |
140 | * | |
141 | * Compatible with *BSD: the result is always a valid | |
142 | * NUL-terminated string that fits in the buffer (unless, | |
143 | * of course, the buffer size is zero). It does not pad | |
144 | * out the result like strncpy() does. | |
145 | */ | |
146 | size_t strlcpy(char *dest, const char *src, size_t size) | |
147 | { | |
148 | size_t ret = strlen(src); | |
149 | ||
150 | if (size) { | |
51a0f0f6 | 151 | size_t len = (ret >= size) ? size - 1 : ret; |
1da177e4 LT |
152 | memcpy(dest, src, len); |
153 | dest[len] = '\0'; | |
154 | } | |
155 | return ret; | |
156 | } | |
157 | EXPORT_SYMBOL(strlcpy); | |
158 | #endif | |
159 | ||
160 | #ifndef __HAVE_ARCH_STRCAT | |
161 | /** | |
162 | * strcat - Append one %NUL-terminated string to another | |
163 | * @dest: The string to be appended to | |
164 | * @src: The string to append to it | |
165 | */ | |
0c28130b | 166 | #undef strcat |
51a0f0f6 | 167 | char *strcat(char *dest, const char *src) |
1da177e4 LT |
168 | { |
169 | char *tmp = dest; | |
170 | ||
171 | while (*dest) | |
172 | dest++; | |
173 | while ((*dest++ = *src++) != '\0') | |
174 | ; | |
1da177e4 LT |
175 | return tmp; |
176 | } | |
177 | EXPORT_SYMBOL(strcat); | |
178 | #endif | |
179 | ||
180 | #ifndef __HAVE_ARCH_STRNCAT | |
181 | /** | |
182 | * strncat - Append a length-limited, %NUL-terminated string to another | |
183 | * @dest: The string to be appended to | |
184 | * @src: The string to append to it | |
185 | * @count: The maximum numbers of bytes to copy | |
186 | * | |
72fd4a35 | 187 | * Note that in contrast to strncpy(), strncat() ensures the result is |
1da177e4 LT |
188 | * terminated. |
189 | */ | |
51a0f0f6 | 190 | char *strncat(char *dest, const char *src, size_t count) |
1da177e4 LT |
191 | { |
192 | char *tmp = dest; | |
193 | ||
194 | if (count) { | |
195 | while (*dest) | |
196 | dest++; | |
197 | while ((*dest++ = *src++) != 0) { | |
198 | if (--count == 0) { | |
199 | *dest = '\0'; | |
200 | break; | |
201 | } | |
202 | } | |
203 | } | |
1da177e4 LT |
204 | return tmp; |
205 | } | |
206 | EXPORT_SYMBOL(strncat); | |
207 | #endif | |
208 | ||
209 | #ifndef __HAVE_ARCH_STRLCAT | |
210 | /** | |
211 | * strlcat - Append a length-limited, %NUL-terminated string to another | |
212 | * @dest: The string to be appended to | |
213 | * @src: The string to append to it | |
214 | * @count: The size of the destination buffer. | |
215 | */ | |
216 | size_t strlcat(char *dest, const char *src, size_t count) | |
217 | { | |
218 | size_t dsize = strlen(dest); | |
219 | size_t len = strlen(src); | |
220 | size_t res = dsize + len; | |
221 | ||
222 | /* This would be a bug */ | |
223 | BUG_ON(dsize >= count); | |
224 | ||
225 | dest += dsize; | |
226 | count -= dsize; | |
227 | if (len >= count) | |
228 | len = count-1; | |
229 | memcpy(dest, src, len); | |
230 | dest[len] = 0; | |
231 | return res; | |
232 | } | |
233 | EXPORT_SYMBOL(strlcat); | |
234 | #endif | |
235 | ||
236 | #ifndef __HAVE_ARCH_STRCMP | |
237 | /** | |
238 | * strcmp - Compare two strings | |
239 | * @cs: One string | |
240 | * @ct: Another string | |
241 | */ | |
0c28130b | 242 | #undef strcmp |
51a0f0f6 | 243 | int strcmp(const char *cs, const char *ct) |
1da177e4 | 244 | { |
a414f01a | 245 | unsigned char c1, c2; |
1da177e4 LT |
246 | |
247 | while (1) { | |
a414f01a LT |
248 | c1 = *cs++; |
249 | c2 = *ct++; | |
250 | if (c1 != c2) | |
251 | return c1 < c2 ? -1 : 1; | |
252 | if (!c1) | |
1da177e4 LT |
253 | break; |
254 | } | |
a414f01a | 255 | return 0; |
1da177e4 LT |
256 | } |
257 | EXPORT_SYMBOL(strcmp); | |
258 | #endif | |
259 | ||
260 | #ifndef __HAVE_ARCH_STRNCMP | |
261 | /** | |
262 | * strncmp - Compare two length-limited strings | |
263 | * @cs: One string | |
264 | * @ct: Another string | |
265 | * @count: The maximum number of bytes to compare | |
266 | */ | |
51a0f0f6 | 267 | int strncmp(const char *cs, const char *ct, size_t count) |
1da177e4 | 268 | { |
a414f01a | 269 | unsigned char c1, c2; |
1da177e4 LT |
270 | |
271 | while (count) { | |
a414f01a LT |
272 | c1 = *cs++; |
273 | c2 = *ct++; | |
274 | if (c1 != c2) | |
275 | return c1 < c2 ? -1 : 1; | |
276 | if (!c1) | |
1da177e4 LT |
277 | break; |
278 | count--; | |
279 | } | |
a414f01a | 280 | return 0; |
1da177e4 LT |
281 | } |
282 | EXPORT_SYMBOL(strncmp); | |
283 | #endif | |
284 | ||
285 | #ifndef __HAVE_ARCH_STRCHR | |
286 | /** | |
287 | * strchr - Find the first occurrence of a character in a string | |
288 | * @s: The string to be searched | |
289 | * @c: The character to search for | |
290 | */ | |
51a0f0f6 | 291 | char *strchr(const char *s, int c) |
1da177e4 | 292 | { |
51a0f0f6 | 293 | for (; *s != (char)c; ++s) |
1da177e4 LT |
294 | if (*s == '\0') |
295 | return NULL; | |
51a0f0f6 | 296 | return (char *)s; |
1da177e4 LT |
297 | } |
298 | EXPORT_SYMBOL(strchr); | |
299 | #endif | |
300 | ||
301 | #ifndef __HAVE_ARCH_STRRCHR | |
302 | /** | |
303 | * strrchr - Find the last occurrence of a character in a string | |
304 | * @s: The string to be searched | |
305 | * @c: The character to search for | |
306 | */ | |
51a0f0f6 | 307 | char *strrchr(const char *s, int c) |
1da177e4 LT |
308 | { |
309 | const char *p = s + strlen(s); | |
310 | do { | |
311 | if (*p == (char)c) | |
312 | return (char *)p; | |
313 | } while (--p >= s); | |
314 | return NULL; | |
315 | } | |
316 | EXPORT_SYMBOL(strrchr); | |
317 | #endif | |
318 | ||
319 | #ifndef __HAVE_ARCH_STRNCHR | |
320 | /** | |
321 | * strnchr - Find a character in a length limited string | |
322 | * @s: The string to be searched | |
323 | * @count: The number of characters to be searched | |
324 | * @c: The character to search for | |
325 | */ | |
326 | char *strnchr(const char *s, size_t count, int c) | |
327 | { | |
328 | for (; count-- && *s != '\0'; ++s) | |
51a0f0f6 JJ |
329 | if (*s == (char)c) |
330 | return (char *)s; | |
1da177e4 LT |
331 | return NULL; |
332 | } | |
333 | EXPORT_SYMBOL(strnchr); | |
334 | #endif | |
335 | ||
f653398c | 336 | /** |
a6cd13f3 RD |
337 | * skip_spaces - Removes leading whitespace from @str. |
338 | * @str: The string to be stripped. | |
f653398c | 339 | * |
a6cd13f3 | 340 | * Returns a pointer to the first non-whitespace character in @str. |
f653398c AGR |
341 | */ |
342 | char *skip_spaces(const char *str) | |
343 | { | |
344 | while (isspace(*str)) | |
345 | ++str; | |
346 | return (char *)str; | |
347 | } | |
348 | EXPORT_SYMBOL(skip_spaces); | |
349 | ||
481fad48 | 350 | /** |
ca54cb8c | 351 | * strim - Removes leading and trailing whitespace from @s. |
481fad48 PE |
352 | * @s: The string to be stripped. |
353 | * | |
354 | * Note that the first trailing whitespace is replaced with a %NUL-terminator | |
355 | * in the given string @s. Returns a pointer to the first non-whitespace | |
356 | * character in @s. | |
357 | */ | |
ca54cb8c | 358 | char *strim(char *s) |
481fad48 PE |
359 | { |
360 | size_t size; | |
361 | char *end; | |
362 | ||
84c95c9a | 363 | s = skip_spaces(s); |
481fad48 | 364 | size = strlen(s); |
481fad48 PE |
365 | if (!size) |
366 | return s; | |
367 | ||
368 | end = s + size - 1; | |
6e6d9fa6 | 369 | while (end >= s && isspace(*end)) |
481fad48 PE |
370 | end--; |
371 | *(end + 1) = '\0'; | |
372 | ||
84c95c9a | 373 | return s; |
481fad48 | 374 | } |
ca54cb8c | 375 | EXPORT_SYMBOL(strim); |
481fad48 | 376 | |
1da177e4 LT |
377 | #ifndef __HAVE_ARCH_STRLEN |
378 | /** | |
379 | * strlen - Find the length of a string | |
380 | * @s: The string to be sized | |
381 | */ | |
51a0f0f6 | 382 | size_t strlen(const char *s) |
1da177e4 LT |
383 | { |
384 | const char *sc; | |
385 | ||
386 | for (sc = s; *sc != '\0'; ++sc) | |
387 | /* nothing */; | |
388 | return sc - s; | |
389 | } | |
390 | EXPORT_SYMBOL(strlen); | |
391 | #endif | |
392 | ||
393 | #ifndef __HAVE_ARCH_STRNLEN | |
394 | /** | |
395 | * strnlen - Find the length of a length-limited string | |
396 | * @s: The string to be sized | |
397 | * @count: The maximum number of bytes to search | |
398 | */ | |
51a0f0f6 | 399 | size_t strnlen(const char *s, size_t count) |
1da177e4 LT |
400 | { |
401 | const char *sc; | |
402 | ||
403 | for (sc = s; count-- && *sc != '\0'; ++sc) | |
404 | /* nothing */; | |
405 | return sc - s; | |
406 | } | |
407 | EXPORT_SYMBOL(strnlen); | |
408 | #endif | |
409 | ||
410 | #ifndef __HAVE_ARCH_STRSPN | |
411 | /** | |
72fd4a35 | 412 | * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept |
1da177e4 LT |
413 | * @s: The string to be searched |
414 | * @accept: The string to search for | |
415 | */ | |
416 | size_t strspn(const char *s, const char *accept) | |
417 | { | |
418 | const char *p; | |
419 | const char *a; | |
420 | size_t count = 0; | |
421 | ||
422 | for (p = s; *p != '\0'; ++p) { | |
423 | for (a = accept; *a != '\0'; ++a) { | |
424 | if (*p == *a) | |
425 | break; | |
426 | } | |
427 | if (*a == '\0') | |
428 | return count; | |
429 | ++count; | |
430 | } | |
1da177e4 LT |
431 | return count; |
432 | } | |
433 | ||
434 | EXPORT_SYMBOL(strspn); | |
435 | #endif | |
436 | ||
8833d328 | 437 | #ifndef __HAVE_ARCH_STRCSPN |
1da177e4 | 438 | /** |
72fd4a35 | 439 | * strcspn - Calculate the length of the initial substring of @s which does not contain letters in @reject |
1da177e4 LT |
440 | * @s: The string to be searched |
441 | * @reject: The string to avoid | |
442 | */ | |
443 | size_t strcspn(const char *s, const char *reject) | |
444 | { | |
445 | const char *p; | |
446 | const char *r; | |
447 | size_t count = 0; | |
448 | ||
449 | for (p = s; *p != '\0'; ++p) { | |
450 | for (r = reject; *r != '\0'; ++r) { | |
451 | if (*p == *r) | |
452 | return count; | |
453 | } | |
454 | ++count; | |
455 | } | |
1da177e4 | 456 | return count; |
51a0f0f6 | 457 | } |
1da177e4 | 458 | EXPORT_SYMBOL(strcspn); |
8833d328 | 459 | #endif |
1da177e4 LT |
460 | |
461 | #ifndef __HAVE_ARCH_STRPBRK | |
462 | /** | |
463 | * strpbrk - Find the first occurrence of a set of characters | |
464 | * @cs: The string to be searched | |
465 | * @ct: The characters to search for | |
466 | */ | |
51a0f0f6 | 467 | char *strpbrk(const char *cs, const char *ct) |
1da177e4 | 468 | { |
51a0f0f6 | 469 | const char *sc1, *sc2; |
1da177e4 | 470 | |
51a0f0f6 JJ |
471 | for (sc1 = cs; *sc1 != '\0'; ++sc1) { |
472 | for (sc2 = ct; *sc2 != '\0'; ++sc2) { | |
1da177e4 | 473 | if (*sc1 == *sc2) |
51a0f0f6 | 474 | return (char *)sc1; |
1da177e4 LT |
475 | } |
476 | } | |
477 | return NULL; | |
478 | } | |
894b5779 | 479 | EXPORT_SYMBOL(strpbrk); |
1da177e4 LT |
480 | #endif |
481 | ||
482 | #ifndef __HAVE_ARCH_STRSEP | |
483 | /** | |
484 | * strsep - Split a string into tokens | |
485 | * @s: The string to be searched | |
486 | * @ct: The characters to search for | |
487 | * | |
488 | * strsep() updates @s to point after the token, ready for the next call. | |
489 | * | |
490 | * It returns empty tokens, too, behaving exactly like the libc function | |
491 | * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. | |
492 | * Same semantics, slimmer shape. ;) | |
493 | */ | |
51a0f0f6 | 494 | char *strsep(char **s, const char *ct) |
1da177e4 | 495 | { |
51a0f0f6 JJ |
496 | char *sbegin = *s; |
497 | char *end; | |
1da177e4 LT |
498 | |
499 | if (sbegin == NULL) | |
500 | return NULL; | |
501 | ||
502 | end = strpbrk(sbegin, ct); | |
503 | if (end) | |
504 | *end++ = '\0'; | |
505 | *s = end; | |
1da177e4 LT |
506 | return sbegin; |
507 | } | |
1da177e4 LT |
508 | EXPORT_SYMBOL(strsep); |
509 | #endif | |
510 | ||
34990cf7 DB |
511 | /** |
512 | * sysfs_streq - return true if strings are equal, modulo trailing newline | |
513 | * @s1: one string | |
514 | * @s2: another string | |
515 | * | |
516 | * This routine returns true iff two strings are equal, treating both | |
517 | * NUL and newline-then-NUL as equivalent string terminations. It's | |
518 | * geared for use with sysfs input strings, which generally terminate | |
519 | * with newlines but are compared against values without newlines. | |
520 | */ | |
521 | bool sysfs_streq(const char *s1, const char *s2) | |
522 | { | |
523 | while (*s1 && *s1 == *s2) { | |
524 | s1++; | |
525 | s2++; | |
526 | } | |
527 | ||
528 | if (*s1 == *s2) | |
529 | return true; | |
530 | if (!*s1 && *s2 == '\n' && !s2[1]) | |
531 | return true; | |
532 | if (*s1 == '\n' && !s1[1] && !*s2) | |
533 | return true; | |
534 | return false; | |
535 | } | |
536 | EXPORT_SYMBOL(sysfs_streq); | |
537 | ||
1da177e4 LT |
538 | #ifndef __HAVE_ARCH_MEMSET |
539 | /** | |
540 | * memset - Fill a region of memory with the given value | |
541 | * @s: Pointer to the start of the area. | |
542 | * @c: The byte to fill the area with | |
543 | * @count: The size of the area. | |
544 | * | |
545 | * Do not use memset() to access IO space, use memset_io() instead. | |
546 | */ | |
51a0f0f6 | 547 | void *memset(void *s, int c, size_t count) |
1da177e4 | 548 | { |
850b9247 | 549 | char *xs = s; |
1da177e4 LT |
550 | |
551 | while (count--) | |
552 | *xs++ = c; | |
1da177e4 LT |
553 | return s; |
554 | } | |
555 | EXPORT_SYMBOL(memset); | |
556 | #endif | |
557 | ||
558 | #ifndef __HAVE_ARCH_MEMCPY | |
559 | /** | |
560 | * memcpy - Copy one area of memory to another | |
561 | * @dest: Where to copy to | |
562 | * @src: Where to copy from | |
563 | * @count: The size of the area. | |
564 | * | |
565 | * You should not use this function to access IO space, use memcpy_toio() | |
566 | * or memcpy_fromio() instead. | |
567 | */ | |
51a0f0f6 | 568 | void *memcpy(void *dest, const void *src, size_t count) |
1da177e4 | 569 | { |
850b9247 | 570 | char *tmp = dest; |
4c416ab7 | 571 | const char *s = src; |
1da177e4 LT |
572 | |
573 | while (count--) | |
574 | *tmp++ = *s++; | |
1da177e4 LT |
575 | return dest; |
576 | } | |
577 | EXPORT_SYMBOL(memcpy); | |
578 | #endif | |
579 | ||
580 | #ifndef __HAVE_ARCH_MEMMOVE | |
581 | /** | |
582 | * memmove - Copy one area of memory to another | |
583 | * @dest: Where to copy to | |
584 | * @src: Where to copy from | |
585 | * @count: The size of the area. | |
586 | * | |
587 | * Unlike memcpy(), memmove() copes with overlapping areas. | |
588 | */ | |
51a0f0f6 | 589 | void *memmove(void *dest, const void *src, size_t count) |
1da177e4 | 590 | { |
82da2c37 PJ |
591 | char *tmp; |
592 | const char *s; | |
1da177e4 LT |
593 | |
594 | if (dest <= src) { | |
850b9247 JJ |
595 | tmp = dest; |
596 | s = src; | |
1da177e4 LT |
597 | while (count--) |
598 | *tmp++ = *s++; | |
51a0f0f6 | 599 | } else { |
850b9247 JJ |
600 | tmp = dest; |
601 | tmp += count; | |
602 | s = src; | |
603 | s += count; | |
1da177e4 LT |
604 | while (count--) |
605 | *--tmp = *--s; | |
51a0f0f6 | 606 | } |
1da177e4 LT |
607 | return dest; |
608 | } | |
609 | EXPORT_SYMBOL(memmove); | |
610 | #endif | |
611 | ||
612 | #ifndef __HAVE_ARCH_MEMCMP | |
613 | /** | |
614 | * memcmp - Compare two areas of memory | |
615 | * @cs: One area of memory | |
616 | * @ct: Another area of memory | |
617 | * @count: The size of the area. | |
618 | */ | |
0c28130b | 619 | #undef memcmp |
51a0f0f6 | 620 | int memcmp(const void *cs, const void *ct, size_t count) |
1da177e4 LT |
621 | { |
622 | const unsigned char *su1, *su2; | |
623 | int res = 0; | |
624 | ||
51a0f0f6 | 625 | for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) |
1da177e4 LT |
626 | if ((res = *su1 - *su2) != 0) |
627 | break; | |
628 | return res; | |
629 | } | |
630 | EXPORT_SYMBOL(memcmp); | |
631 | #endif | |
632 | ||
633 | #ifndef __HAVE_ARCH_MEMSCAN | |
634 | /** | |
635 | * memscan - Find a character in an area of memory. | |
636 | * @addr: The memory area | |
637 | * @c: The byte to search for | |
638 | * @size: The size of the area. | |
639 | * | |
640 | * returns the address of the first occurrence of @c, or 1 byte past | |
641 | * the area if @c is not found | |
642 | */ | |
51a0f0f6 | 643 | void *memscan(void *addr, int c, size_t size) |
1da177e4 | 644 | { |
850b9247 | 645 | unsigned char *p = addr; |
1da177e4 LT |
646 | |
647 | while (size) { | |
648 | if (*p == c) | |
51a0f0f6 | 649 | return (void *)p; |
1da177e4 LT |
650 | p++; |
651 | size--; | |
652 | } | |
51a0f0f6 | 653 | return (void *)p; |
1da177e4 LT |
654 | } |
655 | EXPORT_SYMBOL(memscan); | |
656 | #endif | |
657 | ||
658 | #ifndef __HAVE_ARCH_STRSTR | |
659 | /** | |
660 | * strstr - Find the first substring in a %NUL terminated string | |
661 | * @s1: The string to be searched | |
662 | * @s2: The string to search for | |
663 | */ | |
51a0f0f6 | 664 | char *strstr(const char *s1, const char *s2) |
1da177e4 | 665 | { |
d5f1fb53 | 666 | size_t l1, l2; |
1da177e4 LT |
667 | |
668 | l2 = strlen(s2); | |
669 | if (!l2) | |
51a0f0f6 | 670 | return (char *)s1; |
1da177e4 LT |
671 | l1 = strlen(s1); |
672 | while (l1 >= l2) { | |
673 | l1--; | |
51a0f0f6 JJ |
674 | if (!memcmp(s1, s2, l2)) |
675 | return (char *)s1; | |
1da177e4 LT |
676 | s1++; |
677 | } | |
678 | return NULL; | |
679 | } | |
680 | EXPORT_SYMBOL(strstr); | |
681 | #endif | |
682 | ||
d5f1fb53 LZ |
683 | #ifndef __HAVE_ARCH_STRNSTR |
684 | /** | |
685 | * strnstr - Find the first substring in a length-limited string | |
686 | * @s1: The string to be searched | |
687 | * @s2: The string to search for | |
688 | * @len: the maximum number of characters to search | |
689 | */ | |
690 | char *strnstr(const char *s1, const char *s2, size_t len) | |
691 | { | |
d6a2eedf | 692 | size_t l2; |
d5f1fb53 LZ |
693 | |
694 | l2 = strlen(s2); | |
695 | if (!l2) | |
696 | return (char *)s1; | |
d6a2eedf AGR |
697 | while (len >= l2) { |
698 | len--; | |
d5f1fb53 LZ |
699 | if (!memcmp(s1, s2, l2)) |
700 | return (char *)s1; | |
701 | s1++; | |
702 | } | |
703 | return NULL; | |
704 | } | |
705 | EXPORT_SYMBOL(strnstr); | |
706 | #endif | |
707 | ||
1da177e4 LT |
708 | #ifndef __HAVE_ARCH_MEMCHR |
709 | /** | |
710 | * memchr - Find a character in an area of memory. | |
711 | * @s: The memory area | |
712 | * @c: The byte to search for | |
713 | * @n: The size of the area. | |
714 | * | |
715 | * returns the address of the first occurrence of @c, or %NULL | |
716 | * if @c is not found | |
717 | */ | |
718 | void *memchr(const void *s, int c, size_t n) | |
719 | { | |
720 | const unsigned char *p = s; | |
721 | while (n-- != 0) { | |
722 | if ((unsigned char)c == *p++) { | |
51a0f0f6 | 723 | return (void *)(p - 1); |
1da177e4 LT |
724 | } |
725 | } | |
726 | return NULL; | |
727 | } | |
728 | EXPORT_SYMBOL(memchr); | |
729 | #endif |