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