]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOStringFuncs.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOStringFuncs.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
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
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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*/
0b4e3aa0 79#include <sys/types.h>
1c79356b
A
80#include <machine/limits.h>
81
82typedef int BOOL;
83
84static inline BOOL
85isupper(char c)
86{
87 return (c >= 'A' && c <= 'Z');
88}
89
90static inline BOOL
91isalpha(char c)
92{
93 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
94}
95
96
97static inline BOOL
98isspace(char c)
99{
100 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
101}
102
103static inline BOOL
104isdigit(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 */
115long
116strtol(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
201unsigned long
202strtoul(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
0b4e3aa0
A
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 */
272quad_t
273strtoq(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 */
89b3af67
A
366uint64_t
367strtouq(const char *nptr,
368 char **endptr,
369 register int base)
0b4e3aa0
A
370{
371 register const char *s = nptr;
372 register u_quad_t acc;
373 register int c;
374 register u_quad_t qbase, cutoff;
375 register int neg, any, cutlim;
376
377 /*
378 * See strtoq for comments as to the logic used.
379 */
380 s = nptr;
381 do {
382 c = *s++;
383 } while (isspace(c));
384 if (c == '-') {
385 neg = 1;
386 c = *s++;
387 } else {
388 neg = 0;
389 if (c == '+')
390 c = *s++;
391 }
392 if ((base == 0 || base == 16) &&
393 c == '0' && (*s == 'x' || *s == 'X')) {
394 c = s[1];
395 s += 2;
396 base = 16;
397 }
398 if (base == 0)
399 base = c == '0' ? 8 : 10;
400 qbase = (unsigned)base;
401 cutoff = (u_quad_t)UQUAD_MAX / qbase;
402 cutlim = (u_quad_t)UQUAD_MAX % qbase;
403 for (acc = 0, any = 0;; c = *s++) {
404 if (isdigit(c))
405 c -= '0';
406 else if (isalpha(c))
407 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
408 else
409 break;
410 if (c >= base)
411 break;
412 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
413 any = -1;
414 else {
415 any = 1;
416 acc *= qbase;
417 acc += c;
418 }
419 }
420 if (any < 0) {
421 acc = UQUAD_MAX;
422// errno = ERANGE;
423 } else if (neg)
424 acc = -acc;
425 if (endptr != 0)
426 *endptr = (char *)(any ? s - 1 : nptr);
427 return (acc);
428}
429
430
1c79356b
A
431/*
432 *
433 */
434
435char *strchr(const char *str, int ch)
436{
437 do {
438 if (*str == ch)
439 return((char *)str);
440 } while (*str++);
441 return ((char *) 0);
442}
443
444/*
445 *
446 */
447
448char *
449strncat(char *s1, const char *s2, unsigned long n)
450{
451 char *os1;
452 int i = n;
453
454 os1 = s1;
455 while (*s1++)
456 ;
457 --s1;
458 while ((*s1++ = *s2++))
459 if (--i < 0) {
460 *--s1 = '\0';
461 break;
462 }
463 return(os1);
464}