237aeacb2a63c4942c743462d4ce80567ba9add9
[reactos.git] / reactos / lib / crtdll / stdlib / strtoll.c
1 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
2 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
3 #include <limits.h>
4 #include <crtdll/ctype.h>
5 #include <crtdll/errno.h>
6 #include <crtdll/stdlib.h>
7 //#include <crtdll/unconst.h>
8
9 /* constants used in Solaris */
10 #define LLONG_MIN -9223372036854775807L-1L
11 #define LLONG_MAX 9223372036854775807L
12 #define ULLONG_MAX 18446744073709551615UL
13
14 long
15 strtoll(const char *nptr, char **endptr, int base)
16 {
17 const char *s = nptr;
18 unsigned long acc;
19 int c;
20 unsigned long cutoff;
21 int neg = 0, any, cutlim;
22
23 /*
24 * See strtol for comments as to the logic used.
25 */
26 do {
27 c = *s++;
28 } while (isspace(c));
29 if (c == '-')
30 {
31 neg = 1;
32 c = *s++;
33 }
34 else if (c == '+')
35 c = *s++;
36 if ((base == 0 || base == 16) &&
37 c == '0' && (*s == 'x' || *s == 'X'))
38 {
39 c = s[1];
40 s += 2;
41 base = 16;
42 }
43 if (base == 0)
44 base = c == '0' ? 8 : 10;
45
46 /* to prevent overflow, we take max-1 and add 1 after division */
47 cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1;
48 cutlim = cutoff % base;
49 cutoff /= base;
50 if (++cutlim == base)
51 {
52 cutlim = 0;
53 cutoff++;
54 }
55 for (acc = 0, any = 0;; c = *s++)
56 {
57 if (isdigit(c))
58 c -= '0';
59 else if (isalpha(c))
60 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
61 else
62 break;
63 if (c >= base)
64 break;
65 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
66 any = -1;
67 else
68 {
69 any = 1;
70 acc *= base;
71 acc += c;
72 }
73 }
74 if (any < 0)
75 {
76 acc = neg ? LLONG_MIN : LLONG_MAX;
77 errno = ERANGE;
78 }
79 else if (neg)
80 acc *= -1;
81 if (endptr != 0)
82 *endptr = any ? (char *)s - 1 : (char *)nptr;
83 return acc;
84 }