]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOStringFuncs.c
e3742c96463b81f8d9dbf0bbbd41bd4e4ad396d8
[apple/xnu.git] / iokit / Kernel / IOStringFuncs.c
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
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 typedef int BOOL;
85
86 static inline BOOL
87 isupper(char c)
88 {
89 return (c >= 'A' && c <= 'Z');
90 }
91
92 static inline BOOL
93 isalpha(char c)
94 {
95 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
96 }
97
98
99 static inline BOOL
100 isspace(char c)
101 {
102 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
103 }
104
105 static inline BOOL
106 isdigit(char c)
107 {
108 return (c >= '0' && c <= '9');
109 }
110
111 /*
112 * Convert a string to a long integer.
113 *
114 * Ignores `locale' stuff. Assumes that the upper and lower case
115 * alphabets and digits are each contiguous.
116 */
117 long
118 strtol(nptr, endptr, base)
119 const char *nptr;
120 char **endptr;
121 register int base;
122 {
123 register const char *s = nptr;
124 register unsigned long acc;
125 register int c;
126 register unsigned long cutoff;
127 register int neg = 0, any, cutlim;
128
129 /*
130 * Skip white space and pick up leading +/- sign if any.
131 * If base is 0, allow 0x for hex and 0 for octal, else
132 * assume decimal; if base is already 16, allow 0x.
133 */
134 do {
135 c = *s++;
136 } while (isspace(c));
137 if (c == '-') {
138 neg = 1;
139 c = *s++;
140 } else if (c == '+')
141 c = *s++;
142 if ((base == 0 || base == 16) &&
143 c == '0' && (*s == 'x' || *s == 'X')) {
144 c = s[1];
145 s += 2;
146 base = 16;
147 } else if ((base == 0 || base == 2) &&
148 c == '0' && (*s == 'b' || *s == 'B')) {
149 c = s[1];
150 s += 2;
151 base = 2;
152 }
153 if (base == 0)
154 base = c == '0' ? 8 : 10;
155
156 /*
157 * Compute the cutoff value between legal numbers and illegal
158 * numbers. That is the largest legal value, divided by the
159 * base. An input number that is greater than this value, if
160 * followed by a legal input character, is too big. One that
161 * is equal to this value may be valid or not; the limit
162 * between valid and invalid numbers is then based on the last
163 * digit. For instance, if the range for longs is
164 * [-2147483648..2147483647] and the input base is 10,
165 * cutoff will be set to 214748364 and cutlim to either
166 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
167 * a value > 214748364, or equal but the next digit is > 7 (or 8),
168 * the number is too big, and we will return a range error.
169 *
170 * Set any if any `digits' consumed; make it negative to indicate
171 * overflow.
172 */
173 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
174 cutlim = cutoff % (unsigned long)base;
175 cutoff /= (unsigned long)base;
176 for (acc = 0, any = 0;; c = *s++) {
177 if (isdigit(c))
178 c -= '0';
179 else if (isalpha(c))
180 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
181 else
182 break;
183 if (c >= base)
184 break;
185 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
186 any = -1;
187 else {
188 any = 1;
189 acc *= base;
190 acc += c;
191 }
192 }
193 if (any < 0) {
194 acc = neg ? LONG_MIN : LONG_MAX;
195 // errno = ERANGE;
196 } else if (neg)
197 acc = -acc;
198 if (endptr != 0)
199 *endptr = (char *)(any ? s - 1 : nptr);
200 return (acc);
201 }
202
203 unsigned long
204 strtoul(nptr, endptr, base)
205 const char *nptr;
206 char **endptr;
207 register int base;
208 {
209 register const char *s = nptr;
210 register unsigned long acc;
211 register int c;
212 register unsigned long cutoff;
213 register int neg = 0, any, cutlim;
214
215 /*
216 * See strtol for comments as to the logic used.
217 */
218 do {
219 c = *s++;
220 } while (isspace(c));
221 if (c == '-') {
222 neg = 1;
223 c = *s++;
224 } else if (c == '+')
225 c = *s++;
226 if ((base == 0 || base == 16) &&
227 c == '0' && (*s == 'x' || *s == 'X')) {
228 c = s[1];
229 s += 2;
230 base = 16;
231 } else if ((base == 0 || base == 2) &&
232 c == '0' && (*s == 'b' || *s == 'B')) {
233 c = s[1];
234 s += 2;
235 base = 2;
236 }
237 if (base == 0)
238 base = c == '0' ? 8 : 10;
239 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
240 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
241 for (acc = 0, any = 0;; c = *s++) {
242 if (isdigit(c))
243 c -= '0';
244 else if (isalpha(c))
245 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
246 else
247 break;
248 if (c >= base)
249 break;
250 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) )
251 any = -1;
252 else {
253 any = 1;
254 acc *= base;
255 acc += c;
256 }
257 }
258 if (any < 0) {
259 acc = ULONG_MAX;
260 // errno = ERANGE;
261 } else if (neg)
262 acc = -acc;
263 if (endptr != 0)
264 *endptr = (char *)(any ? s - 1 : nptr);
265 return (acc);
266 }
267
268 /*
269 * Convert a string to a quad integer.
270 *
271 * Ignores `locale' stuff. Assumes that the upper and lower case
272 * alphabets and digits are each contiguous.
273 */
274 quad_t
275 strtoq(nptr, endptr, base)
276 const char *nptr;
277 char **endptr;
278 register int base;
279 {
280 register const char *s;
281 register u_quad_t acc;
282 register int c;
283 register u_quad_t qbase, cutoff;
284 register int neg, any, cutlim;
285
286 /*
287 * Skip white space and pick up leading +/- sign if any.
288 * If base is 0, allow 0x for hex and 0 for octal, else
289 * assume decimal; if base is already 16, allow 0x.
290 */
291 s = nptr;
292 do {
293 c = *s++;
294 } while (isspace(c));
295 if (c == '-') {
296 neg = 1;
297 c = *s++;
298 } else {
299 neg = 0;
300 if (c == '+')
301 c = *s++;
302 }
303 if ((base == 0 || base == 16) &&
304 c == '0' && (*s == 'x' || *s == 'X')) {
305 c = s[1];
306 s += 2;
307 base = 16;
308 }
309 if (base == 0)
310 base = c == '0' ? 8 : 10;
311
312 /*
313 * Compute the cutoff value between legal numbers and illegal
314 * numbers. That is the largest legal value, divided by the
315 * base. An input number that is greater than this value, if
316 * followed by a legal input character, is too big. One that
317 * is equal to this value may be valid or not; the limit
318 * between valid and invalid numbers is then based on the last
319 * digit. For instance, if the range for quads is
320 * [-9223372036854775808..9223372036854775807] and the input base
321 * is 10, cutoff will be set to 922337203685477580 and cutlim to
322 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
323 * accumulated a value > 922337203685477580, or equal but the
324 * next digit is > 7 (or 8), the number is too big, and we will
325 * return a range error.
326 *
327 * Set any if any `digits' consumed; make it negative to indicate
328 * overflow.
329 */
330 qbase = (unsigned)base;
331 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX;
332 cutlim = cutoff % qbase;
333 cutoff /= qbase;
334 for (acc = 0, any = 0;; c = *s++) {
335 if (isdigit(c))
336 c -= '0';
337 else if (isalpha(c))
338 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
339 else
340 break;
341 if (c >= base)
342 break;
343 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
344 any = -1;
345 else {
346 any = 1;
347 acc *= qbase;
348 acc += c;
349 }
350 }
351 if (any < 0) {
352 acc = neg ? QUAD_MIN : QUAD_MAX;
353 // errno = ERANGE;
354 } else if (neg)
355 acc = -acc;
356 if (endptr != 0)
357 *endptr = (char *)(any ? s - 1 : nptr);
358 return (acc);
359 }
360
361
362 /*
363 * Convert a string to an unsigned quad integer.
364 *
365 * Ignores `locale' stuff. Assumes that the upper and lower case
366 * alphabets and digits are each contiguous.
367 */
368 uint64_t
369 strtouq(const char *nptr,
370 char **endptr,
371 register int base)
372 {
373 register const char *s = nptr;
374 register u_quad_t acc;
375 register int c;
376 register u_quad_t qbase, cutoff;
377 register int neg, any, cutlim;
378
379 /*
380 * See strtoq for comments as to the logic used.
381 */
382 s = nptr;
383 do {
384 c = *s++;
385 } while (isspace(c));
386 if (c == '-') {
387 neg = 1;
388 c = *s++;
389 } else {
390 neg = 0;
391 if (c == '+')
392 c = *s++;
393 }
394 if ((base == 0 || base == 16) &&
395 c == '0' && (*s == 'x' || *s == 'X')) {
396 c = s[1];
397 s += 2;
398 base = 16;
399 }
400 if (base == 0)
401 base = c == '0' ? 8 : 10;
402 qbase = (unsigned)base;
403 cutoff = (u_quad_t)UQUAD_MAX / qbase;
404 cutlim = (u_quad_t)UQUAD_MAX % qbase;
405 for (acc = 0, any = 0;; c = *s++) {
406 if (isdigit(c))
407 c -= '0';
408 else if (isalpha(c))
409 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
410 else
411 break;
412 if (c >= base)
413 break;
414 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
415 any = -1;
416 else {
417 any = 1;
418 acc *= qbase;
419 acc += c;
420 }
421 }
422 if (any < 0) {
423 acc = UQUAD_MAX;
424 // errno = ERANGE;
425 } else if (neg)
426 acc = -acc;
427 if (endptr != 0)
428 *endptr = (char *)(any ? s - 1 : nptr);
429 return (acc);
430 }
431
432
433 /*
434 *
435 */
436
437 char *strchr(const char *str, int ch)
438 {
439 do {
440 if (*str == ch)
441 return((char *)str);
442 } while (*str++);
443 return ((char *) 0);
444 }
445
446 /*
447 *
448 */
449
450 char *
451 strncat(char *s1, const char *s2, unsigned long n)
452 {
453 char *os1;
454 int i = n;
455
456 os1 = s1;
457 while (*s1++)
458 ;
459 --s1;
460 while ((*s1++ = *s2++))
461 if (--i < 0) {
462 *--s1 = '\0';
463 break;
464 }
465 return(os1);
466 }