PHP strstr函数原型源码分析

2023-12-08 0 686
目录
  • strstr
    • 函数原型
  • 源码分析 版本PHP5.3.29
    • 1、ext/standard/php_string.h
    • 2、ext/standard/string.c
  • zval *needle
    • 1、char *haystack
    • 2、zend_parse_parameters
    • 3、if (Z_TYPE_P(needle) == IS_STRING)
    • 4、if (!Z_STRLEN_P(needle)) {
    • 5、php_memnstr(haystack, Z_STRVAL_P(needle), Z_STRLEN_P(needle), haystack + haystack_len);
  • 核心函数
    • zend_memnstr 代码分析

strstr

函数原型

PHP 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 Booleanl 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

PHP strstr函数原型源码分析

PHP strstr函数原型源码分析

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

https://www.jb51.net/article/77667.htm

https://www.jb51.net/article/210253.htm

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

您可能感兴趣的文章:

  • php常用字符串查找函数strstr()与strpos()实例分析
  • php学习笔记之mb_strstr的基本使用
  • PHP中检索字符串的方法分析【strstr与substr_count方法】
  • PHP中strpos、strstr和stripos、stristr函数分析
  • PHP使用strstr()函数获取指定字符串后所有字符的方法
  • php字符串函数学习之strstr()

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 PHP PHP strstr函数原型源码分析 https://www.u-9.cn/biancheng/php/128216.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务