summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSascha Schumann <sas@php.net>2001-09-19 10:57:50 +0000
committerSascha Schumann <sas@php.net>2001-09-19 10:57:50 +0000
commite4ace6cde6bcebc52aa8f583f7a98b51829de249 (patch)
tree5565c53e2dc488e4e44838a191fe8e5121e420b9
parent88d408ee11e0dfeb1c0bbde7dedfa8fab889f08c (diff)
downloadphp-git-e4ace6cde6bcebc52aa8f583f7a98b51829de249.tar.gz
Rewrite _php_match_basetozval to need only one multiplication
per iteration and avoid the U?LONG_MAX hassle.
-rw-r--r--ext/standard/math.c58
1 files changed, 27 insertions, 31 deletions
diff --git a/ext/standard/math.c b/ext/standard/math.c
index 22206a676b..a8dec98310 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -706,10 +706,10 @@ _php_math_basetolong(zval *arg, int base) {
*/
PHPAPI int
_php_math_basetozval(zval *arg, int base, zval *ret) {
- long mult = 1, num = 0, digit;
- double fmult, fnum;
+ long num = 0, digit, onum;
+ double fnum;
int i;
- int f_mode = 0;
+ int mode = 0;
char c, *s;
if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
@@ -718,38 +718,34 @@ _php_math_basetozval(zval *arg, int base, zval *ret) {
s = Z_STRVAL_P(arg);
- for (i = Z_STRLEN_P(arg) - 1; i >= 0; i--) {
- c = toupper(s[i]);
- if (c >= '0' && c <= '9') {
- digit = (c - '0');
- } else if (c >= 'A' && c <= 'Z') {
- digit = (c - 'A' + 10);
- } else {
- continue;
- }
- if (digit >= base) {
+ 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(!f_mode && (!mult || digit > LONG_MAX/mult || num > LONG_MAX-mult*digit)) {
- f_mode = 1;
- if(!mult) {
- fmult = (ulong) ULONG_MAX + 1;
- } else {
- fmult = (ulong) mult;
- }
- fnum = (ulong) num;
- }
- if(f_mode) {
- fnum += fmult * digit;
- fmult *= base;
- } else {
- num += mult * digit;
- mult *= base;
- }
+ switch (mode) {
+ case 0: /* Integer */
+ onum = num;
+ num = num * base + digit;
+
+ if (num > onum)
+ break; /* No overflow, continue */
+
+ fnum = onum;
+ mode = 1;
+ /* fall-through */
+ case 1: /* Float */
+ fnum = fnum * base + digit;
+ }
}
- if(f_mode) {
+ if (mode == 1) {
ZVAL_DOUBLE(ret, fnum);
} else {
ZVAL_LONG(ret, num);