当前位置: 代码网 > it编程>编程语言>Php > PHP strstr函数原型源码分析

PHP strstr函数原型源码分析

2024年05月19日 Php 我要评论
strstr函数原型源码分析 版本php5.3.291、ext/standard/php_string.hphp_function(strstr);2、ext/standard/string.cphp

strstr

函数原型

源码分析 版本php5.3.29

1、ext/standard/php_string.h

php_function(strstr);

2、ext/standard/string.c

php_function(strstr)
{
    zval *needle;
    char *haystack;
    int haystack_len;
    char *found = null;
    char needle_char[2];
    long found_offset;
    zend_bool part = 0;
    if (zend_parse_parameters(zend_num_args() tsrmls_cc, "sz|b", &haystack, &haystack_len, &needle, &part) == failure) {
        return;
    }
    if (z_type_p(needle) == is_string) {
        if (!z_strlen_p(needle)) {
            php_error_docref(null tsrmls_cc, e_warning, "empty delimiter");
            return_false;
        }
        found = php_memnstr(haystack, z_strval_p(needle), z_strlen_p(needle), haystack + haystack_len);
    } else {
        if (php_needle_char(needle, needle_char tsrmls_cc) != success) {
            return_false;
        }
        needle_char[1] = 0;
        found = php_memnstr(haystack, needle_char,    1, haystack + haystack_len);
    }
    if (found) {
        found_offset = found - haystack;
        if (part) {
            return_stringl(haystack, found_offset, 1);
        } else {
            return_stringl(found, haystack_len - found_offset, 1);
        }
    }
    return_false;
}

zval *needle

文件位置 zend/zend.h

typedef struct _zval_struct zval;
struct _zval_struct {
    /* variable information */
    zvalue_value value;        /* value */
    zend_uint refcount__gc;
    zend_uchar type;    /* active type */
    zend_uchar is_ref__gc;
};

needle是一个变量结构体,对应php strstr 函数参数 mixed $needle

1、char *haystack

char *haystack s是一个字符指针,对应 php strstr函数参数 string $haystack

2、zend_parse_parameters

文件位置 zend/zend_api.c

int zend_parse_parameters(int num_args tsrmls_dc, char *type_spec, ...);
int zend_parse_parameters_ex(int flags, int num_args tsrmls_dc, char *type_spec, ...);
zend_api int zend_parse_parameters(int num_args tsrmls_dc, char *type_spec, ...) /* {{{ */
{
    va_list va;
    int retval;
    return_if_zero_args(num_args, type_spec, 0);
    va_start(va, type_spec);
    retval = zend_parse_va_args(num_args, type_spec, &va, 0 tsrmls_cc);
    va_end(va);
    return retval;
}
/* }}} */
zend_api int zend_parse_method_parameters(int num_args tsrmls_dc, zval *this_ptr, char *type_spec, ...) /* {{{ */
{
    va_list va;
    int retval;
    char *p = type_spec;
    zval **object;
    zend_class_entry *ce;
    if (!this_ptr) {
        return_if_zero_args(num_args, p, 0);
        va_start(va, type_spec);
        retval = zend_parse_va_args(num_args, type_spec, &va, 0 tsrmls_cc);
        va_end(va);
    } else {
        p++;
        return_if_zero_args(num_args, p, 0);
        va_start(va, type_spec);
        object = va_arg(va, zval **);
        ce = va_arg(va, zend_class_entry *);
        *object = this_ptr;
        if (ce && !instanceof_function(z_objce_p(this_ptr), ce tsrmls_cc)) {
            zend_error(e_core_error, "%s::%s() must be derived from %s::%s",
                ce->name, get_active_function_name(tsrmls_c), z_objce_p(this_ptr)->name, get_active_function_name(tsrmls_c));
        }
        retval = zend_parse_va_args(num_args, p, &va, 0 tsrmls_cc);
        va_end(va);
    }
    return retval;
}

最简单的获取函数调用者传递过来的参数便是使用zend_parse_parameters()函数。

zend_parse_parameters() 函数的前几个参数我们直接用内核里宏来生成便可以了,形式为:zend_num_args() tsrmls_cc,注意两者之间有个空格,但是没有逗号。从名字可以看出,zend_num_args()代表着参数的个数。

紧接着需要传递给zend_parse_parameters()函数的参数是一个用于格式化的字符串,就像printf的第一个参数一样。下面表示了最常用的几个符号。

type_spec是格式化字符串,其常见的含义如下:
参数   代表着的类型
b    boolean
l    integer 整型
d    floating point 浮点型
s    string 字符串
r    resource 资源
a    array 数组
o    object instance 对象
o    object instance of a specified type 特定类型的对象
z    non-specific zval 任意类型~
z    zval**类型
f    表示函数、方法名称,php5.1里貌似木有... ...

3、if (z_type_p(needle) == is_string)

z_type_p
文件位置:zend/zend_operators.h
#define z_type_p(zval_p)    z_type(*zval_p)
#define z_type(zval)        (zval).type

4、if (!z_strlen_p(needle)) {

z_strlen_p
文件位置:zend/zend_operators.h
#define z_strlen_p(zval_p)        z_strlen(*zval_p)
#define z_strlen(zval)            (zval).value.str.len

5、php_memnstr(haystack, z_strval_p(needle), z_strlen_p(needle), haystack + haystack_len);

文件位置:main/php.h
#define php_memnstr zend_memnstr
文件位置:zend/zend_operators.h
static inline char *
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
{
    char *p = haystack;
    char ne = needle[needle_len-1];
    if (needle_len == 1) {
        return (char *)memchr(p, *needle, (end-p));
    }
    if (needle_len > end-haystack) {
        return null;
    }
    end -= needle_len;
    while (p <= end) {
        if ((p = (char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
            if (!memcmp(needle, p, needle_len-1)) {
                return p;
            }
        }
        if (p == null) {
            return null;
        }
        p++;
    }
    return null;
}

核心函数

memchr memcmp

zend_memnstr 代码分析

举例:

strstr('hello word!','world');
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
char *haystack = "hello word!";
char *needle = "world";
int needle_len = strlen(needle);
char *end = haystack + strlen(haystack) 尾部指针
char *p = haystack 字符首元素地址
char ne = needle[needle_len-1] needle 尾部单个字符 d
end -= needle_len  // 初始:4231185 减后:4231180
(p = (char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]
p = (char *)memchr(p, *needle, (end-p+1) // char *p = "world!";
ne == p[needle_len-1] // p[needle_len-1] == d
if (!memcmp(needle, p, needle_len-1)) //world == world
return p

引用

https://www.runoob.com/cprogramming/c-function-memcmp.html

以上就是php strstr源码分析的详细内容,更多关于php strstr的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com