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