]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOStringFuncs.c
0e20f8c505fca6906d30ae4a8376d0748e5dd612
[apple/xnu.git] / iokit / Kernel / IOStringFuncs.c
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All rights reserved.
23 *
24 * strol.c - The functions strtol() & strtoul() are exported as public API
25 * via the header file ~driverkit/generalFuncs.h
26 *
27 * HISTORY
28 * 25-Oct-1995 Dean Reece at NeXT
29 * Created based on BSD4.4's strtol.c & strtoul.c.
30 * Removed dependency on _ctype_ by static versions of isupper()...
31 * Added support for "0b101..." binary constants.
32 * Commented out references to errno.
33 */
34
35 /*-
36 * Copyright (c) 1990, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the University of
50 * California, Berkeley and its contributors.
51 * 4. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 */
67
68 /*
69 #include <string.h>
70 #include <stdlib.h>
71 #include <limits.h>
72 */
73 #include <sys/types.h>
74 #include <stddef.h>
75 #include <machine/limits.h>
76
77 typedef int BOOL;
78
79 static inline BOOL
80 isupper(char c)
81 {
82 return (c >= 'A' && c <= 'Z');
83 }
84
85 static inline BOOL
86 isalpha(char c)
87 {
88 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
89 }
90
91
92 static inline BOOL
93 isspace(char c)
94 {
95 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
96 }
97
98 static inline BOOL
99 isdigit(char c)
100 {
101 return (c >= '0' && c <= '9');
102 }
103
104 /*
105 * Convert a string to a long integer.
106 *
107 * Ignores `locale' stuff. Assumes that the upper and lower case
108 * alphabets and digits are each contiguous.
109 */
110 long
111 strtol(nptr, endptr, base)
112 const char *nptr;
113 char **endptr;
114 register int base;
115 {
116 register const char *s = nptr;
117 register unsigned long acc;
118 register int c;
119 register unsigned long cutoff;
120 register int neg = 0, any, cutlim;
121
122 /*
123 * Skip white space and pick up leading +/- sign if any.
124 * If base is 0, allow 0x for hex and 0 for octal, else
125 * assume decimal; if base is already 16, allow 0x.
126 */
127 do {
128 c = *s++;
129 } while (isspace(c));
130 if (c == '-') {
131 neg = 1;
132 c = *s++;
133 } else if (c == '+')
134 c = *s++;
135 if ((base == 0 || base == 16) &&
136 c == '0' && (*s == 'x' || *s == 'X')) {
137 c = s[1];
138 s += 2;
139 base = 16;
140 } else if ((base == 0 || base == 2) &&
141 c == '0' && (*s == 'b' || *s == 'B')) {
142 c = s[1];
143 s += 2;
144 base = 2;
145 }
146 if (base == 0)
147 base = c == '0' ? 8 : 10;
148
149 /*
150 * Compute the cutoff value between legal numbers and illegal
151 * numbers. That is the largest legal value, divided by the
152 * base. An input number that is greater than this value, if
153 * followed by a legal input character, is too big. One that
154 * is equal to this value may be valid or not; the limit
155 * between valid and invalid numbers is then based on the last
156 * digit. For instance, if the range for longs is
157 * [-2147483648..2147483647] and the input base is 10,
158 * cutoff will be set to 214748364 and cutlim to either
159 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
160 * a value > 214748364, or equal but the next digit is > 7 (or 8),
161 * the number is too big, and we will return a range error.
162 *
163 * Set any if any `digits' consumed; make it negative to indicate
164 * overflow.
165 */
166 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
167 cutlim = cutoff % (unsigned long)base;
168 cutoff /= (unsigned long)base;
169 for (acc = 0, any = 0;; c = *s++) {
170 if (isdigit(c))
171 c -= '0';
172 else if (isalpha(c))
173 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
174 else
175 break;
176 if (c >= base)
177 break;
178 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
179 any = -1;
180 else {
181 any = 1;
182 acc *= base;
183 acc += c;
184 }
185 }
186 if (any < 0) {
187 acc = neg ? LONG_MIN : LONG_MAX;
188 // errno = ERANGE;
189 } else if (neg)
190 acc = -acc;
191 if (endptr != 0)
192 *endptr = (char *)(any ? s - 1 : nptr);
193 return (acc);
194 }
195
196 unsigned long
197 strtoul(nptr, endptr, base)
198 const char *nptr;
199 char **endptr;
200 register int base;
201 {
202 register const char *s = nptr;
203 register unsigned long acc;
204 register int c;
205 register unsigned long cutoff;
206 register int neg = 0, any, cutlim;
207
208 /*
209 * See strtol for comments as to the logic used.
210 */
211 do {
212 c = *s++;
213 } while (isspace(c));
214 if (c == '-') {
215 neg = 1;
216 c = *s++;
217 } else if (c == '+')
218 c = *s++;
219 if ((base == 0 || base == 16) &&
220 c == '0' && (*s == 'x' || *s == 'X')) {
221 c = s[1];
222 s += 2;
223 base = 16;
224 } else if ((base == 0 || base == 2) &&
225 c == '0' && (*s == 'b' || *s == 'B')) {
226 c = s[1];
227 s += 2;
228 base = 2;
229 }
230 if (base == 0)
231 base = c == '0' ? 8 : 10;
232 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
233 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
234 for (acc = 0, any = 0;; c = *s++) {
235 if (isdigit(c))
236 c -= '0';
237 else if (isalpha(c))
238 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
239 else
240 break;
241 if (c >= base)
242 break;
243 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
244 any = -1;
245 else {
246 any = 1;
247 acc *= base;
248 acc += c;
249 }
250 }
251 if (any < 0) {
252 acc = ULONG_MAX;
253 // errno = ERANGE;
254 } else if (neg)
255 acc = -acc;
256 if (endptr != 0)
257 *endptr = (char *)(any ? s - 1 : nptr);
258 return (acc);
259 }
260
261 /*
262 * Convert a string to a quad integer.
263 *
264 * Ignores `locale' stuff. Assumes that the upper and lower case
265 * alphabets and digits are each contiguous.
266 */
267 quad_t
268 strtoq(nptr, endptr, base)
269 const char *nptr;
270 char **endptr;
271 register int base;
272 {
273 register const char *s;
274 register u_quad_t acc;
275 register int c;
276 register u_quad_t qbase, cutoff;
277 register int neg, any, cutlim;
278
279 /*
280 * Skip white space and pick up leading +/- sign if any.
281 * If base is 0, allow 0x for hex and 0 for octal, else
282 * assume decimal; if base is already 16, allow 0x.
283 */
284 s = nptr;
285 do {
286 c = *s++;
287 } while (isspace(c));
288 if (c == '-') {
289 neg = 1;
290 c = *s++;
291 } else {
292 neg = 0;
293 if (c == '+')
294 c = *s++;
295 }
296 if ((base == 0 || base == 16) &&
297 c == '0' && (*s == 'x' || *s == 'X')) {
298 c = s[1];
299 s += 2;
300 base = 16;
301 }
302 if (base == 0)
303 base = c == '0' ? 8 : 10;
304
305 /*
306 * Compute the cutoff value between legal numbers and illegal
307 * numbers. That is the largest legal value, divided by the
308 * base. An input number that is greater than this value, if
309 * followed by a legal input character, is too big. One that
310 * is equal to this value may be valid or not; the limit
311 * between valid and invalid numbers is then based on the last
312 * digit. For instance, if the range for quads is
313 * [-9223372036854775808..9223372036854775807] and the input base
314 * is 10, cutoff will be set to 922337203685477580 and cutlim to
315 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
316 * accumulated a value > 922337203685477580, or equal but the
317 * next digit is > 7 (or 8), the number is too big, and we will
318 * return a range error.
319 *
320 * Set any if any `digits' consumed; make it negative to indicate
321 * overflow.
322 */
323 qbase = (unsigned)base;
324 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
325 cutlim = cutoff % qbase;
326 cutoff /= qbase;
327 for (acc = 0, any = 0;; c = *s++) {
328 if (isdigit(c))
329 c -= '0';
330 else if (isalpha(c))
331 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
332 else
333 break;
334 if (c >= base)
335 break;
336 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
337 any = -1;
338 else {
339 any = 1;
340 acc *= qbase;
341 acc += c;
342 }
343 }
344 if (any < 0) {
345 acc = neg ? QUAD_MIN : QUAD_MAX;
346 // errno = ERANGE;
347 } else if (neg)
348 acc = -acc;
349 if (endptr != 0)
350 *endptr = (char *)(any ? s - 1 : nptr);
351 return (acc);
352 }
353
354
355 /*
356 * Convert a string to an unsigned quad integer.
357 *
358 * Ignores `locale' stuff. Assumes that the upper and lower case
359 * alphabets and digits are each contiguous.
360 */
361 u_quad_t
362 strtouq(nptr, endptr, base)
363 const char *nptr;
364 char **endptr;
365 register int base;
366 {
367 register const char *s = nptr;
368 register u_quad_t acc;
369 register int c;
370 register u_quad_t qbase, cutoff;
371 register int neg, any, cutlim;
372
373 /*
374 * See strtoq for comments as to the logic used.
375 */
376 s = nptr;
377 do {
378 c = *s++;
379 } while (isspace(c));
380 if (c == '-') {
381 neg = 1;
382 c = *s++;
383 } else {
384 neg = 0;
385 if (c == '+')
386 c = *s++;
387 }
388 if ((base == 0 || base == 16) &&
389 c == '0' && (*s == 'x' || *s == 'X')) {
390 c = s[1];
391 s += 2;
392 base = 16;
393 }
394 if (base == 0)
395 base = c == '0' ? 8 : 10;
396 qbase = (unsigned)base;
397 cutoff = (u_quad_t)UQUAD_MAX / qbase;
398 cutlim = (u_quad_t)UQUAD_MAX % qbase;
399 for (acc = 0, any = 0;; c = *s++) {
400 if (isdigit(c))
401 c -= '0';
402 else if (isalpha(c))
403 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
404 else
405 break;
406 if (c >= base)
407 break;
408 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
409 any = -1;
410 else {
411 any = 1;
412 acc *= qbase;
413 acc += c;
414 }
415 }
416 if (any < 0) {
417 acc = UQUAD_MAX;
418 // errno = ERANGE;
419 } else if (neg)
420 acc = -acc;
421 if (endptr != 0)
422 *endptr = (char *)(any ? s - 1 : nptr);
423 return (acc);
424 }
425
426
427 /*
428 *
429 */
430
431 char *strchr(const char *str, int ch)
432 {
433 do {
434 if (*str == ch)
435 return((char *)str);
436 } while (*str++);
437 return ((char *) 0);
438 }
439
440 /*
441 *
442 */
443
444 char *
445 strncat(char *s1, const char *s2, unsigned long n)
446 {
447 char *os1;
448 int i = n;
449
450 os1 = s1;
451 while (*s1++)
452 ;
453 --s1;
454 while ((*s1++ = *s2++))
455 if (--i < 0) {
456 *--s1 = '\0';
457 break;
458 }
459 return(os1);
460 }