mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
MFZE1
This commit is contained in:
parent
e8f4e4660c
commit
8722b31d8a
3 changed files with 61 additions and 125 deletions
|
@ -239,7 +239,7 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec)
|
|||
double d;
|
||||
int type;
|
||||
|
||||
if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d)) == 0) {
|
||||
if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, 0)) == 0) {
|
||||
return "long";
|
||||
} else if (type == IS_DOUBLE) {
|
||||
*p = (long) d;
|
||||
|
@ -273,7 +273,7 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec)
|
|||
long l;
|
||||
int type;
|
||||
|
||||
if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p)) == 0) {
|
||||
if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, 0)) == 0) {
|
||||
return "double";
|
||||
} else if (type == IS_LONG) {
|
||||
*p = (double) l;
|
||||
|
|
|
@ -114,7 +114,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
|
|||
char *strval;
|
||||
|
||||
strval = op->value.str.val;
|
||||
switch ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval))) {
|
||||
switch ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval, 1))) {
|
||||
case IS_DOUBLE:
|
||||
case IS_LONG:
|
||||
break;
|
||||
|
@ -152,7 +152,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
|
|||
switch ((op)->type) { \
|
||||
case IS_STRING: \
|
||||
{ \
|
||||
switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval))) { \
|
||||
switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
|
||||
case IS_DOUBLE: \
|
||||
case IS_LONG: \
|
||||
break; \
|
||||
|
@ -1456,7 +1456,7 @@ ZEND_API int increment_function(zval *op1)
|
|||
double dval;
|
||||
char *strval = op1->value.str.val;
|
||||
|
||||
switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval)) {
|
||||
switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval, 0)) {
|
||||
case IS_LONG:
|
||||
op1->value.lval = lval+1;
|
||||
op1->type = IS_LONG;
|
||||
|
@ -1502,7 +1502,7 @@ ZEND_API int decrement_function(zval *op1)
|
|||
op1->value.lval = -1;
|
||||
op1->type = IS_LONG;
|
||||
break;
|
||||
} else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL)==IS_LONG) { /* long */
|
||||
} else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL, 0)==IS_LONG) { /* long */
|
||||
STR_FREE(op1->value.str.val);
|
||||
op1->value.lval = lval-1;
|
||||
op1->type = IS_LONG;
|
||||
|
@ -1627,8 +1627,8 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
|
|||
long lval1, lval2;
|
||||
double dval1, dval2;
|
||||
|
||||
if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1)) &&
|
||||
(ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2))) {
|
||||
if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
|
||||
(ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) {
|
||||
#if 0&&WITH_BCMATH
|
||||
if ((ret1==FLAG_IS_BC) || (ret2==FLAG_IS_BC)) {
|
||||
bc_num first, second;
|
||||
|
@ -1703,83 +1703,3 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
|
|||
}
|
||||
zend_compare_symbol_tables(result, Z_OBJPROP_P(o1), Z_OBJPROP_P(o2) TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
/* returns 0 for non-numeric string
|
||||
* returns IS_DOUBLE for floating point string, and assigns the value to *dval (if it's not NULL)
|
||||
* returns IS_LONG for integer strings, and assigns the value to *lval (if it's not NULL)
|
||||
* returns FLAG_IS_BC if the number might lose accuracy when converted to a double
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
static inline int is_numeric_string(char *str, int length, long *lval, double *dval)
|
||||
{
|
||||
register char *p=str, *end=str+length;
|
||||
unsigned char had_period=0, had_exponent=0;
|
||||
char *end_ptr;
|
||||
|
||||
if (!length) {
|
||||
return 0;
|
||||
}
|
||||
switch (*p) {
|
||||
case '-':
|
||||
case '+':
|
||||
while (*++p==' '); /* ignore spaces after the sign */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while (p<end) {
|
||||
if (isdigit((int)(unsigned char)*p)) {
|
||||
p++;
|
||||
} else if (*p=='.') {
|
||||
if (had_period) {
|
||||
return 0;
|
||||
} else {
|
||||
had_period=1;
|
||||
p++;
|
||||
}
|
||||
} else if (*p=='e' || *p=='E') {
|
||||
p++;
|
||||
if (is_numeric_string(p, length - (int) (p-str), NULL, NULL)==IS_LONG) { /* valid exponent */
|
||||
had_exponent=1;
|
||||
break;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
errno=0;
|
||||
if (had_period || had_exponent) { /* floating point number */
|
||||
double local_dval;
|
||||
|
||||
local_dval = strtod(str, &end_ptr);
|
||||
if (errno==ERANGE || end_ptr != str+length) { /* overflow or bad string */
|
||||
return 0;
|
||||
} else {
|
||||
if (dval) {
|
||||
*dval = local_dval;
|
||||
}
|
||||
return IS_DOUBLE;
|
||||
}
|
||||
} else {
|
||||
long local_lval;
|
||||
|
||||
local_lval = strtol(str, &end_ptr, 10);
|
||||
if (errno==ERANGE || end_ptr != str+length) { /* overflow or bad string */
|
||||
return 0;
|
||||
} else {
|
||||
if (lval) {
|
||||
*lval = local_lval;
|
||||
}
|
||||
return IS_LONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,11 +58,11 @@ ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
|||
ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
static inline int is_numeric_string(char *str, int length, long *lval, double *dval)
|
||||
static inline int is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
|
||||
{
|
||||
long local_lval;
|
||||
double local_dval;
|
||||
char *end_ptr;
|
||||
char *end_ptr_long, *end_ptr_double;
|
||||
int conv_base=10;
|
||||
|
||||
if (!length) {
|
||||
|
@ -74,12 +74,16 @@ static inline int is_numeric_string(char *str, int length, long *lval, double *d
|
|||
conv_base=16;
|
||||
}
|
||||
errno=0;
|
||||
local_lval = strtol(str, &end_ptr, conv_base);
|
||||
if (errno!=ERANGE && end_ptr == str+length) { /* integer string */
|
||||
if (lval) {
|
||||
*lval = local_lval;
|
||||
local_lval = strtol(str, &end_ptr_long, conv_base);
|
||||
if (errno!=ERANGE) {
|
||||
if (end_ptr_long == str+length) { /* integer string */
|
||||
if (lval) {
|
||||
*lval = local_lval;
|
||||
}
|
||||
return IS_LONG;
|
||||
}
|
||||
return IS_LONG;
|
||||
} else {
|
||||
end_ptr_long=NULL;
|
||||
}
|
||||
|
||||
if (conv_base==16) { /* hex string, under UNIX strtod() messes it up */
|
||||
|
@ -87,40 +91,52 @@ static inline int is_numeric_string(char *str, int length, long *lval, double *d
|
|||
}
|
||||
|
||||
errno=0;
|
||||
local_dval = strtod(str, &end_ptr);
|
||||
if (errno!=ERANGE && end_ptr == str+length) { /* floating point string */
|
||||
if (! zend_finite(local_dval)) {
|
||||
/* "inf","nan" and maybe other weird ones */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dval) {
|
||||
*dval = local_dval;
|
||||
}
|
||||
#if 0&&WITH_BCMATH
|
||||
if (length>16) {
|
||||
register char *ptr=str, *end=str+length;
|
||||
|
||||
while (ptr<end) {
|
||||
switch(*ptr++) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
/* scientific notation, not handled by the BC library */
|
||||
return IS_DOUBLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
local_dval = strtod(str, &end_ptr_double);
|
||||
if (errno!=ERANGE) {
|
||||
if (end_ptr_double == str+length) { /* floating point string */
|
||||
if (! zend_finite(local_dval)) {
|
||||
/* "inf","nan" and maybe other weird ones */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dval) {
|
||||
*dval = local_dval;
|
||||
}
|
||||
#if 0&&WITH_BCMATH
|
||||
if (length>16) {
|
||||
register char *ptr=str, *end=str+length;
|
||||
|
||||
while (ptr<end) {
|
||||
switch(*ptr++) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
/* scientific notation, not handled by the BC library */
|
||||
return IS_DOUBLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FLAG_IS_BC;
|
||||
} else {
|
||||
return IS_DOUBLE;
|
||||
}
|
||||
return FLAG_IS_BC;
|
||||
} else {
|
||||
return IS_DOUBLE;
|
||||
}
|
||||
#else
|
||||
return IS_DOUBLE;
|
||||
return IS_DOUBLE;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
end_ptr_double=NULL;
|
||||
}
|
||||
if (allow_errors) {
|
||||
if (end_ptr_double>end_ptr_long && dval) {
|
||||
*dval = local_dval;
|
||||
return IS_DOUBLE;
|
||||
} else if (end_ptr_long && lval) {
|
||||
*lval = local_lval;
|
||||
return IS_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue