cvs: php4 /ext/standard math.c

From: Date: Thu, 20 Sep 2001 08:22:45 +0000
Subject: cvs: php4 /ext/standard math.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-7490@lists.php.net to get a copy of this message
sas Thu Sep 20 04:22:45 2001 EDT Modified files: /php4/ext/standard math.c Log: Rework some string-to-number and vice-versa functions to work smarter (e.g. without using functions that use slow locales, without allocating extra memory and with fewer integer/float operations) Index: php4/ext/standard/math.c diff -u php4/ext/standard/math.c:1.61 php4/ext/standard/math.c:1.62 --- php4/ext/standard/math.c:1.61 Wed Sep 19 07:03:58 2001 +++ php4/ext/standard/math.c Thu Sep 20 04:22:44 2001 @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: math.c,v 1.61 2001/09/19 11:03:58 sas Exp $ */ +/* $Id: math.c,v 1.62 2001/09/20 08:22:44 sas Exp $ */ #include "php.h" #include "php_math.h" @@ -664,7 +664,7 @@ */ PHPAPI long _php_math_basetolong(zval *arg, int base) { - long mult = 1, num = 0, digit; + long num = 0, digit, onum; int i; char c, *s; @@ -674,23 +674,25 @@ s = Z_STRVAL_P(arg); - for (i = Z_STRLEN_P(arg) - 1; i >= 0; i--, mult *= base) { - c = toupper(s[i]); - if (c >= '0' && c <= '9') { - digit = (c - '0'); - } else if (c >= 'A' && c <= 'Z') { - digit = (c - 'A' + 10); - } else { - continue; - } + for (i = Z_STRLEN_P(arg); i > 0; i--) { + c = *s++; + + digit = (c >= '0' && c <= '9') ? c - '0' + : (c >= 'A' && c <= 'Z') ? c - 'A' + 10 + : (c >= 'a' && c <= 'z') ? c - 'a' + 10 + : base; + if (digit >= base) { continue; } - if(!mult || digit > LONG_MAX/mult || num > LONG_MAX-mult*digit) { - php_error(E_WARNING, "base_to_long: number '%s' is too big to fit in long", s); - return LONG_MAX; - } - num += mult * digit; + + onum = num; + num = num * base + digit; + if (num > onum) + continue; + + php_error(E_WARNING, "base_to_long: number '%s' is too big to fit in long", s); + return LONG_MAX; } return num; @@ -764,8 +766,8 @@ _php_math_longtobase(zval *arg, int base) { static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - char *result, *ptr, *ret; - int len, digit; + char buf[(sizeof(unsigned long) << 3) + 1]; + char *ptr, *end; unsigned long value; if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) { @@ -774,25 +776,16 @@ value = Z_LVAL_P(arg); - /* allocates space for the longest possible result with the lowest base */ - len = (sizeof(Z_LVAL_P(arg)) * 8) + 1; - result = emalloc((sizeof(Z_LVAL_P(arg)) * 8) + 1); - - ptr = result + len - 1; - *ptr-- = '\0'; + end = ptr = buf + sizeof(buf) - 1; + *ptr = '\0'; do { - digit = value % base; - *ptr = digits[digit]; + *--ptr = digits[value % base]; value /= base; - } - while (ptr-- > result && value); - ptr++; - ret = estrdup(ptr); - efree(result); + } while (ptr > buf && value); - return ret; -} + return estrndup(ptr, end - ptr); +} /* }}} */ /* {{{ _php_math_zvaltobase */ @@ -805,49 +798,28 @@ _php_math_zvaltobase(zval *arg, int base) { static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - char *result, *ptr, *ret; - int len, digit; - unsigned long value; - double fvalue; - int f_mode; if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) { return empty_string; } - f_mode = (Z_TYPE_P(arg) == IS_DOUBLE); + if (Z_TYPE_P(arg) == IS_DOUBLE) { + double fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */ + char *ptr, *end; + char buf[(sizeof(double) << 3) + 1]; + + end = ptr = buf + sizeof(buf) - 1; + *ptr = '\0'; + + do { + *--ptr = digits[(int) fmod(fvalue, base)]; + fvalue /= base; + } while (ptr > buf && fabs(fvalue) >= 1); - if(f_mode) { - fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */ - } else { - value = Z_LVAL_P(arg); + return estrndup(ptr, end - ptr); } - - /* allocates space for the longest possible result with the lowest base */ - len = (sizeof(Z_DVAL_P(arg)) * 8) + 1; - result = emalloc((sizeof(Z_DVAL_P(arg)) * 8) + 1); - - ptr = result + len - 1; - *ptr-- = '\0'; - - do { - if(f_mode) { - double d = floor(fvalue/base); - digit = (int)ceil(fvalue - d*base); - *ptr = digits[digit]; - fvalue = d; - } else { - digit = value % base; - *ptr = digits[digit]; - value /= base; - } - } - while (ptr-- > result && (f_mode?(fabs(fvalue)>=1):value)); - ptr++; - ret = estrdup(ptr); - efree(result); - - return ret; + + return _php_math_longtobase(arg, base); } /* }}} */

« previous php.cvs (#7490) next »