purge remaining gpl code from clib, and make clib build again
[tangerine.git] / compiler / clib / strtoull.c
blobaabeb3288dd962b876ecae668b12b20c46e21d53
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 ANSI C function strtoull().
6 */
8 /* This function requires the use of the long long type. */
9 #include <aros/system.h>
10 #if defined(AROS_HAVE_LONG_LONG)
12 #include <ctype.h>
13 #include <errno.h>
14 #include <stdlib.h>
15 #ifndef AROS_NO_LIMITS_H
16 # include <limits.h>
17 #else
18 # define ULLONG_MAX 0xffffffffffffffffULL
19 #endif
21 /* Function disabled because of the long long support fns not in the libs */
22 #if 0
23 /*****************************************************************************
25 NAME */
26 #include <stdlib.h>
28 unsigned long long strtoull (
30 /* SYNOPSIS */
31 const char * restrict str,
32 char ** restrict endptr,
33 int base)
35 /* FUNCTION
36 Convert a string of digits into an integer according to the
37 given base.
39 INPUTS
40 str - The string which should be converted. Leading
41 whitespace are ignored. The number may be prefixed
42 by a '+' or '-'. If base is above 10, then the
43 alphabetic characters from 'A' are used to specify
44 digits above 9 (ie. 'A' or 'a' is 10, 'B' or 'b' is
45 11 and so on until 'Z' or 'z' is 35).
46 endptr - If this is non-NULL, then the address of the first
47 character after the number in the string is stored
48 here.
49 base - The base for the number. May be 0 or between 2 and 36,
50 including both. 0 means to autodetect the base. strtoull()
51 selects the base by inspecting the first characters
52 of the string. If they are "0x", then base 16 is
53 assumed. If they are "0", then base 8 is assumed. Any
54 other digit will assume base 10. This is like in C.
56 If you give base 16, then an optional "0x" may
57 precede the number in the string.
59 RESULT
60 The value of the string. The first character after the number
61 is returned in *endptr, if endptr is non-NULL. If no digits can
62 be converted, *endptr contains str (if non-NULL) and 0 is
63 returned.
65 NOTES
67 EXAMPLE
68 // Returns 1, ptr points to the 0-Byte
69 strtoull (" \t +0x1", &ptr, 0);
71 // Returns 15. ptr points to the a
72 strtoull ("017a", &ptr, 0);
74 // Returns 215 (5*36 + 35)
75 strtoull ("5z", &ptr, 36);
77 BUGS
79 SEE ALSO
80 strtoll(), strtoull()
82 INTERNALS
84 ******************************************************************************/
86 unsigned long long val = 0;
87 int digit;
88 char c = 0;
89 unsigned long long cutoff;
90 int cutlim;
91 int any;
93 if (base < 0 || base == 1 || base > 36)
95 errno = EINVAL;
97 if (endptr)
98 *endptr = (char *)str;
100 return 0;
103 while (isspace (*str))
104 str ++;
106 if (*str)
108 if (*str == '+' || *str == '-')
109 c = *str ++;
111 /* Assume base ? */
112 if (base == 0)
114 if (*str == '0') /* Base 8 or 16 */
116 str++;
117 if (*str == 'x' || *str == 'X')
119 base = 16;
120 str++;
122 else
123 base = 8;
125 else /* Any other digit: Base 10 (decimal) */
126 base = 10;
130 Conversion loop, from FreeBSD's src/lib/libc/stdlib/strtoull.c
132 The previous AROS loop was
133 a) inefficient - it did a division each time around.
134 b) buggy - it returned the wrong value in endptr on overflow.
136 cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base;
137 cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base;
138 val = 0;
139 any = 0;
141 while (*str)
143 digit = *str;
145 if (!isascii(digit))
146 break;
148 if (isdigit(digit))
149 digit -= '0';
150 else if (isalpha(digit))
151 digit -= isupper(c) ? 'A' - 10 : 'a' - 10;
152 else
153 break;
155 if (digit >= base)
156 break;
159 any < 0 when we have overflowed. We still need to find the
160 end of the subject sequence
162 if (any < 0 || val > cutoff || (val == cutoff && digit > cutlim))
164 any = -1;
166 else
168 any = 1;
169 val = (val * base) + digit;
172 str++;
175 /* Range overflow */
176 if (any < 0)
178 val = ULLONG_MAX;
179 errno = ERANGE;
182 if (c == '-')
183 val = -val;
186 if (endptr)
187 *endptr = (char *)str;
189 return val;
190 } /* strtoull */
191 #else
192 unsigned long long
193 strtoull(const char * restrict str, char ** restrict endptr, int base)
195 abort();
197 #endif
198 #endif /* AROS_HAVE_LONG_LONG */