xref: /kernel/linux/linux-6.6/lib/string.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/lib/string.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 1991, 1992  Linus Torvalds
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * This file should be used only for "library" routines that may have
1062306a36Sopenharmony_ci * alternative implementations on specific architectures (generally
1162306a36Sopenharmony_ci * found in <asm-xx/string.h>), or get overloaded by FORTIFY_SOURCE.
1262306a36Sopenharmony_ci * (Specifically, this file is built with __NO_FORTIFY.)
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Other helper functions should live in string_helpers.c.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define __NO_FORTIFY
1862306a36Sopenharmony_ci#include <linux/types.h>
1962306a36Sopenharmony_ci#include <linux/string.h>
2062306a36Sopenharmony_ci#include <linux/ctype.h>
2162306a36Sopenharmony_ci#include <linux/kernel.h>
2262306a36Sopenharmony_ci#include <linux/export.h>
2362306a36Sopenharmony_ci#include <linux/bug.h>
2462306a36Sopenharmony_ci#include <linux/errno.h>
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <asm/unaligned.h>
2862306a36Sopenharmony_ci#include <asm/byteorder.h>
2962306a36Sopenharmony_ci#include <asm/word-at-a-time.h>
3062306a36Sopenharmony_ci#include <asm/page.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNCASECMP
3362306a36Sopenharmony_ci/**
3462306a36Sopenharmony_ci * strncasecmp - Case insensitive, length-limited string comparison
3562306a36Sopenharmony_ci * @s1: One string
3662306a36Sopenharmony_ci * @s2: The other string
3762306a36Sopenharmony_ci * @len: the maximum number of characters to compare
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ciint strncasecmp(const char *s1, const char *s2, size_t len)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	/* Yes, Virginia, it had better be unsigned */
4262306a36Sopenharmony_ci	unsigned char c1, c2;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	if (!len)
4562306a36Sopenharmony_ci		return 0;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	do {
4862306a36Sopenharmony_ci		c1 = *s1++;
4962306a36Sopenharmony_ci		c2 = *s2++;
5062306a36Sopenharmony_ci		if (!c1 || !c2)
5162306a36Sopenharmony_ci			break;
5262306a36Sopenharmony_ci		if (c1 == c2)
5362306a36Sopenharmony_ci			continue;
5462306a36Sopenharmony_ci		c1 = tolower(c1);
5562306a36Sopenharmony_ci		c2 = tolower(c2);
5662306a36Sopenharmony_ci		if (c1 != c2)
5762306a36Sopenharmony_ci			break;
5862306a36Sopenharmony_ci	} while (--len);
5962306a36Sopenharmony_ci	return (int)c1 - (int)c2;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ciEXPORT_SYMBOL(strncasecmp);
6262306a36Sopenharmony_ci#endif
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCASECMP
6562306a36Sopenharmony_ciint strcasecmp(const char *s1, const char *s2)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	int c1, c2;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	do {
7062306a36Sopenharmony_ci		c1 = tolower(*s1++);
7162306a36Sopenharmony_ci		c2 = tolower(*s2++);
7262306a36Sopenharmony_ci	} while (c1 == c2 && c1 != 0);
7362306a36Sopenharmony_ci	return c1 - c2;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ciEXPORT_SYMBOL(strcasecmp);
7662306a36Sopenharmony_ci#endif
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCPY
7962306a36Sopenharmony_cichar *strcpy(char *dest, const char *src)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	char *tmp = dest;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	while ((*dest++ = *src++) != '\0')
8462306a36Sopenharmony_ci		/* nothing */;
8562306a36Sopenharmony_ci	return tmp;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ciEXPORT_SYMBOL(strcpy);
8862306a36Sopenharmony_ci#endif
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNCPY
9162306a36Sopenharmony_cichar *strncpy(char *dest, const char *src, size_t count)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	char *tmp = dest;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	while (count) {
9662306a36Sopenharmony_ci		if ((*tmp = *src) != 0)
9762306a36Sopenharmony_ci			src++;
9862306a36Sopenharmony_ci		tmp++;
9962306a36Sopenharmony_ci		count--;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci	return dest;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ciEXPORT_SYMBOL(strncpy);
10462306a36Sopenharmony_ci#endif
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRLCPY
10762306a36Sopenharmony_cisize_t strlcpy(char *dest, const char *src, size_t size)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	size_t ret = strlen(src);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	if (size) {
11262306a36Sopenharmony_ci		size_t len = (ret >= size) ? size - 1 : ret;
11362306a36Sopenharmony_ci		__builtin_memcpy(dest, src, len);
11462306a36Sopenharmony_ci		dest[len] = '\0';
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci	return ret;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ciEXPORT_SYMBOL(strlcpy);
11962306a36Sopenharmony_ci#endif
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRSCPY
12262306a36Sopenharmony_cissize_t strscpy(char *dest, const char *src, size_t count)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
12562306a36Sopenharmony_ci	size_t max = count;
12662306a36Sopenharmony_ci	long res = 0;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
12962306a36Sopenharmony_ci		return -E2BIG;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
13262306a36Sopenharmony_ci	/*
13362306a36Sopenharmony_ci	 * If src is unaligned, don't cross a page boundary,
13462306a36Sopenharmony_ci	 * since we don't know if the next page is mapped.
13562306a36Sopenharmony_ci	 */
13662306a36Sopenharmony_ci	if ((long)src & (sizeof(long) - 1)) {
13762306a36Sopenharmony_ci		size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
13862306a36Sopenharmony_ci		if (limit < max)
13962306a36Sopenharmony_ci			max = limit;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci#else
14262306a36Sopenharmony_ci	/* If src or dest is unaligned, don't do word-at-a-time. */
14362306a36Sopenharmony_ci	if (((long) dest | (long) src) & (sizeof(long) - 1))
14462306a36Sopenharmony_ci		max = 0;
14562306a36Sopenharmony_ci#endif
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/*
14862306a36Sopenharmony_ci	 * read_word_at_a_time() below may read uninitialized bytes after the
14962306a36Sopenharmony_ci	 * trailing zero and use them in comparisons. Disable this optimization
15062306a36Sopenharmony_ci	 * under KMSAN to prevent false positive reports.
15162306a36Sopenharmony_ci	 */
15262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_KMSAN))
15362306a36Sopenharmony_ci		max = 0;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	while (max >= sizeof(unsigned long)) {
15662306a36Sopenharmony_ci		unsigned long c, data;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci		c = read_word_at_a_time(src+res);
15962306a36Sopenharmony_ci		if (has_zero(c, &data, &constants)) {
16062306a36Sopenharmony_ci			data = prep_zero_mask(c, data, &constants);
16162306a36Sopenharmony_ci			data = create_zero_mask(data);
16262306a36Sopenharmony_ci			*(unsigned long *)(dest+res) = c & zero_bytemask(data);
16362306a36Sopenharmony_ci			return res + find_zero(data);
16462306a36Sopenharmony_ci		}
16562306a36Sopenharmony_ci		*(unsigned long *)(dest+res) = c;
16662306a36Sopenharmony_ci		res += sizeof(unsigned long);
16762306a36Sopenharmony_ci		count -= sizeof(unsigned long);
16862306a36Sopenharmony_ci		max -= sizeof(unsigned long);
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	while (count) {
17262306a36Sopenharmony_ci		char c;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		c = src[res];
17562306a36Sopenharmony_ci		dest[res] = c;
17662306a36Sopenharmony_ci		if (!c)
17762306a36Sopenharmony_ci			return res;
17862306a36Sopenharmony_ci		res++;
17962306a36Sopenharmony_ci		count--;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	/* Hit buffer length without finding a NUL; force NUL-termination. */
18362306a36Sopenharmony_ci	if (res)
18462306a36Sopenharmony_ci		dest[res-1] = '\0';
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	return -E2BIG;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ciEXPORT_SYMBOL(strscpy);
18962306a36Sopenharmony_ci#endif
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/**
19262306a36Sopenharmony_ci * stpcpy - copy a string from src to dest returning a pointer to the new end
19362306a36Sopenharmony_ci *          of dest, including src's %NUL-terminator. May overrun dest.
19462306a36Sopenharmony_ci * @dest: pointer to end of string being copied into. Must be large enough
19562306a36Sopenharmony_ci *        to receive copy.
19662306a36Sopenharmony_ci * @src: pointer to the beginning of string being copied from. Must not overlap
19762306a36Sopenharmony_ci *       dest.
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci * stpcpy differs from strcpy in a key way: the return value is a pointer
20062306a36Sopenharmony_ci * to the new %NUL-terminating character in @dest. (For strcpy, the return
20162306a36Sopenharmony_ci * value is a pointer to the start of @dest). This interface is considered
20262306a36Sopenharmony_ci * unsafe as it doesn't perform bounds checking of the inputs. As such it's
20362306a36Sopenharmony_ci * not recommended for usage. Instead, its definition is provided in case
20462306a36Sopenharmony_ci * the compiler lowers other libcalls to stpcpy.
20562306a36Sopenharmony_ci */
20662306a36Sopenharmony_cichar *stpcpy(char *__restrict__ dest, const char *__restrict__ src);
20762306a36Sopenharmony_cichar *stpcpy(char *__restrict__ dest, const char *__restrict__ src)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	while ((*dest++ = *src++) != '\0')
21062306a36Sopenharmony_ci		/* nothing */;
21162306a36Sopenharmony_ci	return --dest;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ciEXPORT_SYMBOL(stpcpy);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCAT
21662306a36Sopenharmony_cichar *strcat(char *dest, const char *src)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	char *tmp = dest;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	while (*dest)
22162306a36Sopenharmony_ci		dest++;
22262306a36Sopenharmony_ci	while ((*dest++ = *src++) != '\0')
22362306a36Sopenharmony_ci		;
22462306a36Sopenharmony_ci	return tmp;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ciEXPORT_SYMBOL(strcat);
22762306a36Sopenharmony_ci#endif
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNCAT
23062306a36Sopenharmony_cichar *strncat(char *dest, const char *src, size_t count)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	char *tmp = dest;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (count) {
23562306a36Sopenharmony_ci		while (*dest)
23662306a36Sopenharmony_ci			dest++;
23762306a36Sopenharmony_ci		while ((*dest++ = *src++) != 0) {
23862306a36Sopenharmony_ci			if (--count == 0) {
23962306a36Sopenharmony_ci				*dest = '\0';
24062306a36Sopenharmony_ci				break;
24162306a36Sopenharmony_ci			}
24262306a36Sopenharmony_ci		}
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci	return tmp;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ciEXPORT_SYMBOL(strncat);
24762306a36Sopenharmony_ci#endif
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRLCAT
25062306a36Sopenharmony_cisize_t strlcat(char *dest, const char *src, size_t count)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	size_t dsize = strlen(dest);
25362306a36Sopenharmony_ci	size_t len = strlen(src);
25462306a36Sopenharmony_ci	size_t res = dsize + len;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	/* This would be a bug */
25762306a36Sopenharmony_ci	BUG_ON(dsize >= count);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	dest += dsize;
26062306a36Sopenharmony_ci	count -= dsize;
26162306a36Sopenharmony_ci	if (len >= count)
26262306a36Sopenharmony_ci		len = count-1;
26362306a36Sopenharmony_ci	__builtin_memcpy(dest, src, len);
26462306a36Sopenharmony_ci	dest[len] = 0;
26562306a36Sopenharmony_ci	return res;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ciEXPORT_SYMBOL(strlcat);
26862306a36Sopenharmony_ci#endif
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCMP
27162306a36Sopenharmony_ci/**
27262306a36Sopenharmony_ci * strcmp - Compare two strings
27362306a36Sopenharmony_ci * @cs: One string
27462306a36Sopenharmony_ci * @ct: Another string
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_ciint strcmp(const char *cs, const char *ct)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	unsigned char c1, c2;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	while (1) {
28162306a36Sopenharmony_ci		c1 = *cs++;
28262306a36Sopenharmony_ci		c2 = *ct++;
28362306a36Sopenharmony_ci		if (c1 != c2)
28462306a36Sopenharmony_ci			return c1 < c2 ? -1 : 1;
28562306a36Sopenharmony_ci		if (!c1)
28662306a36Sopenharmony_ci			break;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	return 0;
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ciEXPORT_SYMBOL(strcmp);
29162306a36Sopenharmony_ci#endif
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNCMP
29462306a36Sopenharmony_ci/**
29562306a36Sopenharmony_ci * strncmp - Compare two length-limited strings
29662306a36Sopenharmony_ci * @cs: One string
29762306a36Sopenharmony_ci * @ct: Another string
29862306a36Sopenharmony_ci * @count: The maximum number of bytes to compare
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_ciint strncmp(const char *cs, const char *ct, size_t count)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	unsigned char c1, c2;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	while (count) {
30562306a36Sopenharmony_ci		c1 = *cs++;
30662306a36Sopenharmony_ci		c2 = *ct++;
30762306a36Sopenharmony_ci		if (c1 != c2)
30862306a36Sopenharmony_ci			return c1 < c2 ? -1 : 1;
30962306a36Sopenharmony_ci		if (!c1)
31062306a36Sopenharmony_ci			break;
31162306a36Sopenharmony_ci		count--;
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci	return 0;
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ciEXPORT_SYMBOL(strncmp);
31662306a36Sopenharmony_ci#endif
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCHR
31962306a36Sopenharmony_ci/**
32062306a36Sopenharmony_ci * strchr - Find the first occurrence of a character in a string
32162306a36Sopenharmony_ci * @s: The string to be searched
32262306a36Sopenharmony_ci * @c: The character to search for
32362306a36Sopenharmony_ci *
32462306a36Sopenharmony_ci * Note that the %NUL-terminator is considered part of the string, and can
32562306a36Sopenharmony_ci * be searched for.
32662306a36Sopenharmony_ci */
32762306a36Sopenharmony_cichar *strchr(const char *s, int c)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	for (; *s != (char)c; ++s)
33062306a36Sopenharmony_ci		if (*s == '\0')
33162306a36Sopenharmony_ci			return NULL;
33262306a36Sopenharmony_ci	return (char *)s;
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ciEXPORT_SYMBOL(strchr);
33562306a36Sopenharmony_ci#endif
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCHRNUL
33862306a36Sopenharmony_ci/**
33962306a36Sopenharmony_ci * strchrnul - Find and return a character in a string, or end of string
34062306a36Sopenharmony_ci * @s: The string to be searched
34162306a36Sopenharmony_ci * @c: The character to search for
34262306a36Sopenharmony_ci *
34362306a36Sopenharmony_ci * Returns pointer to first occurrence of 'c' in s. If c is not found, then
34462306a36Sopenharmony_ci * return a pointer to the null byte at the end of s.
34562306a36Sopenharmony_ci */
34662306a36Sopenharmony_cichar *strchrnul(const char *s, int c)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	while (*s && *s != (char)c)
34962306a36Sopenharmony_ci		s++;
35062306a36Sopenharmony_ci	return (char *)s;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ciEXPORT_SYMBOL(strchrnul);
35362306a36Sopenharmony_ci#endif
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci/**
35662306a36Sopenharmony_ci * strnchrnul - Find and return a character in a length limited string,
35762306a36Sopenharmony_ci * or end of string
35862306a36Sopenharmony_ci * @s: The string to be searched
35962306a36Sopenharmony_ci * @count: The number of characters to be searched
36062306a36Sopenharmony_ci * @c: The character to search for
36162306a36Sopenharmony_ci *
36262306a36Sopenharmony_ci * Returns pointer to the first occurrence of 'c' in s. If c is not found,
36362306a36Sopenharmony_ci * then return a pointer to the last character of the string.
36462306a36Sopenharmony_ci */
36562306a36Sopenharmony_cichar *strnchrnul(const char *s, size_t count, int c)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	while (count-- && *s && *s != (char)c)
36862306a36Sopenharmony_ci		s++;
36962306a36Sopenharmony_ci	return (char *)s;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRRCHR
37362306a36Sopenharmony_ci/**
37462306a36Sopenharmony_ci * strrchr - Find the last occurrence of a character in a string
37562306a36Sopenharmony_ci * @s: The string to be searched
37662306a36Sopenharmony_ci * @c: The character to search for
37762306a36Sopenharmony_ci */
37862306a36Sopenharmony_cichar *strrchr(const char *s, int c)
37962306a36Sopenharmony_ci{
38062306a36Sopenharmony_ci	const char *last = NULL;
38162306a36Sopenharmony_ci	do {
38262306a36Sopenharmony_ci		if (*s == (char)c)
38362306a36Sopenharmony_ci			last = s;
38462306a36Sopenharmony_ci	} while (*s++);
38562306a36Sopenharmony_ci	return (char *)last;
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ciEXPORT_SYMBOL(strrchr);
38862306a36Sopenharmony_ci#endif
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNCHR
39162306a36Sopenharmony_ci/**
39262306a36Sopenharmony_ci * strnchr - Find a character in a length limited string
39362306a36Sopenharmony_ci * @s: The string to be searched
39462306a36Sopenharmony_ci * @count: The number of characters to be searched
39562306a36Sopenharmony_ci * @c: The character to search for
39662306a36Sopenharmony_ci *
39762306a36Sopenharmony_ci * Note that the %NUL-terminator is considered part of the string, and can
39862306a36Sopenharmony_ci * be searched for.
39962306a36Sopenharmony_ci */
40062306a36Sopenharmony_cichar *strnchr(const char *s, size_t count, int c)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	while (count--) {
40362306a36Sopenharmony_ci		if (*s == (char)c)
40462306a36Sopenharmony_ci			return (char *)s;
40562306a36Sopenharmony_ci		if (*s++ == '\0')
40662306a36Sopenharmony_ci			break;
40762306a36Sopenharmony_ci	}
40862306a36Sopenharmony_ci	return NULL;
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ciEXPORT_SYMBOL(strnchr);
41162306a36Sopenharmony_ci#endif
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRLEN
41462306a36Sopenharmony_cisize_t strlen(const char *s)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	const char *sc;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	for (sc = s; *sc != '\0'; ++sc)
41962306a36Sopenharmony_ci		/* nothing */;
42062306a36Sopenharmony_ci	return sc - s;
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ciEXPORT_SYMBOL(strlen);
42362306a36Sopenharmony_ci#endif
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNLEN
42662306a36Sopenharmony_cisize_t strnlen(const char *s, size_t count)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	const char *sc;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	for (sc = s; count-- && *sc != '\0'; ++sc)
43162306a36Sopenharmony_ci		/* nothing */;
43262306a36Sopenharmony_ci	return sc - s;
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ciEXPORT_SYMBOL(strnlen);
43562306a36Sopenharmony_ci#endif
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRSPN
43862306a36Sopenharmony_ci/**
43962306a36Sopenharmony_ci * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
44062306a36Sopenharmony_ci * @s: The string to be searched
44162306a36Sopenharmony_ci * @accept: The string to search for
44262306a36Sopenharmony_ci */
44362306a36Sopenharmony_cisize_t strspn(const char *s, const char *accept)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	const char *p;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	for (p = s; *p != '\0'; ++p) {
44862306a36Sopenharmony_ci		if (!strchr(accept, *p))
44962306a36Sopenharmony_ci			break;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci	return p - s;
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ciEXPORT_SYMBOL(strspn);
45462306a36Sopenharmony_ci#endif
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRCSPN
45762306a36Sopenharmony_ci/**
45862306a36Sopenharmony_ci * strcspn - Calculate the length of the initial substring of @s which does not contain letters in @reject
45962306a36Sopenharmony_ci * @s: The string to be searched
46062306a36Sopenharmony_ci * @reject: The string to avoid
46162306a36Sopenharmony_ci */
46262306a36Sopenharmony_cisize_t strcspn(const char *s, const char *reject)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	const char *p;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	for (p = s; *p != '\0'; ++p) {
46762306a36Sopenharmony_ci		if (strchr(reject, *p))
46862306a36Sopenharmony_ci			break;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci	return p - s;
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ciEXPORT_SYMBOL(strcspn);
47362306a36Sopenharmony_ci#endif
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRPBRK
47662306a36Sopenharmony_ci/**
47762306a36Sopenharmony_ci * strpbrk - Find the first occurrence of a set of characters
47862306a36Sopenharmony_ci * @cs: The string to be searched
47962306a36Sopenharmony_ci * @ct: The characters to search for
48062306a36Sopenharmony_ci */
48162306a36Sopenharmony_cichar *strpbrk(const char *cs, const char *ct)
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	const char *sc;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	for (sc = cs; *sc != '\0'; ++sc) {
48662306a36Sopenharmony_ci		if (strchr(ct, *sc))
48762306a36Sopenharmony_ci			return (char *)sc;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci	return NULL;
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_ciEXPORT_SYMBOL(strpbrk);
49262306a36Sopenharmony_ci#endif
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRSEP
49562306a36Sopenharmony_ci/**
49662306a36Sopenharmony_ci * strsep - Split a string into tokens
49762306a36Sopenharmony_ci * @s: The string to be searched
49862306a36Sopenharmony_ci * @ct: The characters to search for
49962306a36Sopenharmony_ci *
50062306a36Sopenharmony_ci * strsep() updates @s to point after the token, ready for the next call.
50162306a36Sopenharmony_ci *
50262306a36Sopenharmony_ci * It returns empty tokens, too, behaving exactly like the libc function
50362306a36Sopenharmony_ci * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
50462306a36Sopenharmony_ci * Same semantics, slimmer shape. ;)
50562306a36Sopenharmony_ci */
50662306a36Sopenharmony_cichar *strsep(char **s, const char *ct)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	char *sbegin = *s;
50962306a36Sopenharmony_ci	char *end;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	if (sbegin == NULL)
51262306a36Sopenharmony_ci		return NULL;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	end = strpbrk(sbegin, ct);
51562306a36Sopenharmony_ci	if (end)
51662306a36Sopenharmony_ci		*end++ = '\0';
51762306a36Sopenharmony_ci	*s = end;
51862306a36Sopenharmony_ci	return sbegin;
51962306a36Sopenharmony_ci}
52062306a36Sopenharmony_ciEXPORT_SYMBOL(strsep);
52162306a36Sopenharmony_ci#endif
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMSET
52462306a36Sopenharmony_ci/**
52562306a36Sopenharmony_ci * memset - Fill a region of memory with the given value
52662306a36Sopenharmony_ci * @s: Pointer to the start of the area.
52762306a36Sopenharmony_ci * @c: The byte to fill the area with
52862306a36Sopenharmony_ci * @count: The size of the area.
52962306a36Sopenharmony_ci *
53062306a36Sopenharmony_ci * Do not use memset() to access IO space, use memset_io() instead.
53162306a36Sopenharmony_ci */
53262306a36Sopenharmony_civoid *memset(void *s, int c, size_t count)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	char *xs = s;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	while (count--)
53762306a36Sopenharmony_ci		*xs++ = c;
53862306a36Sopenharmony_ci	return s;
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ciEXPORT_SYMBOL(memset);
54162306a36Sopenharmony_ci#endif
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMSET16
54462306a36Sopenharmony_ci/**
54562306a36Sopenharmony_ci * memset16() - Fill a memory area with a uint16_t
54662306a36Sopenharmony_ci * @s: Pointer to the start of the area.
54762306a36Sopenharmony_ci * @v: The value to fill the area with
54862306a36Sopenharmony_ci * @count: The number of values to store
54962306a36Sopenharmony_ci *
55062306a36Sopenharmony_ci * Differs from memset() in that it fills with a uint16_t instead
55162306a36Sopenharmony_ci * of a byte.  Remember that @count is the number of uint16_ts to
55262306a36Sopenharmony_ci * store, not the number of bytes.
55362306a36Sopenharmony_ci */
55462306a36Sopenharmony_civoid *memset16(uint16_t *s, uint16_t v, size_t count)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	uint16_t *xs = s;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	while (count--)
55962306a36Sopenharmony_ci		*xs++ = v;
56062306a36Sopenharmony_ci	return s;
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ciEXPORT_SYMBOL(memset16);
56362306a36Sopenharmony_ci#endif
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMSET32
56662306a36Sopenharmony_ci/**
56762306a36Sopenharmony_ci * memset32() - Fill a memory area with a uint32_t
56862306a36Sopenharmony_ci * @s: Pointer to the start of the area.
56962306a36Sopenharmony_ci * @v: The value to fill the area with
57062306a36Sopenharmony_ci * @count: The number of values to store
57162306a36Sopenharmony_ci *
57262306a36Sopenharmony_ci * Differs from memset() in that it fills with a uint32_t instead
57362306a36Sopenharmony_ci * of a byte.  Remember that @count is the number of uint32_ts to
57462306a36Sopenharmony_ci * store, not the number of bytes.
57562306a36Sopenharmony_ci */
57662306a36Sopenharmony_civoid *memset32(uint32_t *s, uint32_t v, size_t count)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	uint32_t *xs = s;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	while (count--)
58162306a36Sopenharmony_ci		*xs++ = v;
58262306a36Sopenharmony_ci	return s;
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ciEXPORT_SYMBOL(memset32);
58562306a36Sopenharmony_ci#endif
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMSET64
58862306a36Sopenharmony_ci/**
58962306a36Sopenharmony_ci * memset64() - Fill a memory area with a uint64_t
59062306a36Sopenharmony_ci * @s: Pointer to the start of the area.
59162306a36Sopenharmony_ci * @v: The value to fill the area with
59262306a36Sopenharmony_ci * @count: The number of values to store
59362306a36Sopenharmony_ci *
59462306a36Sopenharmony_ci * Differs from memset() in that it fills with a uint64_t instead
59562306a36Sopenharmony_ci * of a byte.  Remember that @count is the number of uint64_ts to
59662306a36Sopenharmony_ci * store, not the number of bytes.
59762306a36Sopenharmony_ci */
59862306a36Sopenharmony_civoid *memset64(uint64_t *s, uint64_t v, size_t count)
59962306a36Sopenharmony_ci{
60062306a36Sopenharmony_ci	uint64_t *xs = s;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	while (count--)
60362306a36Sopenharmony_ci		*xs++ = v;
60462306a36Sopenharmony_ci	return s;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ciEXPORT_SYMBOL(memset64);
60762306a36Sopenharmony_ci#endif
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMCPY
61062306a36Sopenharmony_ci/**
61162306a36Sopenharmony_ci * memcpy - Copy one area of memory to another
61262306a36Sopenharmony_ci * @dest: Where to copy to
61362306a36Sopenharmony_ci * @src: Where to copy from
61462306a36Sopenharmony_ci * @count: The size of the area.
61562306a36Sopenharmony_ci *
61662306a36Sopenharmony_ci * You should not use this function to access IO space, use memcpy_toio()
61762306a36Sopenharmony_ci * or memcpy_fromio() instead.
61862306a36Sopenharmony_ci */
61962306a36Sopenharmony_civoid *memcpy(void *dest, const void *src, size_t count)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	char *tmp = dest;
62262306a36Sopenharmony_ci	const char *s = src;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	while (count--)
62562306a36Sopenharmony_ci		*tmp++ = *s++;
62662306a36Sopenharmony_ci	return dest;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ciEXPORT_SYMBOL(memcpy);
62962306a36Sopenharmony_ci#endif
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMMOVE
63262306a36Sopenharmony_ci/**
63362306a36Sopenharmony_ci * memmove - Copy one area of memory to another
63462306a36Sopenharmony_ci * @dest: Where to copy to
63562306a36Sopenharmony_ci * @src: Where to copy from
63662306a36Sopenharmony_ci * @count: The size of the area.
63762306a36Sopenharmony_ci *
63862306a36Sopenharmony_ci * Unlike memcpy(), memmove() copes with overlapping areas.
63962306a36Sopenharmony_ci */
64062306a36Sopenharmony_civoid *memmove(void *dest, const void *src, size_t count)
64162306a36Sopenharmony_ci{
64262306a36Sopenharmony_ci	char *tmp;
64362306a36Sopenharmony_ci	const char *s;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (dest <= src) {
64662306a36Sopenharmony_ci		tmp = dest;
64762306a36Sopenharmony_ci		s = src;
64862306a36Sopenharmony_ci		while (count--)
64962306a36Sopenharmony_ci			*tmp++ = *s++;
65062306a36Sopenharmony_ci	} else {
65162306a36Sopenharmony_ci		tmp = dest;
65262306a36Sopenharmony_ci		tmp += count;
65362306a36Sopenharmony_ci		s = src;
65462306a36Sopenharmony_ci		s += count;
65562306a36Sopenharmony_ci		while (count--)
65662306a36Sopenharmony_ci			*--tmp = *--s;
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci	return dest;
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ciEXPORT_SYMBOL(memmove);
66162306a36Sopenharmony_ci#endif
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMCMP
66462306a36Sopenharmony_ci/**
66562306a36Sopenharmony_ci * memcmp - Compare two areas of memory
66662306a36Sopenharmony_ci * @cs: One area of memory
66762306a36Sopenharmony_ci * @ct: Another area of memory
66862306a36Sopenharmony_ci * @count: The size of the area.
66962306a36Sopenharmony_ci */
67062306a36Sopenharmony_ci#undef memcmp
67162306a36Sopenharmony_ci__visible int memcmp(const void *cs, const void *ct, size_t count)
67262306a36Sopenharmony_ci{
67362306a36Sopenharmony_ci	const unsigned char *su1, *su2;
67462306a36Sopenharmony_ci	int res = 0;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
67762306a36Sopenharmony_ci	if (count >= sizeof(unsigned long)) {
67862306a36Sopenharmony_ci		const unsigned long *u1 = cs;
67962306a36Sopenharmony_ci		const unsigned long *u2 = ct;
68062306a36Sopenharmony_ci		do {
68162306a36Sopenharmony_ci			if (get_unaligned(u1) != get_unaligned(u2))
68262306a36Sopenharmony_ci				break;
68362306a36Sopenharmony_ci			u1++;
68462306a36Sopenharmony_ci			u2++;
68562306a36Sopenharmony_ci			count -= sizeof(unsigned long);
68662306a36Sopenharmony_ci		} while (count >= sizeof(unsigned long));
68762306a36Sopenharmony_ci		cs = u1;
68862306a36Sopenharmony_ci		ct = u2;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci#endif
69162306a36Sopenharmony_ci	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
69262306a36Sopenharmony_ci		if ((res = *su1 - *su2) != 0)
69362306a36Sopenharmony_ci			break;
69462306a36Sopenharmony_ci	return res;
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ciEXPORT_SYMBOL(memcmp);
69762306a36Sopenharmony_ci#endif
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci#ifndef __HAVE_ARCH_BCMP
70062306a36Sopenharmony_ci/**
70162306a36Sopenharmony_ci * bcmp - returns 0 if and only if the buffers have identical contents.
70262306a36Sopenharmony_ci * @a: pointer to first buffer.
70362306a36Sopenharmony_ci * @b: pointer to second buffer.
70462306a36Sopenharmony_ci * @len: size of buffers.
70562306a36Sopenharmony_ci *
70662306a36Sopenharmony_ci * The sign or magnitude of a non-zero return value has no particular
70762306a36Sopenharmony_ci * meaning, and architectures may implement their own more efficient bcmp(). So
70862306a36Sopenharmony_ci * while this particular implementation is a simple (tail) call to memcmp, do
70962306a36Sopenharmony_ci * not rely on anything but whether the return value is zero or non-zero.
71062306a36Sopenharmony_ci */
71162306a36Sopenharmony_ciint bcmp(const void *a, const void *b, size_t len)
71262306a36Sopenharmony_ci{
71362306a36Sopenharmony_ci	return memcmp(a, b, len);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ciEXPORT_SYMBOL(bcmp);
71662306a36Sopenharmony_ci#endif
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMSCAN
71962306a36Sopenharmony_ci/**
72062306a36Sopenharmony_ci * memscan - Find a character in an area of memory.
72162306a36Sopenharmony_ci * @addr: The memory area
72262306a36Sopenharmony_ci * @c: The byte to search for
72362306a36Sopenharmony_ci * @size: The size of the area.
72462306a36Sopenharmony_ci *
72562306a36Sopenharmony_ci * returns the address of the first occurrence of @c, or 1 byte past
72662306a36Sopenharmony_ci * the area if @c is not found
72762306a36Sopenharmony_ci */
72862306a36Sopenharmony_civoid *memscan(void *addr, int c, size_t size)
72962306a36Sopenharmony_ci{
73062306a36Sopenharmony_ci	unsigned char *p = addr;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	while (size) {
73362306a36Sopenharmony_ci		if (*p == (unsigned char)c)
73462306a36Sopenharmony_ci			return (void *)p;
73562306a36Sopenharmony_ci		p++;
73662306a36Sopenharmony_ci		size--;
73762306a36Sopenharmony_ci	}
73862306a36Sopenharmony_ci  	return (void *)p;
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ciEXPORT_SYMBOL(memscan);
74162306a36Sopenharmony_ci#endif
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRSTR
74462306a36Sopenharmony_ci/**
74562306a36Sopenharmony_ci * strstr - Find the first substring in a %NUL terminated string
74662306a36Sopenharmony_ci * @s1: The string to be searched
74762306a36Sopenharmony_ci * @s2: The string to search for
74862306a36Sopenharmony_ci */
74962306a36Sopenharmony_cichar *strstr(const char *s1, const char *s2)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	size_t l1, l2;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	l2 = strlen(s2);
75462306a36Sopenharmony_ci	if (!l2)
75562306a36Sopenharmony_ci		return (char *)s1;
75662306a36Sopenharmony_ci	l1 = strlen(s1);
75762306a36Sopenharmony_ci	while (l1 >= l2) {
75862306a36Sopenharmony_ci		l1--;
75962306a36Sopenharmony_ci		if (!memcmp(s1, s2, l2))
76062306a36Sopenharmony_ci			return (char *)s1;
76162306a36Sopenharmony_ci		s1++;
76262306a36Sopenharmony_ci	}
76362306a36Sopenharmony_ci	return NULL;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ciEXPORT_SYMBOL(strstr);
76662306a36Sopenharmony_ci#endif
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci#ifndef __HAVE_ARCH_STRNSTR
76962306a36Sopenharmony_ci/**
77062306a36Sopenharmony_ci * strnstr - Find the first substring in a length-limited string
77162306a36Sopenharmony_ci * @s1: The string to be searched
77262306a36Sopenharmony_ci * @s2: The string to search for
77362306a36Sopenharmony_ci * @len: the maximum number of characters to search
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_cichar *strnstr(const char *s1, const char *s2, size_t len)
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	size_t l2;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	l2 = strlen(s2);
78062306a36Sopenharmony_ci	if (!l2)
78162306a36Sopenharmony_ci		return (char *)s1;
78262306a36Sopenharmony_ci	while (len >= l2) {
78362306a36Sopenharmony_ci		len--;
78462306a36Sopenharmony_ci		if (!memcmp(s1, s2, l2))
78562306a36Sopenharmony_ci			return (char *)s1;
78662306a36Sopenharmony_ci		s1++;
78762306a36Sopenharmony_ci	}
78862306a36Sopenharmony_ci	return NULL;
78962306a36Sopenharmony_ci}
79062306a36Sopenharmony_ciEXPORT_SYMBOL(strnstr);
79162306a36Sopenharmony_ci#endif
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci#ifndef __HAVE_ARCH_MEMCHR
79462306a36Sopenharmony_ci/**
79562306a36Sopenharmony_ci * memchr - Find a character in an area of memory.
79662306a36Sopenharmony_ci * @s: The memory area
79762306a36Sopenharmony_ci * @c: The byte to search for
79862306a36Sopenharmony_ci * @n: The size of the area.
79962306a36Sopenharmony_ci *
80062306a36Sopenharmony_ci * returns the address of the first occurrence of @c, or %NULL
80162306a36Sopenharmony_ci * if @c is not found
80262306a36Sopenharmony_ci */
80362306a36Sopenharmony_civoid *memchr(const void *s, int c, size_t n)
80462306a36Sopenharmony_ci{
80562306a36Sopenharmony_ci	const unsigned char *p = s;
80662306a36Sopenharmony_ci	while (n-- != 0) {
80762306a36Sopenharmony_ci        	if ((unsigned char)c == *p++) {
80862306a36Sopenharmony_ci			return (void *)(p - 1);
80962306a36Sopenharmony_ci		}
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci	return NULL;
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ciEXPORT_SYMBOL(memchr);
81462306a36Sopenharmony_ci#endif
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	while (bytes) {
81962306a36Sopenharmony_ci		if (*start != value)
82062306a36Sopenharmony_ci			return (void *)start;
82162306a36Sopenharmony_ci		start++;
82262306a36Sopenharmony_ci		bytes--;
82362306a36Sopenharmony_ci	}
82462306a36Sopenharmony_ci	return NULL;
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci/**
82862306a36Sopenharmony_ci * memchr_inv - Find an unmatching character in an area of memory.
82962306a36Sopenharmony_ci * @start: The memory area
83062306a36Sopenharmony_ci * @c: Find a character other than c
83162306a36Sopenharmony_ci * @bytes: The size of the area.
83262306a36Sopenharmony_ci *
83362306a36Sopenharmony_ci * returns the address of the first character other than @c, or %NULL
83462306a36Sopenharmony_ci * if the whole buffer contains just @c.
83562306a36Sopenharmony_ci */
83662306a36Sopenharmony_civoid *memchr_inv(const void *start, int c, size_t bytes)
83762306a36Sopenharmony_ci{
83862306a36Sopenharmony_ci	u8 value = c;
83962306a36Sopenharmony_ci	u64 value64;
84062306a36Sopenharmony_ci	unsigned int words, prefix;
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	if (bytes <= 16)
84362306a36Sopenharmony_ci		return check_bytes8(start, value, bytes);
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	value64 = value;
84662306a36Sopenharmony_ci#if defined(CONFIG_ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
84762306a36Sopenharmony_ci	value64 *= 0x0101010101010101ULL;
84862306a36Sopenharmony_ci#elif defined(CONFIG_ARCH_HAS_FAST_MULTIPLIER)
84962306a36Sopenharmony_ci	value64 *= 0x01010101;
85062306a36Sopenharmony_ci	value64 |= value64 << 32;
85162306a36Sopenharmony_ci#else
85262306a36Sopenharmony_ci	value64 |= value64 << 8;
85362306a36Sopenharmony_ci	value64 |= value64 << 16;
85462306a36Sopenharmony_ci	value64 |= value64 << 32;
85562306a36Sopenharmony_ci#endif
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	prefix = (unsigned long)start % 8;
85862306a36Sopenharmony_ci	if (prefix) {
85962306a36Sopenharmony_ci		u8 *r;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci		prefix = 8 - prefix;
86262306a36Sopenharmony_ci		r = check_bytes8(start, value, prefix);
86362306a36Sopenharmony_ci		if (r)
86462306a36Sopenharmony_ci			return r;
86562306a36Sopenharmony_ci		start += prefix;
86662306a36Sopenharmony_ci		bytes -= prefix;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	words = bytes / 8;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	while (words) {
87262306a36Sopenharmony_ci		if (*(u64 *)start != value64)
87362306a36Sopenharmony_ci			return check_bytes8(start, value, 8);
87462306a36Sopenharmony_ci		start += 8;
87562306a36Sopenharmony_ci		words--;
87662306a36Sopenharmony_ci	}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	return check_bytes8(start, value, bytes % 8);
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ciEXPORT_SYMBOL(memchr_inv);
881