Blame view

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