@@ -2019,6 +2019,89 @@ static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
2019
2019
}
2020
2020
/* }}} */
2021
2021
2022
+ static int compare_long_to_string (zend_long lval , zend_string * str ) /* {{{ */
2023
+ {
2024
+ zend_long str_lval ;
2025
+ double str_dval ;
2026
+ int num_cmp_result ;
2027
+ zend_uchar type = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 1 );
2028
+
2029
+ if (type == IS_LONG ) {
2030
+ num_cmp_result = lval > str_lval ? 1 : lval < str_lval ? -1 : 0 ;
2031
+ } else if (type == IS_DOUBLE ) {
2032
+ double diff = (double ) lval - str_dval ;
2033
+ num_cmp_result = ZEND_NORMALIZE_BOOL (diff );
2034
+ } else {
2035
+ num_cmp_result = ZEND_NORMALIZE_BOOL (lval );
2036
+ }
2037
+
2038
+ /* TODO Avoid duplicate is_numeric_string call. */
2039
+ zend_bool is_numeric = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
2040
+ if (is_numeric ) {
2041
+ /* For numeric strings, the comparison result stays the same. */
2042
+ return num_cmp_result ;
2043
+ }
2044
+
2045
+ zend_string * lval_as_str = zend_long_to_str (lval );
2046
+ int str_cmp_result = zend_binary_strcmp (
2047
+ ZSTR_VAL (lval_as_str ), ZSTR_LEN (lval_as_str ), ZSTR_VAL (str ), ZSTR_LEN (str ));
2048
+ str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
2049
+ zend_string_release (lval_as_str );
2050
+
2051
+ if (str_cmp_result != num_cmp_result ) {
2052
+ zend_error (E_WARNING ,
2053
+ "Result of comparison between " ZEND_LONG_FMT " and \"%s\" will change (%d to %d)" ,
2054
+ lval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
2055
+ }
2056
+
2057
+ /* Return old (numeric) comparison result. */
2058
+ return num_cmp_result ;
2059
+ }
2060
+ /* }}} */
2061
+
2062
+ static int compare_double_to_string (double dval , zend_string * str ) /* {{{ */
2063
+ {
2064
+ zend_long str_lval ;
2065
+ double str_dval ;
2066
+ int num_cmp_result ;
2067
+ zend_uchar type = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
2068
+
2069
+ if (type == IS_LONG ) {
2070
+ double diff = dval - (double ) str_lval ;
2071
+ num_cmp_result = ZEND_NORMALIZE_BOOL (diff );
2072
+ } else if (type == IS_DOUBLE ) {
2073
+ if (dval == str_dval ) {
2074
+ return 0 ;
2075
+ }
2076
+ num_cmp_result = ZEND_NORMALIZE_BOOL (dval - str_dval );
2077
+ } else {
2078
+ num_cmp_result = ZEND_NORMALIZE_BOOL (dval );
2079
+ }
2080
+
2081
+ /* TODO Avoid duplicate is_numeric_string call. */
2082
+ zend_bool is_numeric = is_numeric_string (ZSTR_VAL (str ), ZSTR_LEN (str ), & str_lval , & str_dval , 0 );
2083
+ if (is_numeric ) {
2084
+ /* For numeric strings, the comparison result stays the same. */
2085
+ return num_cmp_result ;
2086
+ }
2087
+
2088
+ zend_string * dval_as_str = zend_strpprintf (0 , "%.*G" , (int ) EG (precision ), dval );
2089
+ int str_cmp_result = zend_binary_strcmp (
2090
+ ZSTR_VAL (dval_as_str ), ZSTR_LEN (dval_as_str ), ZSTR_VAL (str ), ZSTR_LEN (str ));
2091
+ str_cmp_result = ZEND_NORMALIZE_BOOL (str_cmp_result );
2092
+ zend_string_release (dval_as_str );
2093
+
2094
+ if (str_cmp_result != num_cmp_result ) {
2095
+ zend_error (E_WARNING ,
2096
+ "Result of comparison between %G and \"%s\" will change (%d to %d)" ,
2097
+ dval , ZSTR_VAL (str ), num_cmp_result , str_cmp_result );
2098
+ }
2099
+
2100
+ /* Return old (numeric) comparison result. */
2101
+ return num_cmp_result ;
2102
+ }
2103
+ /* }}} */
2104
+
2022
2105
ZEND_API int ZEND_FASTCALL compare_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
2023
2106
{
2024
2107
int ret ;
@@ -2087,6 +2170,32 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
2087
2170
ZVAL_LONG (result , Z_STRLEN_P (op1 ) == 0 ? 0 : 1 );
2088
2171
return SUCCESS ;
2089
2172
2173
+ case TYPE_PAIR (IS_LONG , IS_STRING ):
2174
+ ZVAL_LONG (result , compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 )));
2175
+ return SUCCESS ;
2176
+
2177
+ case TYPE_PAIR (IS_STRING , IS_LONG ):
2178
+ ZVAL_LONG (result , - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 )));
2179
+ return SUCCESS ;
2180
+
2181
+ case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2182
+ if (zend_isnan (Z_DVAL_P (op1 ))) {
2183
+ ZVAL_LONG (result , 1 );
2184
+ return SUCCESS ;
2185
+ }
2186
+
2187
+ ZVAL_LONG (result , compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 )));
2188
+ return SUCCESS ;
2189
+
2190
+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2191
+ if (zend_isnan (Z_DVAL_P (op2 ))) {
2192
+ ZVAL_LONG (result , 1 );
2193
+ return SUCCESS ;
2194
+ }
2195
+
2196
+ ZVAL_LONG (result , - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 )));
2197
+ return SUCCESS ;
2198
+
2090
2199
case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2091
2200
ZVAL_LONG (result , 1 );
2092
2201
return SUCCESS ;
0 commit comments