GNU Linux-libre 4.19.245-gnu1
[releases.git] / arch / x86 / boot / string.c
1 /* -*- linux-c -*- ------------------------------------------------------- *
2  *
3  *   Copyright (C) 1991, 1992 Linus Torvalds
4  *   Copyright 2007 rPath, Inc. - All Rights Reserved
5  *
6  *   This file is part of the Linux kernel, and is made available under
7  *   the terms of the GNU General Public License version 2.
8  *
9  * ----------------------------------------------------------------------- */
10
11 /*
12  * Very basic string functions
13  */
14
15 #include <linux/types.h>
16 #include <asm/asm.h>
17 #include "ctype.h"
18 #include "string.h"
19
20 /*
21  * Undef these macros so that the functions that we provide
22  * here will have the correct names regardless of how string.h
23  * may have chosen to #define them.
24  */
25 #undef memcpy
26 #undef memset
27 #undef memcmp
28
29 int memcmp(const void *s1, const void *s2, size_t len)
30 {
31         bool diff;
32         asm("repe; cmpsb" CC_SET(nz)
33             : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));
34         return diff;
35 }
36
37 /*
38  * Clang may lower `memcmp == 0` to `bcmp == 0`.
39  */
40 int bcmp(const void *s1, const void *s2, size_t len)
41 {
42         return memcmp(s1, s2, len);
43 }
44
45 int strcmp(const char *str1, const char *str2)
46 {
47         const unsigned char *s1 = (const unsigned char *)str1;
48         const unsigned char *s2 = (const unsigned char *)str2;
49         int delta = 0;
50
51         while (*s1 || *s2) {
52                 delta = *s1 - *s2;
53                 if (delta)
54                         return delta;
55                 s1++;
56                 s2++;
57         }
58         return 0;
59 }
60
61 int strncmp(const char *cs, const char *ct, size_t count)
62 {
63         unsigned char c1, c2;
64
65         while (count) {
66                 c1 = *cs++;
67                 c2 = *ct++;
68                 if (c1 != c2)
69                         return c1 < c2 ? -1 : 1;
70                 if (!c1)
71                         break;
72                 count--;
73         }
74         return 0;
75 }
76
77 size_t strnlen(const char *s, size_t maxlen)
78 {
79         const char *es = s;
80         while (*es && maxlen) {
81                 es++;
82                 maxlen--;
83         }
84
85         return (es - s);
86 }
87
88 unsigned int atou(const char *s)
89 {
90         unsigned int i = 0;
91         while (isdigit(*s))
92                 i = i * 10 + (*s++ - '0');
93         return i;
94 }
95
96 /* Works only for digits and letters, but small and fast */
97 #define TOLOWER(x) ((x) | 0x20)
98
99 static unsigned int simple_guess_base(const char *cp)
100 {
101         if (cp[0] == '0') {
102                 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
103                         return 16;
104                 else
105                         return 8;
106         } else {
107                 return 10;
108         }
109 }
110
111 /**
112  * simple_strtoull - convert a string to an unsigned long long
113  * @cp: The start of the string
114  * @endp: A pointer to the end of the parsed string will be placed here
115  * @base: The number base to use
116  */
117
118 unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
119 {
120         unsigned long long result = 0;
121
122         if (!base)
123                 base = simple_guess_base(cp);
124
125         if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
126                 cp += 2;
127
128         while (isxdigit(*cp)) {
129                 unsigned int value;
130
131                 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
132                 if (value >= base)
133                         break;
134                 result = result * base + value;
135                 cp++;
136         }
137         if (endp)
138                 *endp = (char *)cp;
139
140         return result;
141 }
142
143 long simple_strtol(const char *cp, char **endp, unsigned int base)
144 {
145         if (*cp == '-')
146                 return -simple_strtoull(cp + 1, endp, base);
147
148         return simple_strtoull(cp, endp, base);
149 }
150
151 /**
152  * strlen - Find the length of a string
153  * @s: The string to be sized
154  */
155 size_t strlen(const char *s)
156 {
157         const char *sc;
158
159         for (sc = s; *sc != '\0'; ++sc)
160                 /* nothing */;
161         return sc - s;
162 }
163
164 /**
165  * strstr - Find the first substring in a %NUL terminated string
166  * @s1: The string to be searched
167  * @s2: The string to search for
168  */
169 char *strstr(const char *s1, const char *s2)
170 {
171         size_t l1, l2;
172
173         l2 = strlen(s2);
174         if (!l2)
175                 return (char *)s1;
176         l1 = strlen(s1);
177         while (l1 >= l2) {
178                 l1--;
179                 if (!memcmp(s1, s2, l2))
180                         return (char *)s1;
181                 s1++;
182         }
183         return NULL;
184 }
185
186 /**
187  * strchr - Find the first occurrence of the character c in the string s.
188  * @s: the string to be searched
189  * @c: the character to search for
190  */
191 char *strchr(const char *s, int c)
192 {
193         while (*s != (char)c)
194                 if (*s++ == '\0')
195                         return NULL;
196         return (char *)s;
197 }