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