1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Taken from:
4 *  linux/lib/string.c
5 *
6 *  Copyright (C) 1991, 1992  Linus Torvalds
7 */
8
9#include <linux/ctype.h>
10#include <linux/kernel.h>
11#include <linux/types.h>
12#include <linux/string.h>
13
14#ifndef __HAVE_ARCH_STRSTR
15/**
16 * strstr - Find the first substring in a %NUL terminated string
17 * @s1: The string to be searched
18 * @s2: The string to search for
19 */
20char *strstr(const char *s1, const char *s2)
21{
22	size_t l1, l2;
23
24	l2 = strlen(s2);
25	if (!l2)
26		return (char *)s1;
27	l1 = strlen(s1);
28	while (l1 >= l2) {
29		l1--;
30		if (!memcmp(s1, s2, l2))
31			return (char *)s1;
32		s1++;
33	}
34	return NULL;
35}
36#endif
37
38#ifndef __HAVE_ARCH_STRNCMP
39/**
40 * strncmp - Compare two length-limited strings
41 * @cs: One string
42 * @ct: Another string
43 * @count: The maximum number of bytes to compare
44 */
45int strncmp(const char *cs, const char *ct, size_t count)
46{
47	unsigned char c1, c2;
48
49	while (count) {
50		c1 = *cs++;
51		c2 = *ct++;
52		if (c1 != c2)
53			return c1 < c2 ? -1 : 1;
54		if (!c1)
55			break;
56		count--;
57	}
58	return 0;
59}
60#endif
61
62/* Works only for digits and letters, but small and fast */
63#define TOLOWER(x) ((x) | 0x20)
64
65static unsigned int simple_guess_base(const char *cp)
66{
67	if (cp[0] == '0') {
68		if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
69			return 16;
70		else
71			return 8;
72	} else {
73		return 10;
74	}
75}
76
77/**
78 * simple_strtoull - convert a string to an unsigned long long
79 * @cp: The start of the string
80 * @endp: A pointer to the end of the parsed string will be placed here
81 * @base: The number base to use
82 */
83
84unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
85{
86	unsigned long long result = 0;
87
88	if (!base)
89		base = simple_guess_base(cp);
90
91	if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
92		cp += 2;
93
94	while (isxdigit(*cp)) {
95		unsigned int value;
96
97		value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
98		if (value >= base)
99			break;
100		result = result * base + value;
101		cp++;
102	}
103	if (endp)
104		*endp = (char *)cp;
105
106	return result;
107}
108
109long simple_strtol(const char *cp, char **endp, unsigned int base)
110{
111	if (*cp == '-')
112		return -simple_strtoull(cp + 1, endp, base);
113
114	return simple_strtoull(cp, endp, base);
115}
116