18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/ctype.h>
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include <linux/errno.h>
58c2ecf20Sopenharmony_ci#undef CONFIG_KASAN
68c2ecf20Sopenharmony_ci#include "../lib/string.c"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ciint strncmp(const char *cs, const char *ct, size_t count)
98c2ecf20Sopenharmony_ci{
108c2ecf20Sopenharmony_ci	unsigned char c1, c2;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci	while (count) {
138c2ecf20Sopenharmony_ci		c1 = *cs++;
148c2ecf20Sopenharmony_ci		c2 = *ct++;
158c2ecf20Sopenharmony_ci		if (c1 != c2)
168c2ecf20Sopenharmony_ci			return c1 < c2 ? -1 : 1;
178c2ecf20Sopenharmony_ci		if (!c1)
188c2ecf20Sopenharmony_ci			break;
198c2ecf20Sopenharmony_ci		count--;
208c2ecf20Sopenharmony_ci	}
218c2ecf20Sopenharmony_ci	return 0;
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cichar *skip_spaces(const char *str)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	while (isspace(*str))
278c2ecf20Sopenharmony_ci		++str;
288c2ecf20Sopenharmony_ci	return (char *)str;
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cichar *strim(char *s)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	size_t size;
348c2ecf20Sopenharmony_ci	char *end;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	size = strlen(s);
378c2ecf20Sopenharmony_ci	if (!size)
388c2ecf20Sopenharmony_ci		return s;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	end = s + size - 1;
418c2ecf20Sopenharmony_ci	while (end >= s && isspace(*end))
428c2ecf20Sopenharmony_ci		end--;
438c2ecf20Sopenharmony_ci	*(end + 1) = '\0';
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	return skip_spaces(s);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* Works only for digits and letters, but small and fast */
498c2ecf20Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20)
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic unsigned int simple_guess_base(const char *cp)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	if (cp[0] == '0') {
548c2ecf20Sopenharmony_ci		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
558c2ecf20Sopenharmony_ci			return 16;
568c2ecf20Sopenharmony_ci		else
578c2ecf20Sopenharmony_ci			return 8;
588c2ecf20Sopenharmony_ci	} else {
598c2ecf20Sopenharmony_ci		return 10;
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/**
648c2ecf20Sopenharmony_ci * simple_strtoull - convert a string to an unsigned long long
658c2ecf20Sopenharmony_ci * @cp: The start of the string
668c2ecf20Sopenharmony_ci * @endp: A pointer to the end of the parsed string will be placed here
678c2ecf20Sopenharmony_ci * @base: The number base to use
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciunsigned long long simple_strtoull(const char *cp, char **endp,
718c2ecf20Sopenharmony_ci				   unsigned int base)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	unsigned long long result = 0;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	if (!base)
768c2ecf20Sopenharmony_ci		base = simple_guess_base(cp);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
798c2ecf20Sopenharmony_ci		cp += 2;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	while (isxdigit(*cp)) {
828c2ecf20Sopenharmony_ci		unsigned int value;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
858c2ecf20Sopenharmony_ci		if (value >= base)
868c2ecf20Sopenharmony_ci			break;
878c2ecf20Sopenharmony_ci		result = result * base + value;
888c2ecf20Sopenharmony_ci		cp++;
898c2ecf20Sopenharmony_ci	}
908c2ecf20Sopenharmony_ci	if (endp)
918c2ecf20Sopenharmony_ci		*endp = (char *)cp;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	return result;
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cilong simple_strtol(const char *cp, char **endp, unsigned int base)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	if (*cp == '-')
998c2ecf20Sopenharmony_ci		return -simple_strtoull(cp + 1, endp, base);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return simple_strtoull(cp, endp, base);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciint kstrtobool(const char *s, bool *res)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	if (!s)
1078c2ecf20Sopenharmony_ci		return -EINVAL;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	switch (s[0]) {
1108c2ecf20Sopenharmony_ci	case 'y':
1118c2ecf20Sopenharmony_ci	case 'Y':
1128c2ecf20Sopenharmony_ci	case '1':
1138c2ecf20Sopenharmony_ci		*res = true;
1148c2ecf20Sopenharmony_ci		return 0;
1158c2ecf20Sopenharmony_ci	case 'n':
1168c2ecf20Sopenharmony_ci	case 'N':
1178c2ecf20Sopenharmony_ci	case '0':
1188c2ecf20Sopenharmony_ci		*res = false;
1198c2ecf20Sopenharmony_ci		return 0;
1208c2ecf20Sopenharmony_ci	case 'o':
1218c2ecf20Sopenharmony_ci	case 'O':
1228c2ecf20Sopenharmony_ci		switch (s[1]) {
1238c2ecf20Sopenharmony_ci		case 'n':
1248c2ecf20Sopenharmony_ci		case 'N':
1258c2ecf20Sopenharmony_ci			*res = true;
1268c2ecf20Sopenharmony_ci			return 0;
1278c2ecf20Sopenharmony_ci		case 'f':
1288c2ecf20Sopenharmony_ci		case 'F':
1298c2ecf20Sopenharmony_ci			*res = false;
1308c2ecf20Sopenharmony_ci			return 0;
1318c2ecf20Sopenharmony_ci		default:
1328c2ecf20Sopenharmony_ci			break;
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci	default:
1358c2ecf20Sopenharmony_ci		break;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	return -EINVAL;
1398c2ecf20Sopenharmony_ci}
140