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>