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