Annotation of embedaddon/php/win32/strtoi64.c, revision 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>