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