File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / win32 / strtoi64.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:48:06 2012 UTC (12 years, 5 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, v5_4_17p0, v5_4_17, v5_3_10, HEAD
php

    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>