Annotation of embedaddon/php/win32/strtoi64.c, revision 1.1.1.1
1.1 misho 1: #if _MSC_VERS <= 1300
2: #include "php_strtoi64.h"
3: /*
4: From APR, apr_strings.c
5: See http://www.apache.org/licenses/LICENSE-2.0
6: */
7:
8: PHPAPI int64_t _strtoi64(const char *nptr, char **endptr, int base)
9: {
10: const char *s;
11: int64_t acc;
12: int64_t val;
13: int neg, any;
14: char c;
15:
16: /*
17: * Skip white space and pick up leading +/- sign if any.
18: * If base is 0, allow 0x for hex and 0 for octal, else
19: * assume decimal; if base is already 16, allow 0x.
20: */
21: s = nptr;
22: do {
23: c = *s++;
24: } while (isspace((unsigned char)c));
25: if (c == '-') {
26: neg = 1;
27: c = *s++;
28: } else {
29: neg = 0;
30: if (c == '+') {
31: c = *s++;
32: }
33: }
34:
35: if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
36: c = s[1];
37: s += 2;
38: base = 16;
39: }
40: if (base == 0) {
41: base = c == '0' ? 8 : 10;
42: }
43: acc = any = 0;
44: if (base < 2 || base > 36) {
45: errno = EINVAL;
46: if (endptr != NULL) {
47: *endptr = (char *)(any ? s - 1 : nptr);
48: }
49: return acc;
50: }
51:
52: /* The classic bsd implementation requires div/mod operators
53: * to compute a cutoff. Benchmarking proves that iss very, very
54: * evil to some 32 bit processors. Instead, look for underflow
55: * in both the mult and add/sub operation. Unlike the bsd impl,
56: * we also work strictly in a signed int64 word as we haven't
57: * implemented the unsigned type in win32.
58: *
59: * Set 'any' if any `digits' consumed; make it negative to indicate
60: * overflow.
61: */
62: val = 0;
63: for ( ; ; c = *s++) {
64: if (c >= '0' && c <= '9')
65: c -= '0';
66:
67: #if (('Z' - 'A') == 25)
68: else if (c >= 'A' && c <= 'Z')
69: c -= 'A' - 10;
70: else if (c >= 'a' && c <= 'z')
71: c -= 'a' - 10;
72: #elif APR_CHARSET_EBCDIC
73: else if (c >= 'A' && c <= 'I')
74: c -= 'A' - 10;
75: else if (c >= 'J' && c <= 'R')
76: c -= 'J' - 19;
77: else if (c >= 'S' && c <= 'Z')
78: c -= 'S' - 28;
79: else if (c >= 'a' && c <= 'i')
80: c -= 'a' - 10;
81: else if (c >= 'j' && c <= 'r')
82: c -= 'j' - 19;
83: else if (c >= 's' && c <= 'z')
84: c -= 'z' - 28;
85: #else
86: # error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported"
87: #endif
88: else {
89: break;
90: }
91:
92: if (c >= base) {
93: break;
94: }
95:
96: val *= base;
97: if ( (any < 0) /* already noted an over/under flow - short circuit */
98: || (neg && (val > acc || (val -= c) > acc)) /* underflow */
99: || (val < acc || (val += c) < acc)) { /* overflow */
100: any = -1; /* once noted, over/underflows never go away */
101: #ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
102: break;
103: #endif
104: } else {
105: acc = val;
106: any = 1;
107: }
108: }
109:
110: if (any < 0) {
111: acc = neg ? INT64_MIN : INT64_MAX;
112: errno = ERANGE;
113: } else if (!any) {
114: errno = EINVAL;
115: }
116:
117: if (endptr != NULL) {
118: *endptr = (char *)(any ? s - 1 : nptr);
119: }
120: return (acc);
121: }
122: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>