]> git.saurik.com Git - apple/xnu.git/blob - bsd/libkern/strtol.c
5050546a1b4750f9e137db2ba423da47237fb600
[apple/xnu.git] / bsd / libkern / strtol.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* Copyright (c) 1995 NeXT Computer, Inc. All rights reserved.
24 *
25 * strol.c - The functions strtol() & strtoul() are exported as public API
26 * via the header file ~driverkit/generalFuncs.h
27 *
28 * HISTORY
29 * 25-Oct-1995 Dean Reece at NeXT
30 * Created based on BSD4.4's strtol.c & strtoul.c.
31 * Removed dependency on _ctype_ by static versions of isupper()...
32 * Added support for "0b101..." binary constants.
33 * Commented out references to errno.
34 */
35
36 /*-
37 * Copyright (c) 1990, 1993
38 * The Regents of the University of California. All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 */
68
69
70 static inline int
71 isupper(char c)
72 {
73 return (c >= 'A' && c <= 'Z');
74 }
75
76 static inline int
77 isalpha(char c)
78 {
79 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
80 }
81
82
83 static inline int
84 isspace(char c)
85 {
86 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
87 }
88
89 static inline int
90 isdigit(char c)
91 {
92 return (c >= '0' && c <= '9');
93 }
94
95 /*
96 * Convert a string to a long integer.
97 *
98 * Ignores `locale' stuff. Assumes that the upper and lower case
99 * alphabets and digits are each contiguous.
100 */
101 long
102 strtol(nptr, endptr, base)
103 const char *nptr;
104 char **endptr;
105 register int base;
106 {
107 register const char *s = nptr;
108 register unsigned long acc;
109 register int c;
110 register unsigned long cutoff;
111 register int neg = 0, any, cutlim;
112
113 /*
114 * Skip white space and pick up leading +/- sign if any.
115 * If base is 0, allow 0x for hex and 0 for octal, else
116 * assume decimal; if base is already 16, allow 0x.
117 */
118 do {
119 c = *s++;
120 } while (isspace(c));
121 if (c == '-') {
122 neg = 1;
123 c = *s++;
124 } else if (c == '+')
125 c = *s++;
126 if ((base == 0 || base == 16) &&
127 c == '0' && (*s == 'x' || *s == 'X')) {
128 c = s[1];
129 s += 2;
130 base = 16;
131 } else if ((base == 0 || base == 2) &&
132 c == '0' && (*s == 'b' || *s == 'B')) {
133 c = s[1];
134 s += 2;
135 base = 2;
136 }
137 if (base == 0)
138 base = c == '0' ? 8 : 10;
139
140 /*
141 * Compute the cutoff value between legal numbers and illegal
142 * numbers. That is the largest legal value, divided by the
143 * base. An input number that is greater than this value, if
144 * followed by a legal input character, is too big. One that
145 * is equal to this value may be valid or not; the limit
146 * between valid and invalid numbers is then based on the last
147 * digit. For instance, if the range for longs is
148 * [-2147483648..2147483647] and the input base is 10,
149 * cutoff will be set to 214748364 and cutlim to either
150 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
151 * a value > 214748364, or equal but the next digit is > 7 (or 8),
152 * the number is too big, and we will return a range error.
153 *
154 * Set any if any `digits' consumed; make it negative to indicate
155 * overflow.
156 */
157 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
158 cutlim = cutoff % (unsigned long)base;
159 cutoff /= (unsigned long)base;
160 for (acc = 0, any = 0;; c = *s++) {
161 if (isdigit(c))
162 c -= '0';
163 else if (isalpha(c))
164 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
165 else
166 break;
167 if (c >= base)
168 break;
169 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
170 any = -1;
171 else {
172 any = 1;
173 acc *= base;
174 acc += c;
175 }
176 }
177 if (any < 0) {
178 acc = neg ? LONG_MIN : LONG_MAX;
179 // errno = ERANGE;
180 } else if (neg)
181 acc = -acc;
182 if (endptr != 0)
183 *endptr = (char *)(any ? s - 1 : nptr);
184 return (acc);
185 }
186
187 /*
188 * Convert a string to an unsigned long integer.
189 *
190 * Ignores `locale' stuff. Assumes that the upper and lower case
191 * alphabets and digits are each contiguous.
192 */
193 unsigned long
194 strtoul(nptr, endptr, base)
195 const char *nptr;
196 char **endptr;
197 register int base;
198 {
199 register const char *s = nptr;
200 register unsigned long acc;
201 register int c;
202 register unsigned long cutoff;
203 register int neg = 0, any, cutlim;
204
205 /*
206 * See strtol for comments as to the logic used.
207 */
208 do {
209 c = *s++;
210 } while (isspace(c));
211 if (c == '-') {
212 neg = 1;
213 c = *s++;
214 } else if (c == '+')
215 c = *s++;
216 if ((base == 0 || base == 16) &&
217 c == '0' && (*s == 'x' || *s == 'X')) {
218 c = s[1];
219 s += 2;
220 base = 16;
221 } else if ((base == 0 || base == 2) &&
222 c == '0' && (*s == 'b' || *s == 'B')) {
223 c = s[1];
224 s += 2;
225 base = 2;
226 }
227 if (base == 0)
228 base = c == '0' ? 8 : 10;
229 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
230 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
231 for (acc = 0, any = 0;; c = *s++) {
232 if (isdigit(c))
233 c -= '0';
234 else if (isalpha(c))
235 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
236 else
237 break;
238 if (c >= base)
239 break;
240 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
241 any = -1;
242 else {
243 any = 1;
244 acc *= base;
245 acc += c;
246 }
247 }
248 if (any < 0) {
249 acc = ULONG_MAX;
250 // errno = ERANGE;
251 } else if (neg)
252 acc = -acc;
253 if (endptr != 0)
254 *endptr = (char *)(any ? s - 1 : nptr);
255 return (acc);
256 }