@@ -1965,6 +1965,89 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
1965
1965
}
1966
1966
/* }}} */
1967
1967
1968
+ static int compare_long_to_string (zend_long lval , zend_string * str ) /* {{{ */
1969
+ {
1970
+ zend_long str_lval ;
1971
+ double str_dval ;
1972
+ int num_cmp_result ;
1973
+ zend_uchar type = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 1 );
1974
+
1975
+ if (type == IS_LONG ) {
1976
+ num_cmp_result = lval > str_lval ? 1 : lval < str_lval ? -1 : 0 ;
1977
+ } else if (type == IS_DOUBLE ) {
1978
+ double diff = (double ) lval - str_dval ;
1979
+ num_cmp_result = ZEND_NORMALIZE_BOOL (diff );
1980
+ } else {
1981
+ num_cmp_result = ZEND_NORMALIZE_BOOL (lval );
1982
+ }
1983
+
1984
+ /* TODO Avoid duplicate is_numeric_string call. */
1985
+ zend_bool is_numeric = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
1986
+ if (is_numeric ) {
1987
+ /* For numeric strings, the comparison result stays the same. */
1988
+ return num_cmp_result ;
1989
+ }
1990
+
1991
+ zend_string * lval_as_str = zend_long_to_str (lval );
1992
+ int str_cmp_result = zend_binary_strcmp (
1993
+ ZSTR_VAL (lval_as_str ), ZSTR_LEN (lval_as_str ), ZSTR_VAL (str ), ZSTR_LEN (str ));
1994
+ str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
1995
+ zend_string_release (lval_as_str );
1996
+
1997
+ if (str_cmp_result != num_cmp_result ) {
1998
+ zend_error (E_WARNING ,
1999
+ "Result of comparison between " ZEND_LONG_FMT " and \"%s\" will change (%d to %d)" ,
2000
+ lval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
2001
+ }
2002
+
2003
+ /* Return old (numeric) comparison result. */
2004
+ return num_cmp_result ;
2005
+ }
2006
+ /* }}} */
2007
+
2008
+ static int compare_double_to_string (double dval , zend_string * str ) /* {{{ */
2009
+ {
2010
+ zend_long str_lval ;
2011
+ double str_dval ;
2012
+ int num_cmp_result ;
2013
+ zend_uchar type = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
2014
+
2015
+ if (type == IS_LONG ) {
2016
+ double diff = dval - (double ) str_lval ;
2017
+ num_cmp_result = ZEND_NORMALIZE_BOOL (diff );
2018
+ } else if (type == IS_DOUBLE ) {
2019
+ if (dval == str_dval ) {
2020
+ return 0 ;
2021
+ }
2022
+ num_cmp_result = ZEND_NORMALIZE_BOOL (dval - str_dval );
2023
+ } else {
2024
+ num_cmp_result = ZEND_NORMALIZE_BOOL (dval );
2025
+ }
2026
+
2027
+ /* TODO Avoid duplicate is_numeric_string call. */
2028
+ zend_bool is_numeric = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
2029
+ if (is_numeric ) {
2030
+ /* For numeric strings, the comparison result stays the same. */
2031
+ return num_cmp_result ;
2032
+ }
2033
+
2034
+ zend_string * dval_as_str = zend_strpprintf (0 , "%.*G" , (int ) EG (precision ), dval );
2035
+ int str_cmp_result = zend_binary_strcmp (
2036
+ ZSTR_VAL (dval_as_str ), ZSTR_LEN (dval_as_str ), ZSTR_VAL (str ), ZSTR_LEN (str ));
2037
+ str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
2038
+ zend_string_release (dval_as_str );
2039
+
2040
+ if (str_cmp_result != num_cmp_result ) {
2041
+ zend_error (E_WARNING ,
2042
+ "Result of comparison between %G and \"%s\" will change (%d to %d)" ,
2043
+ dval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
2044
+ }
2045
+
2046
+ /* Return old (numeric) comparison result. */
2047
+ return num_cmp_result ;
2048
+ }
2049
+ /* }}} */
2050
+
1968
2051
ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
1969
2052
{
1970
2053
int ret ;
@@ -2033,6 +2116,32 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2033
2116
ZVAL_LONG (result , Z_STRLEN_P (op1 ) == 0 ? 0 : 1 );
2034
2117
return SUCCESS ;
2035
2118
2119
+ case TYPE_PAIR (IS_LONG , IS_STRING ):
2120
+ ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 )));
2121
+ return SUCCESS ;
2122
+
2123
+ case TYPE_PAIR (IS_STRING , IS_LONG ):
2124
+ ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 )));
2125
+ return SUCCESS ;
2126
+
2127
+ case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2128
+ if (zend_isnan (Z_DVAL_P (op1 ))) {
2129
+ ZVAL_LONG (result , 1 );
2130
+ return SUCCESS ;
2131
+ }
2132
+
2133
+ ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 )));
2134
+ return SUCCESS ;
2135
+
2136
+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2137
+ if (zend_isnan (Z_DVAL_P (op2 ))) {
2138
+ ZVAL_LONG (result , 1 );
2139
+ return SUCCESS ;
2140
+ }
2141
+
2142
+ ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 )));
2143
+ return SUCCESS ;
2144
+
2036
2145
case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2037
2146
ZVAL_LONG (result , 1 );
2038
2147
return SUCCESS ;
0 commit comments