php strripos 字符串查找函数内部源码实现

和stripos实现不相同,除开查找方式不一样即返回的地址不一样外,个人感觉strripos比stripos的实现在条件判断上更好(看strripos函数的判断,绿色字体的地方)。

/* {{{ proto int strripos(string haystack, string needle [, int offset])

   Finds position of last occurrence of a string within another string */
PHP_FUNCTION(strripos)
{
    zval *zneedle;
    char *needle, *haystack;
    int needle_len, haystack_len;
    long offset = 0;
    char *p, *e, ord_needle[2];
    char *needle_dup, *haystack_dup;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &haystack, &haystack_len, &zneedle, &offset) == FAILURE) {
        RETURN_FALSE;
    }

    if (Z_TYPE_P(zneedle) == IS_STRING) {
        needle = Z_STRVAL_P(zneedle);
        needle_len = Z_STRLEN_P(zneedle);
    } else {
        if (php_needle_char(zneedle, ord_needle TSRMLS_CC) != SUCCESS) {
            RETURN_FALSE;
        }
        ord_needle[1] = '\0';
        needle = ord_needle;
        needle_len = 1;
    }

    if ((haystack_len == 0) || (needle_len == 0)) {
        RETURN_FALSE;
    }

    if (needle_len == 1) {
        /* Single character search can shortcut memcmps
           Can also avoid tolower emallocs */
        if (offset >= 0) {
            if (offset > haystack_len) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
                RETURN_FALSE;
            }
            p = haystack + offset;
            e = haystack + haystack_len - 1;
        } else {
            p = haystack;
            if (offset < -INT_MAX || -offset > haystack_len) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
                RETURN_FALSE;
            }
            e = haystack + haystack_len + offset;
        }
        /* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */
        *ord_needle = tolower(*needle);
        while (e >= p) {
            if (tolower(*e) == *ord_needle) {
                RETURN_LONG(e - p + (offset > 0 ? offset : 0));
            }
            e--;
        }
        RETURN_FALSE;
    }

    needle_dup = estrndup(needle, needle_len);
    php_strtolower(needle_dup, needle_len);
    haystack_dup = estrndup(haystack, haystack_len);
    php_strtolower(haystack_dup, haystack_len);

    if (offset >= 0) {
        if (offset > haystack_len) {
            efree(needle_dup);
            efree(haystack_dup);
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
            RETURN_FALSE;
        }
        p = haystack_dup + offset;
        e = haystack_dup + haystack_len - needle_len;
    } else {
        if (offset < -INT_MAX || -offset > haystack_len) {
            efree(needle_dup);
            efree(haystack_dup);
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
            RETURN_FALSE;
        }
        p = haystack_dup;
        if (needle_len > -offset) {
            e = haystack_dup + haystack_len - needle_len;
        } else {
            e = haystack_dup + haystack_len + offset;
        }
    }

    while (e >= p) {
        if (memcmp(e, needle_dup, needle_len) == 0) {
            efree(haystack_dup);
            efree(needle_dup);
            RETURN_LONG(e - p + (offset > 0 ? offset : 0));
        }
        e--;
    }

    efree(haystack_dup);
    efree(needle_dup);
    RETURN_FALSE;
}
/* }}} */

你可能感兴趣的:(php strripos 字符串查找函数内部源码实现)