]> git.saurik.com Git - apple/xnu.git/blame_incremental - iokit/Kernel/IOStringFuncs.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / iokit / Kernel / IOStringFuncs.c
... / ...
CommitLineData
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
84typedef int BOOL;
85
86static inline BOOL
87isupper(char c)
88{
89 return (c >= 'A' && c <= 'Z');
90}
91
92static inline BOOL
93isalpha(char c)
94{
95 return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
96}
97
98
99static inline BOOL
100isspace(char c)
101{
102 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
103}
104
105static inline BOOL
106isdigit(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 */
117long
118strtol(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
203unsigned long
204strtoul(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 */
274quad_t
275strtoq(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 */
368u_quad_t
369strtouq(nptr, endptr, base)
370 const char *nptr;
371 char **endptr;
372 register int base;
373{
374 register const char *s = nptr;
375 register u_quad_t acc;
376 register int c;
377 register u_quad_t qbase, cutoff;
378 register int neg, any, cutlim;
379
380 /*
381 * See strtoq for comments as to the logic used.
382 */
383 s = nptr;
384 do {
385 c = *s++;
386 } while (isspace(c));
387 if (c == '-') {
388 neg = 1;
389 c = *s++;
390 } else {
391 neg = 0;
392 if (c == '+')
393 c = *s++;
394 }
395 if ((base == 0 || base == 16) &&
396 c == '0' && (*s == 'x' || *s == 'X')) {
397 c = s[1];
398 s += 2;
399 base = 16;
400 }
401 if (base == 0)
402 base = c == '0' ? 8 : 10;
403 qbase = (unsigned)base;
404 cutoff = (u_quad_t)UQUAD_MAX / qbase;
405 cutlim = (u_quad_t)UQUAD_MAX % qbase;
406 for (acc = 0, any = 0;; c = *s++) {
407 if (isdigit(c))
408 c -= '0';
409 else if (isalpha(c))
410 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
411 else
412 break;
413 if (c >= base)
414 break;
415 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
416 any = -1;
417 else {
418 any = 1;
419 acc *= qbase;
420 acc += c;
421 }
422 }
423 if (any < 0) {
424 acc = UQUAD_MAX;
425// errno = ERANGE;
426 } else if (neg)
427 acc = -acc;
428 if (endptr != 0)
429 *endptr = (char *)(any ? s - 1 : nptr);
430 return (acc);
431}
432
433
434/*
435 *
436 */
437
438char *strchr(const char *str, int ch)
439{
440 do {
441 if (*str == ch)
442 return((char *)str);
443 } while (*str++);
444 return ((char *) 0);
445}
446
447/*
448 *
449 */
450
451char *
452strncat(char *s1, const char *s2, unsigned long n)
453{
454 char *os1;
455 int i = n;
456
457 os1 = s1;
458 while (*s1++)
459 ;
460 --s1;
461 while ((*s1++ = *s2++))
462 if (--i < 0) {
463 *--s1 = '\0';
464 break;
465 }
466 return(os1);
467}