Copyright© M&AΫϥυ 21
zendi_smart_strcmpͱݴ͏ո͍ؔ͠
ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2) /* {{{ */
{
zend_uchar ret1, ret2;
int oflow1, oflow2;
zend_long lval1 = 0, lval2 = 0;
double dval1 = 0.0, dval2 = 0.0;
if ((ret1 = is_numeric_string_ex(s1->val, s1->len, &lval1, &dval1, false, &oflow1, NULL)) &&
(ret2 = is_numeric_string_ex(s2->val, s2->len, &lval2, &dval2, false, &oflow2, NULL))) {
#if ZEND_ULONG_MAX == 0xFFFFFFFF
if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
|| (oflow1 == -1 && dval1 < -9007199254740991.))) {
#else
if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
#endif
/* both values are integers overflown to the same side, and the
* double comparison may have resulted in crucial accuracy lost */
goto string_cmp;
}
if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
if (ret1 != IS_DOUBLE) {
if (oflow2) {
/* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
return -1 * oflow2;
}
dval1 = (double) lval1;
} else if (ret2 != IS_DOUBLE) {
if (oflow1) {
return oflow1;
}
dval2 = (double) lval2;
} else if (dval1 == dval2 && !zend_finite(dval1)) {
/* Both values overflowed and have the same sign,
* so a numeric comparison would be inaccurate */
goto string_cmp;
}
dval1 = dval1 - dval2;
return ZEND_NORMALIZE_BOOL(dval1);
} else { /* they both have to be long's */
return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
}
} else {
int strcmp_ret;
string_cmp:
strcmp_ret = zend_binary_strcmp(s1->val, s1->len, s2->val, s2->len);
return ZEND_NORMALIZE_BOOL(strcmp_ret);
}
}
/* }}} */