xref: /openbmc/u-boot/lib/strto.c (revision 14453fbfadc2f98ca35d6033140466c7a4b4947a)
1  /*
2   *  linux/lib/vsprintf.c
3   *
4   *  Copyright (C) 1991, 1992  Linus Torvalds
5   */
6  
7  /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8  /*
9   * Wirzenius wrote this portably, Torvalds fucked it up :-)
10   */
11  
12  #include <common.h>
13  #include <errno.h>
14  #include <linux/ctype.h>
15  
16  /* from lib/kstrtox.c */
17  static const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
18  {
19  	if (*base == 0) {
20  		if (s[0] == '0') {
21  			if (tolower(s[1]) == 'x' && isxdigit(s[2]))
22  				*base = 16;
23  			else
24  				*base = 8;
25  		} else
26  			*base = 10;
27  	}
28  	if (*base == 16 && s[0] == '0' && tolower(s[1]) == 'x')
29  		s += 2;
30  	return s;
31  }
32  
33  unsigned long simple_strtoul(const char *cp, char **endp,
34  				unsigned int base)
35  {
36  	unsigned long result = 0;
37  	unsigned long value;
38  
39  	cp = _parse_integer_fixup_radix(cp, &base);
40  
41  	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
42  	    ? toupper(*cp) : *cp)-'A'+10) < base) {
43  		result = result*base + value;
44  		cp++;
45  	}
46  
47  	if (endp)
48  		*endp = (char *)cp;
49  
50  	return result;
51  }
52  
53  int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
54  {
55  	char *tail;
56  	unsigned long val;
57  	size_t len;
58  
59  	*res = 0;
60  	len = strlen(cp);
61  	if (len == 0)
62  		return -EINVAL;
63  
64  	val = simple_strtoul(cp, &tail, base);
65  	if (tail == cp)
66  		return -EINVAL;
67  
68  	if ((*tail == '\0') ||
69  		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
70  		*res = val;
71  		return 0;
72  	}
73  
74  	return -EINVAL;
75  }
76  
77  long simple_strtol(const char *cp, char **endp, unsigned int base)
78  {
79  	if (*cp == '-')
80  		return -simple_strtoul(cp + 1, endp, base);
81  
82  	return simple_strtoul(cp, endp, base);
83  }
84  
85  unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
86  {
87  	unsigned long result = simple_strtoul(cp, endp, base);
88  	switch (tolower(**endp)) {
89  	case 'g':
90  		result *= 1024;
91  		/* fall through */
92  	case 'm':
93  		result *= 1024;
94  		/* fall through */
95  	case 'k':
96  		result *= 1024;
97  		(*endp)++;
98  		if (**endp == 'i')
99  			(*endp)++;
100  		if (**endp == 'B')
101  			(*endp)++;
102  	}
103  	return result;
104  }
105  
106  unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base)
107  {
108  	unsigned long long result = simple_strtoull(cp, endp, base);
109  	switch (tolower(**endp)) {
110  	case 'g':
111  		result *= 1024;
112  		/* fall through */
113  	case 'm':
114  		result *= 1024;
115  		/* fall through */
116  	case 'k':
117  		result *= 1024;
118  		(*endp)++;
119  		if (**endp == 'i')
120  			(*endp)++;
121  		if (**endp == 'B')
122  			(*endp)++;
123  	}
124  	return result;
125  }
126  
127  unsigned long long simple_strtoull(const char *cp, char **endp,
128  					unsigned int base)
129  {
130  	unsigned long long result = 0, value;
131  
132  	cp = _parse_integer_fixup_radix(cp, &base);
133  
134  	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp - '0'
135  		: (islower(*cp) ? toupper(*cp) : *cp) - 'A' + 10) < base) {
136  		result = result * base + value;
137  		cp++;
138  	}
139  
140  	if (endp)
141  		*endp = (char *) cp;
142  
143  	return result;
144  }
145  
146  long trailing_strtoln(const char *str, const char *end)
147  {
148  	const char *p;
149  
150  	if (!end)
151  		end = str + strlen(str);
152  	if (isdigit(end[-1])) {
153  		for (p = end - 1; p > str; p--) {
154  			if (!isdigit(*p))
155  				return simple_strtoul(p + 1, NULL, 10);
156  		}
157  	}
158  
159  	return -1;
160  }
161  
162  long trailing_strtol(const char *str)
163  {
164  	return trailing_strtoln(str, NULL);
165  }
166