197873a3dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
296ae6ea0SThomas Gleixner /* -*- linux-c -*- ------------------------------------------------------- *
396ae6ea0SThomas Gleixner *
496ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds
596ae6ea0SThomas Gleixner * Copyright 2007 rPath, Inc. - All Rights Reserved
696ae6ea0SThomas Gleixner *
796ae6ea0SThomas Gleixner * ----------------------------------------------------------------------- */
896ae6ea0SThomas Gleixner
996ae6ea0SThomas Gleixner /*
1096ae6ea0SThomas Gleixner * Very basic string functions
1196ae6ea0SThomas Gleixner */
1296ae6ea0SThomas Gleixner
133d379225SVivek Goyal #include <linux/types.h>
14a9c640acSNick Desaulniers #include <linux/compiler.h>
15de50ce20SChao Fan #include <linux/errno.h>
16a9c640acSNick Desaulniers #include <linux/limits.h>
17216a3720SUros Bizjak #include <asm/asm.h>
183d379225SVivek Goyal #include "ctype.h"
19fac69d0eSNicholas Mc Guire #include "string.h"
2096ae6ea0SThomas Gleixner
21de50ce20SChao Fan #define KSTRTOX_OVERFLOW (1U << 31)
22de50ce20SChao Fan
2318d5e6c3SMichael Davidson /*
2418d5e6c3SMichael Davidson * Undef these macros so that the functions that we provide
2518d5e6c3SMichael Davidson * here will have the correct names regardless of how string.h
2618d5e6c3SMichael Davidson * may have chosen to #define them.
2718d5e6c3SMichael Davidson */
2818d5e6c3SMichael Davidson #undef memcpy
2918d5e6c3SMichael Davidson #undef memset
3018d5e6c3SMichael Davidson #undef memcmp
3118d5e6c3SMichael Davidson
memcmp(const void * s1,const void * s2,size_t len)32fb4cac57SVivek Goyal int memcmp(const void *s1, const void *s2, size_t len)
33fb4cac57SVivek Goyal {
34117780eeSH. Peter Anvin bool diff;
35216a3720SUros Bizjak asm("repe; cmpsb" CC_SET(nz)
36216a3720SUros Bizjak : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));
37fb4cac57SVivek Goyal return diff;
38fb4cac57SVivek Goyal }
39fb4cac57SVivek Goyal
404ce97317SNick Desaulniers /*
414ce97317SNick Desaulniers * Clang may lower `memcmp == 0` to `bcmp == 0`.
424ce97317SNick Desaulniers */
bcmp(const void * s1,const void * s2,size_t len)434ce97317SNick Desaulniers int bcmp(const void *s1, const void *s2, size_t len)
444ce97317SNick Desaulniers {
454ce97317SNick Desaulniers return memcmp(s1, s2, len);
464ce97317SNick Desaulniers }
474ce97317SNick Desaulniers
strcmp(const char * str1,const char * str2)4896ae6ea0SThomas Gleixner int strcmp(const char *str1, const char *str2)
4996ae6ea0SThomas Gleixner {
5096ae6ea0SThomas Gleixner const unsigned char *s1 = (const unsigned char *)str1;
5196ae6ea0SThomas Gleixner const unsigned char *s2 = (const unsigned char *)str2;
5296ae6ea0SThomas Gleixner int delta = 0;
5396ae6ea0SThomas Gleixner
5496ae6ea0SThomas Gleixner while (*s1 || *s2) {
551c1d046bSArjun Sreedharan delta = *s1 - *s2;
5696ae6ea0SThomas Gleixner if (delta)
5796ae6ea0SThomas Gleixner return delta;
5896ae6ea0SThomas Gleixner s1++;
5996ae6ea0SThomas Gleixner s2++;
6096ae6ea0SThomas Gleixner }
6196ae6ea0SThomas Gleixner return 0;
6296ae6ea0SThomas Gleixner }
6396ae6ea0SThomas Gleixner
strncmp(const char * cs,const char * ct,size_t count)64fa97bdf9SPekka Enberg int strncmp(const char *cs, const char *ct, size_t count)
65fa97bdf9SPekka Enberg {
66fa97bdf9SPekka Enberg unsigned char c1, c2;
67fa97bdf9SPekka Enberg
68fa97bdf9SPekka Enberg while (count) {
69fa97bdf9SPekka Enberg c1 = *cs++;
70fa97bdf9SPekka Enberg c2 = *ct++;
71fa97bdf9SPekka Enberg if (c1 != c2)
72fa97bdf9SPekka Enberg return c1 < c2 ? -1 : 1;
73fa97bdf9SPekka Enberg if (!c1)
74fa97bdf9SPekka Enberg break;
75fa97bdf9SPekka Enberg count--;
76fa97bdf9SPekka Enberg }
77fa97bdf9SPekka Enberg return 0;
78fa97bdf9SPekka Enberg }
79fa97bdf9SPekka Enberg
strnlen(const char * s,size_t maxlen)8096ae6ea0SThomas Gleixner size_t strnlen(const char *s, size_t maxlen)
8196ae6ea0SThomas Gleixner {
8296ae6ea0SThomas Gleixner const char *es = s;
8396ae6ea0SThomas Gleixner while (*es && maxlen) {
8496ae6ea0SThomas Gleixner es++;
8596ae6ea0SThomas Gleixner maxlen--;
8696ae6ea0SThomas Gleixner }
8796ae6ea0SThomas Gleixner
8896ae6ea0SThomas Gleixner return (es - s);
8996ae6ea0SThomas Gleixner }
9096ae6ea0SThomas Gleixner
atou(const char * s)9196ae6ea0SThomas Gleixner unsigned int atou(const char *s)
9296ae6ea0SThomas Gleixner {
9396ae6ea0SThomas Gleixner unsigned int i = 0;
9496ae6ea0SThomas Gleixner while (isdigit(*s))
9596ae6ea0SThomas Gleixner i = i * 10 + (*s++ - '0');
9696ae6ea0SThomas Gleixner return i;
9796ae6ea0SThomas Gleixner }
98fa97bdf9SPekka Enberg
99fa97bdf9SPekka Enberg /* Works only for digits and letters, but small and fast */
100fa97bdf9SPekka Enberg #define TOLOWER(x) ((x) | 0x20)
101fa97bdf9SPekka Enberg
simple_guess_base(const char * cp)102ce0aa5ddSYinghai Lu static unsigned int simple_guess_base(const char *cp)
103ce0aa5ddSYinghai Lu {
104ce0aa5ddSYinghai Lu if (cp[0] == '0') {
105ce0aa5ddSYinghai Lu if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
106ce0aa5ddSYinghai Lu return 16;
107ce0aa5ddSYinghai Lu else
108ce0aa5ddSYinghai Lu return 8;
109ce0aa5ddSYinghai Lu } else {
110ce0aa5ddSYinghai Lu return 10;
111ce0aa5ddSYinghai Lu }
112ce0aa5ddSYinghai Lu }
113ce0aa5ddSYinghai Lu
114ce0aa5ddSYinghai Lu /**
115ce0aa5ddSYinghai Lu * simple_strtoull - convert a string to an unsigned long long
116ce0aa5ddSYinghai Lu * @cp: The start of the string
117ce0aa5ddSYinghai Lu * @endp: A pointer to the end of the parsed string will be placed here
118ce0aa5ddSYinghai Lu * @base: The number base to use
119ce0aa5ddSYinghai Lu */
simple_strtoull(const char * cp,char ** endp,unsigned int base)120fa97bdf9SPekka Enberg unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
121fa97bdf9SPekka Enberg {
122fa97bdf9SPekka Enberg unsigned long long result = 0;
123fa97bdf9SPekka Enberg
124ce0aa5ddSYinghai Lu if (!base)
125ce0aa5ddSYinghai Lu base = simple_guess_base(cp);
126ce0aa5ddSYinghai Lu
127fa97bdf9SPekka Enberg if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
128fa97bdf9SPekka Enberg cp += 2;
129fa97bdf9SPekka Enberg
130fa97bdf9SPekka Enberg while (isxdigit(*cp)) {
131fa97bdf9SPekka Enberg unsigned int value;
132fa97bdf9SPekka Enberg
133fa97bdf9SPekka Enberg value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
134fa97bdf9SPekka Enberg if (value >= base)
135fa97bdf9SPekka Enberg break;
136fa97bdf9SPekka Enberg result = result * base + value;
137fa97bdf9SPekka Enberg cp++;
138fa97bdf9SPekka Enberg }
139fa97bdf9SPekka Enberg if (endp)
140fa97bdf9SPekka Enberg *endp = (char *)cp;
141fa97bdf9SPekka Enberg
142fa97bdf9SPekka Enberg return result;
143fa97bdf9SPekka Enberg }
144291f3632SMatt Fleming
simple_strtol(const char * cp,char ** endp,unsigned int base)145d52e7d5aSBaoquan He long simple_strtol(const char *cp, char **endp, unsigned int base)
146d52e7d5aSBaoquan He {
147d52e7d5aSBaoquan He if (*cp == '-')
148d52e7d5aSBaoquan He return -simple_strtoull(cp + 1, endp, base);
149d52e7d5aSBaoquan He
150d52e7d5aSBaoquan He return simple_strtoull(cp, endp, base);
151d52e7d5aSBaoquan He }
152d52e7d5aSBaoquan He
153291f3632SMatt Fleming /**
154291f3632SMatt Fleming * strlen - Find the length of a string
155291f3632SMatt Fleming * @s: The string to be sized
156291f3632SMatt Fleming */
strlen(const char * s)157291f3632SMatt Fleming size_t strlen(const char *s)
158291f3632SMatt Fleming {
159291f3632SMatt Fleming const char *sc;
160291f3632SMatt Fleming
161291f3632SMatt Fleming for (sc = s; *sc != '\0'; ++sc)
162291f3632SMatt Fleming /* nothing */;
163291f3632SMatt Fleming return sc - s;
164291f3632SMatt Fleming }
165291f3632SMatt Fleming
166291f3632SMatt Fleming /**
167291f3632SMatt Fleming * strstr - Find the first substring in a %NUL terminated string
168291f3632SMatt Fleming * @s1: The string to be searched
169291f3632SMatt Fleming * @s2: The string to search for
170291f3632SMatt Fleming */
strstr(const char * s1,const char * s2)171291f3632SMatt Fleming char *strstr(const char *s1, const char *s2)
172291f3632SMatt Fleming {
173291f3632SMatt Fleming size_t l1, l2;
174291f3632SMatt Fleming
175291f3632SMatt Fleming l2 = strlen(s2);
176291f3632SMatt Fleming if (!l2)
177291f3632SMatt Fleming return (char *)s1;
178291f3632SMatt Fleming l1 = strlen(s1);
179291f3632SMatt Fleming while (l1 >= l2) {
180291f3632SMatt Fleming l1--;
181291f3632SMatt Fleming if (!memcmp(s1, s2, l2))
182291f3632SMatt Fleming return (char *)s1;
183291f3632SMatt Fleming s1++;
184291f3632SMatt Fleming }
185291f3632SMatt Fleming return NULL;
186291f3632SMatt Fleming }
187f2844249SDave Jiang
188f2844249SDave Jiang /**
189f2844249SDave Jiang * strchr - Find the first occurrence of the character c in the string s.
190f2844249SDave Jiang * @s: the string to be searched
191f2844249SDave Jiang * @c: the character to search for
192f2844249SDave Jiang */
strchr(const char * s,int c)193f2844249SDave Jiang char *strchr(const char *s, int c)
194f2844249SDave Jiang {
195f2844249SDave Jiang while (*s != (char)c)
196f2844249SDave Jiang if (*s++ == '\0')
197f2844249SDave Jiang return NULL;
198f2844249SDave Jiang return (char *)s;
199f2844249SDave Jiang }
200de50ce20SChao Fan
__div_u64_rem(u64 dividend,u32 divisor,u32 * remainder)201de50ce20SChao Fan static inline u64 __div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
202de50ce20SChao Fan {
203de50ce20SChao Fan union {
204de50ce20SChao Fan u64 v64;
205de50ce20SChao Fan u32 v32[2];
206de50ce20SChao Fan } d = { dividend };
207de50ce20SChao Fan u32 upper;
208de50ce20SChao Fan
209de50ce20SChao Fan upper = d.v32[1];
210de50ce20SChao Fan d.v32[1] = 0;
211de50ce20SChao Fan if (upper >= divisor) {
212de50ce20SChao Fan d.v32[1] = upper / divisor;
213de50ce20SChao Fan upper %= divisor;
214de50ce20SChao Fan }
215de50ce20SChao Fan asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) :
216de50ce20SChao Fan "rm" (divisor), "0" (d.v32[0]), "1" (upper));
217de50ce20SChao Fan return d.v64;
218de50ce20SChao Fan }
219de50ce20SChao Fan
__div_u64(u64 dividend,u32 divisor)220de50ce20SChao Fan static inline u64 __div_u64(u64 dividend, u32 divisor)
221de50ce20SChao Fan {
222de50ce20SChao Fan u32 remainder;
223de50ce20SChao Fan
224de50ce20SChao Fan return __div_u64_rem(dividend, divisor, &remainder);
225de50ce20SChao Fan }
226de50ce20SChao Fan
_tolower(const char c)227de50ce20SChao Fan static inline char _tolower(const char c)
228de50ce20SChao Fan {
229de50ce20SChao Fan return c | 0x20;
230de50ce20SChao Fan }
231de50ce20SChao Fan
_parse_integer_fixup_radix(const char * s,unsigned int * base)232de50ce20SChao Fan static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
233de50ce20SChao Fan {
234de50ce20SChao Fan if (*base == 0) {
235de50ce20SChao Fan if (s[0] == '0') {
236de50ce20SChao Fan if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
237de50ce20SChao Fan *base = 16;
238de50ce20SChao Fan else
239de50ce20SChao Fan *base = 8;
240de50ce20SChao Fan } else
241de50ce20SChao Fan *base = 10;
242de50ce20SChao Fan }
243de50ce20SChao Fan if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
244de50ce20SChao Fan s += 2;
245de50ce20SChao Fan return s;
246de50ce20SChao Fan }
247de50ce20SChao Fan
248de50ce20SChao Fan /*
249de50ce20SChao Fan * Convert non-negative integer string representation in explicitly given radix
250de50ce20SChao Fan * to an integer.
251de50ce20SChao Fan * Return number of characters consumed maybe or-ed with overflow bit.
252de50ce20SChao Fan * If overflow occurs, result integer (incorrect) is still returned.
253de50ce20SChao Fan *
254de50ce20SChao Fan * Don't you dare use this function.
255de50ce20SChao Fan */
_parse_integer(const char * s,unsigned int base,unsigned long long * p)256de50ce20SChao Fan static unsigned int _parse_integer(const char *s,
257de50ce20SChao Fan unsigned int base,
258de50ce20SChao Fan unsigned long long *p)
259de50ce20SChao Fan {
260de50ce20SChao Fan unsigned long long res;
261de50ce20SChao Fan unsigned int rv;
262de50ce20SChao Fan
263de50ce20SChao Fan res = 0;
264de50ce20SChao Fan rv = 0;
265de50ce20SChao Fan while (1) {
266de50ce20SChao Fan unsigned int c = *s;
267de50ce20SChao Fan unsigned int lc = c | 0x20; /* don't tolower() this line */
268de50ce20SChao Fan unsigned int val;
269de50ce20SChao Fan
270de50ce20SChao Fan if ('0' <= c && c <= '9')
271de50ce20SChao Fan val = c - '0';
272de50ce20SChao Fan else if ('a' <= lc && lc <= 'f')
273de50ce20SChao Fan val = lc - 'a' + 10;
274de50ce20SChao Fan else
275de50ce20SChao Fan break;
276de50ce20SChao Fan
277de50ce20SChao Fan if (val >= base)
278de50ce20SChao Fan break;
279de50ce20SChao Fan /*
280de50ce20SChao Fan * Check for overflow only if we are within range of
281de50ce20SChao Fan * it in the max base we support (16)
282de50ce20SChao Fan */
283de50ce20SChao Fan if (unlikely(res & (~0ull << 60))) {
284de50ce20SChao Fan if (res > __div_u64(ULLONG_MAX - val, base))
285de50ce20SChao Fan rv |= KSTRTOX_OVERFLOW;
286de50ce20SChao Fan }
287de50ce20SChao Fan res = res * base + val;
288de50ce20SChao Fan rv++;
289de50ce20SChao Fan s++;
290de50ce20SChao Fan }
291de50ce20SChao Fan *p = res;
292de50ce20SChao Fan return rv;
293de50ce20SChao Fan }
294de50ce20SChao Fan
_kstrtoull(const char * s,unsigned int base,unsigned long long * res)295de50ce20SChao Fan static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
296de50ce20SChao Fan {
297de50ce20SChao Fan unsigned long long _res;
298de50ce20SChao Fan unsigned int rv;
299de50ce20SChao Fan
300de50ce20SChao Fan s = _parse_integer_fixup_radix(s, &base);
301de50ce20SChao Fan rv = _parse_integer(s, base, &_res);
302de50ce20SChao Fan if (rv & KSTRTOX_OVERFLOW)
303de50ce20SChao Fan return -ERANGE;
304de50ce20SChao Fan if (rv == 0)
305de50ce20SChao Fan return -EINVAL;
306de50ce20SChao Fan s += rv;
307de50ce20SChao Fan if (*s == '\n')
308de50ce20SChao Fan s++;
309de50ce20SChao Fan if (*s)
310de50ce20SChao Fan return -EINVAL;
311de50ce20SChao Fan *res = _res;
312de50ce20SChao Fan return 0;
313de50ce20SChao Fan }
314de50ce20SChao Fan
315de50ce20SChao Fan /**
316de50ce20SChao Fan * kstrtoull - convert a string to an unsigned long long
317de50ce20SChao Fan * @s: The start of the string. The string must be null-terminated, and may also
318de50ce20SChao Fan * include a single newline before its terminating null. The first character
319de50ce20SChao Fan * may also be a plus sign, but not a minus sign.
320de50ce20SChao Fan * @base: The number base to use. The maximum supported base is 16. If base is
321de50ce20SChao Fan * given as 0, then the base of the string is automatically detected with the
322de50ce20SChao Fan * conventional semantics - If it begins with 0x the number will be parsed as a
323de50ce20SChao Fan * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
324de50ce20SChao Fan * parsed as an octal number. Otherwise it will be parsed as a decimal.
325de50ce20SChao Fan * @res: Where to write the result of the conversion on success.
326de50ce20SChao Fan *
327de50ce20SChao Fan * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
328de50ce20SChao Fan * Used as a replacement for the obsolete simple_strtoull. Return code must
329de50ce20SChao Fan * be checked.
330de50ce20SChao Fan */
kstrtoull(const char * s,unsigned int base,unsigned long long * res)331de50ce20SChao Fan int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
332de50ce20SChao Fan {
333de50ce20SChao Fan if (s[0] == '+')
334de50ce20SChao Fan s++;
335de50ce20SChao Fan return _kstrtoull(s, base, res);
336de50ce20SChao Fan }
3375fafbebcSVamshi K Sthambamkadi
_kstrtoul(const char * s,unsigned int base,unsigned long * res)3385fafbebcSVamshi K Sthambamkadi static int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
3395fafbebcSVamshi K Sthambamkadi {
3405fafbebcSVamshi K Sthambamkadi unsigned long long tmp;
3415fafbebcSVamshi K Sthambamkadi int rv;
3425fafbebcSVamshi K Sthambamkadi
3435fafbebcSVamshi K Sthambamkadi rv = kstrtoull(s, base, &tmp);
3445fafbebcSVamshi K Sthambamkadi if (rv < 0)
3455fafbebcSVamshi K Sthambamkadi return rv;
3465fafbebcSVamshi K Sthambamkadi if (tmp != (unsigned long)tmp)
3475fafbebcSVamshi K Sthambamkadi return -ERANGE;
3485fafbebcSVamshi K Sthambamkadi *res = tmp;
3495fafbebcSVamshi K Sthambamkadi return 0;
3505fafbebcSVamshi K Sthambamkadi }
3515fafbebcSVamshi K Sthambamkadi
3525fafbebcSVamshi K Sthambamkadi /**
353*d632bf6fSLukas Bulwahn * boot_kstrtoul - convert a string to an unsigned long
3545fafbebcSVamshi K Sthambamkadi * @s: The start of the string. The string must be null-terminated, and may also
3555fafbebcSVamshi K Sthambamkadi * include a single newline before its terminating null. The first character
3565fafbebcSVamshi K Sthambamkadi * may also be a plus sign, but not a minus sign.
3575fafbebcSVamshi K Sthambamkadi * @base: The number base to use. The maximum supported base is 16. If base is
3585fafbebcSVamshi K Sthambamkadi * given as 0, then the base of the string is automatically detected with the
3595fafbebcSVamshi K Sthambamkadi * conventional semantics - If it begins with 0x the number will be parsed as a
3605fafbebcSVamshi K Sthambamkadi * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
3615fafbebcSVamshi K Sthambamkadi * parsed as an octal number. Otherwise it will be parsed as a decimal.
3625fafbebcSVamshi K Sthambamkadi * @res: Where to write the result of the conversion on success.
3635fafbebcSVamshi K Sthambamkadi *
3645fafbebcSVamshi K Sthambamkadi * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
3655fafbebcSVamshi K Sthambamkadi * Used as a replacement for the simple_strtoull.
3665fafbebcSVamshi K Sthambamkadi */
boot_kstrtoul(const char * s,unsigned int base,unsigned long * res)3675fafbebcSVamshi K Sthambamkadi int boot_kstrtoul(const char *s, unsigned int base, unsigned long *res)
3685fafbebcSVamshi K Sthambamkadi {
3695fafbebcSVamshi K Sthambamkadi /*
3705fafbebcSVamshi K Sthambamkadi * We want to shortcut function call, but
3715fafbebcSVamshi K Sthambamkadi * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0.
3725fafbebcSVamshi K Sthambamkadi */
3735fafbebcSVamshi K Sthambamkadi if (sizeof(unsigned long) == sizeof(unsigned long long) &&
3745fafbebcSVamshi K Sthambamkadi __alignof__(unsigned long) == __alignof__(unsigned long long))
3755fafbebcSVamshi K Sthambamkadi return kstrtoull(s, base, (unsigned long long *)res);
3765fafbebcSVamshi K Sthambamkadi else
3775fafbebcSVamshi K Sthambamkadi return _kstrtoul(s, base, res);
3785fafbebcSVamshi K Sthambamkadi }
379