162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 562306a36Sopenharmony_ci * Copyright 2007 rPath, Inc. - All Rights Reserved 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * ----------------------------------------------------------------------- */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci * Very basic string functions 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <linux/compiler.h> 1562306a36Sopenharmony_ci#include <linux/errno.h> 1662306a36Sopenharmony_ci#include <linux/limits.h> 1762306a36Sopenharmony_ci#include <asm/asm.h> 1862306a36Sopenharmony_ci#include "ctype.h" 1962306a36Sopenharmony_ci#include "string.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define KSTRTOX_OVERFLOW (1U << 31) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * Undef these macros so that the functions that we provide 2562306a36Sopenharmony_ci * here will have the correct names regardless of how string.h 2662306a36Sopenharmony_ci * may have chosen to #define them. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci#undef memcpy 2962306a36Sopenharmony_ci#undef memset 3062306a36Sopenharmony_ci#undef memcmp 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciint memcmp(const void *s1, const void *s2, size_t len) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci bool diff; 3562306a36Sopenharmony_ci asm("repe; cmpsb" CC_SET(nz) 3662306a36Sopenharmony_ci : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len)); 3762306a36Sopenharmony_ci return diff; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * Clang may lower `memcmp == 0` to `bcmp == 0`. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ciint bcmp(const void *s1, const void *s2, size_t len) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return memcmp(s1, s2, len); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciint strcmp(const char *str1, const char *str2) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci const unsigned char *s1 = (const unsigned char *)str1; 5162306a36Sopenharmony_ci const unsigned char *s2 = (const unsigned char *)str2; 5262306a36Sopenharmony_ci int delta = 0; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci while (*s1 || *s2) { 5562306a36Sopenharmony_ci delta = *s1 - *s2; 5662306a36Sopenharmony_ci if (delta) 5762306a36Sopenharmony_ci return delta; 5862306a36Sopenharmony_ci s1++; 5962306a36Sopenharmony_ci s2++; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint strncmp(const char *cs, const char *ct, size_t count) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci unsigned char c1, c2; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci while (count) { 6962306a36Sopenharmony_ci c1 = *cs++; 7062306a36Sopenharmony_ci c2 = *ct++; 7162306a36Sopenharmony_ci if (c1 != c2) 7262306a36Sopenharmony_ci return c1 < c2 ? -1 : 1; 7362306a36Sopenharmony_ci if (!c1) 7462306a36Sopenharmony_ci break; 7562306a36Sopenharmony_ci count--; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci return 0; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cisize_t strnlen(const char *s, size_t maxlen) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci const char *es = s; 8362306a36Sopenharmony_ci while (*es && maxlen) { 8462306a36Sopenharmony_ci es++; 8562306a36Sopenharmony_ci maxlen--; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return (es - s); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ciunsigned int atou(const char *s) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci unsigned int i = 0; 9462306a36Sopenharmony_ci while (isdigit(*s)) 9562306a36Sopenharmony_ci i = i * 10 + (*s++ - '0'); 9662306a36Sopenharmony_ci return i; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* Works only for digits and letters, but small and fast */ 10062306a36Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic unsigned int simple_guess_base(const char *cp) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci if (cp[0] == '0') { 10562306a36Sopenharmony_ci if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2])) 10662306a36Sopenharmony_ci return 16; 10762306a36Sopenharmony_ci else 10862306a36Sopenharmony_ci return 8; 10962306a36Sopenharmony_ci } else { 11062306a36Sopenharmony_ci return 10; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * simple_strtoull - convert a string to an unsigned long long 11662306a36Sopenharmony_ci * @cp: The start of the string 11762306a36Sopenharmony_ci * @endp: A pointer to the end of the parsed string will be placed here 11862306a36Sopenharmony_ci * @base: The number base to use 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ciunsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci unsigned long long result = 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (!base) 12562306a36Sopenharmony_ci base = simple_guess_base(cp); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') 12862306a36Sopenharmony_ci cp += 2; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci while (isxdigit(*cp)) { 13162306a36Sopenharmony_ci unsigned int value; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; 13462306a36Sopenharmony_ci if (value >= base) 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci result = result * base + value; 13762306a36Sopenharmony_ci cp++; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci if (endp) 14062306a36Sopenharmony_ci *endp = (char *)cp; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return result; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cilong simple_strtol(const char *cp, char **endp, unsigned int base) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci if (*cp == '-') 14862306a36Sopenharmony_ci return -simple_strtoull(cp + 1, endp, base); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return simple_strtoull(cp, endp, base); 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/** 15462306a36Sopenharmony_ci * strlen - Find the length of a string 15562306a36Sopenharmony_ci * @s: The string to be sized 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cisize_t strlen(const char *s) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci const char *sc; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci for (sc = s; *sc != '\0'; ++sc) 16262306a36Sopenharmony_ci /* nothing */; 16362306a36Sopenharmony_ci return sc - s; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/** 16762306a36Sopenharmony_ci * strstr - Find the first substring in a %NUL terminated string 16862306a36Sopenharmony_ci * @s1: The string to be searched 16962306a36Sopenharmony_ci * @s2: The string to search for 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cichar *strstr(const char *s1, const char *s2) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci size_t l1, l2; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci l2 = strlen(s2); 17662306a36Sopenharmony_ci if (!l2) 17762306a36Sopenharmony_ci return (char *)s1; 17862306a36Sopenharmony_ci l1 = strlen(s1); 17962306a36Sopenharmony_ci while (l1 >= l2) { 18062306a36Sopenharmony_ci l1--; 18162306a36Sopenharmony_ci if (!memcmp(s1, s2, l2)) 18262306a36Sopenharmony_ci return (char *)s1; 18362306a36Sopenharmony_ci s1++; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci return NULL; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci/** 18962306a36Sopenharmony_ci * strchr - Find the first occurrence of the character c in the string s. 19062306a36Sopenharmony_ci * @s: the string to be searched 19162306a36Sopenharmony_ci * @c: the character to search for 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_cichar *strchr(const char *s, int c) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci while (*s != (char)c) 19662306a36Sopenharmony_ci if (*s++ == '\0') 19762306a36Sopenharmony_ci return NULL; 19862306a36Sopenharmony_ci return (char *)s; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic inline u64 __div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci union { 20462306a36Sopenharmony_ci u64 v64; 20562306a36Sopenharmony_ci u32 v32[2]; 20662306a36Sopenharmony_ci } d = { dividend }; 20762306a36Sopenharmony_ci u32 upper; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci upper = d.v32[1]; 21062306a36Sopenharmony_ci d.v32[1] = 0; 21162306a36Sopenharmony_ci if (upper >= divisor) { 21262306a36Sopenharmony_ci d.v32[1] = upper / divisor; 21362306a36Sopenharmony_ci upper %= divisor; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) : 21662306a36Sopenharmony_ci "rm" (divisor), "0" (d.v32[0]), "1" (upper)); 21762306a36Sopenharmony_ci return d.v64; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic inline u64 __div_u64(u64 dividend, u32 divisor) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci u32 remainder; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return __div_u64_rem(dividend, divisor, &remainder); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic inline char _tolower(const char c) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci return c | 0x20; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci if (*base == 0) { 23562306a36Sopenharmony_ci if (s[0] == '0') { 23662306a36Sopenharmony_ci if (_tolower(s[1]) == 'x' && isxdigit(s[2])) 23762306a36Sopenharmony_ci *base = 16; 23862306a36Sopenharmony_ci else 23962306a36Sopenharmony_ci *base = 8; 24062306a36Sopenharmony_ci } else 24162306a36Sopenharmony_ci *base = 10; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x') 24462306a36Sopenharmony_ci s += 2; 24562306a36Sopenharmony_ci return s; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* 24962306a36Sopenharmony_ci * Convert non-negative integer string representation in explicitly given radix 25062306a36Sopenharmony_ci * to an integer. 25162306a36Sopenharmony_ci * Return number of characters consumed maybe or-ed with overflow bit. 25262306a36Sopenharmony_ci * If overflow occurs, result integer (incorrect) is still returned. 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * Don't you dare use this function. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_cistatic unsigned int _parse_integer(const char *s, 25762306a36Sopenharmony_ci unsigned int base, 25862306a36Sopenharmony_ci unsigned long long *p) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci unsigned long long res; 26162306a36Sopenharmony_ci unsigned int rv; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci res = 0; 26462306a36Sopenharmony_ci rv = 0; 26562306a36Sopenharmony_ci while (1) { 26662306a36Sopenharmony_ci unsigned int c = *s; 26762306a36Sopenharmony_ci unsigned int lc = c | 0x20; /* don't tolower() this line */ 26862306a36Sopenharmony_ci unsigned int val; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if ('0' <= c && c <= '9') 27162306a36Sopenharmony_ci val = c - '0'; 27262306a36Sopenharmony_ci else if ('a' <= lc && lc <= 'f') 27362306a36Sopenharmony_ci val = lc - 'a' + 10; 27462306a36Sopenharmony_ci else 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (val >= base) 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci /* 28062306a36Sopenharmony_ci * Check for overflow only if we are within range of 28162306a36Sopenharmony_ci * it in the max base we support (16) 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_ci if (unlikely(res & (~0ull << 60))) { 28462306a36Sopenharmony_ci if (res > __div_u64(ULLONG_MAX - val, base)) 28562306a36Sopenharmony_ci rv |= KSTRTOX_OVERFLOW; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci res = res * base + val; 28862306a36Sopenharmony_ci rv++; 28962306a36Sopenharmony_ci s++; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci *p = res; 29262306a36Sopenharmony_ci return rv; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci unsigned long long _res; 29862306a36Sopenharmony_ci unsigned int rv; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci s = _parse_integer_fixup_radix(s, &base); 30162306a36Sopenharmony_ci rv = _parse_integer(s, base, &_res); 30262306a36Sopenharmony_ci if (rv & KSTRTOX_OVERFLOW) 30362306a36Sopenharmony_ci return -ERANGE; 30462306a36Sopenharmony_ci if (rv == 0) 30562306a36Sopenharmony_ci return -EINVAL; 30662306a36Sopenharmony_ci s += rv; 30762306a36Sopenharmony_ci if (*s == '\n') 30862306a36Sopenharmony_ci s++; 30962306a36Sopenharmony_ci if (*s) 31062306a36Sopenharmony_ci return -EINVAL; 31162306a36Sopenharmony_ci *res = _res; 31262306a36Sopenharmony_ci return 0; 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/** 31662306a36Sopenharmony_ci * kstrtoull - convert a string to an unsigned long long 31762306a36Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 31862306a36Sopenharmony_ci * include a single newline before its terminating null. The first character 31962306a36Sopenharmony_ci * may also be a plus sign, but not a minus sign. 32062306a36Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 32162306a36Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 32262306a36Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 32362306a36Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 32462306a36Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 32562306a36Sopenharmony_ci * @res: Where to write the result of the conversion on success. 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 32862306a36Sopenharmony_ci * Used as a replacement for the obsolete simple_strtoull. Return code must 32962306a36Sopenharmony_ci * be checked. 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_ciint kstrtoull(const char *s, unsigned int base, unsigned long long *res) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci if (s[0] == '+') 33462306a36Sopenharmony_ci s++; 33562306a36Sopenharmony_ci return _kstrtoull(s, base, res); 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic int _kstrtoul(const char *s, unsigned int base, unsigned long *res) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci unsigned long long tmp; 34162306a36Sopenharmony_ci int rv; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci rv = kstrtoull(s, base, &tmp); 34462306a36Sopenharmony_ci if (rv < 0) 34562306a36Sopenharmony_ci return rv; 34662306a36Sopenharmony_ci if (tmp != (unsigned long)tmp) 34762306a36Sopenharmony_ci return -ERANGE; 34862306a36Sopenharmony_ci *res = tmp; 34962306a36Sopenharmony_ci return 0; 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/** 35362306a36Sopenharmony_ci * boot_kstrtoul - convert a string to an unsigned long 35462306a36Sopenharmony_ci * @s: The start of the string. The string must be null-terminated, and may also 35562306a36Sopenharmony_ci * include a single newline before its terminating null. The first character 35662306a36Sopenharmony_ci * may also be a plus sign, but not a minus sign. 35762306a36Sopenharmony_ci * @base: The number base to use. The maximum supported base is 16. If base is 35862306a36Sopenharmony_ci * given as 0, then the base of the string is automatically detected with the 35962306a36Sopenharmony_ci * conventional semantics - If it begins with 0x the number will be parsed as a 36062306a36Sopenharmony_ci * hexadecimal (case insensitive), if it otherwise begins with 0, it will be 36162306a36Sopenharmony_ci * parsed as an octal number. Otherwise it will be parsed as a decimal. 36262306a36Sopenharmony_ci * @res: Where to write the result of the conversion on success. 36362306a36Sopenharmony_ci * 36462306a36Sopenharmony_ci * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. 36562306a36Sopenharmony_ci * Used as a replacement for the simple_strtoull. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ciint boot_kstrtoul(const char *s, unsigned int base, unsigned long *res) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci /* 37062306a36Sopenharmony_ci * We want to shortcut function call, but 37162306a36Sopenharmony_ci * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci if (sizeof(unsigned long) == sizeof(unsigned long long) && 37462306a36Sopenharmony_ci __alignof__(unsigned long) == __alignof__(unsigned long long)) 37562306a36Sopenharmony_ci return kstrtoull(s, base, (unsigned long long *)res); 37662306a36Sopenharmony_ci else 37762306a36Sopenharmony_ci return _kstrtoul(s, base, res); 37862306a36Sopenharmony_ci} 379