Skip to content

Commit 4f4d2be

Browse files
committed
Improved integer/float to string comparison semantics
1 parent d5ff574 commit 4f4d2be

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

Zend/zend_operators.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,6 +1965,63 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
19651965
}
19661966
/* }}} */
19671967

1968+
static int compare_long_to_string(zend_long lval, zend_string *str) /* {{{ */
1969+
{
1970+
if (ZSTR_LEN(str) == 0) {
1971+
return ZEND_NORMALIZE_BOOL(lval);
1972+
}
1973+
1974+
zend_long str_lval;
1975+
double str_dval;
1976+
zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
1977+
1978+
if (type == IS_LONG) {
1979+
return lval > str_lval ? 1 : lval < str_lval ? -1 : 0;
1980+
}
1981+
1982+
if (type == IS_DOUBLE) {
1983+
double diff = (double) lval - str_dval;
1984+
return ZEND_NORMALIZE_BOOL(diff);
1985+
}
1986+
1987+
zend_string *lval_as_str = zend_long_to_str(lval);
1988+
int cmp_result = zend_binary_strcmp(
1989+
ZSTR_VAL(lval_as_str), ZSTR_LEN(lval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
1990+
zend_string_release(lval_as_str);
1991+
return ZEND_NORMALIZE_BOOL(cmp_result);
1992+
}
1993+
/* }}} */
1994+
1995+
static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
1996+
{
1997+
if (ZSTR_LEN(str) == 0) {
1998+
return ZEND_NORMALIZE_BOOL(dval);
1999+
}
2000+
2001+
zend_long str_lval;
2002+
double str_dval;
2003+
zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &str_lval, &str_dval, 0);
2004+
2005+
if (type == IS_LONG) {
2006+
double diff = dval - (double) str_lval;
2007+
return ZEND_NORMALIZE_BOOL(diff);
2008+
}
2009+
2010+
if (type == IS_DOUBLE) {
2011+
if (dval == str_dval) {
2012+
return 0;
2013+
}
2014+
return ZEND_NORMALIZE_BOOL(dval - str_dval);
2015+
}
2016+
2017+
zend_string *dval_as_str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
2018+
int cmp_result = zend_binary_strcmp(
2019+
ZSTR_VAL(dval_as_str), ZSTR_LEN(dval_as_str), ZSTR_VAL(str), ZSTR_LEN(str));
2020+
zend_string_release(dval_as_str);
2021+
return ZEND_NORMALIZE_BOOL(cmp_result);
2022+
}
2023+
/* }}} */
2024+
19682025
ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
19692026
{
19702027
int ret;
@@ -2033,6 +2090,22 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
20332090
ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
20342091
return SUCCESS;
20352092

2093+
case TYPE_PAIR(IS_LONG, IS_STRING):
2094+
ZVAL_LONG(result, compare_long_to_string(Z_LVAL_P(op1), Z_STR_P(op2)));
2095+
return SUCCESS;
2096+
2097+
case TYPE_PAIR(IS_STRING, IS_LONG):
2098+
ZVAL_LONG(result, -compare_long_to_string(Z_LVAL_P(op2), Z_STR_P(op1)));
2099+
return SUCCESS;
2100+
2101+
case TYPE_PAIR(IS_DOUBLE, IS_STRING):
2102+
ZVAL_LONG(result, compare_double_to_string(Z_DVAL_P(op1), Z_STR_P(op2)));
2103+
return SUCCESS;
2104+
2105+
case TYPE_PAIR(IS_STRING, IS_DOUBLE):
2106+
ZVAL_LONG(result, -compare_double_to_string(Z_DVAL_P(op2), Z_STR_P(op1)));
2107+
return SUCCESS;
2108+
20362109
case TYPE_PAIR(IS_OBJECT, IS_NULL):
20372110
ZVAL_LONG(result, 1);
20382111
return SUCCESS;

0 commit comments

Comments
 (0)