PHP?strstr函數(shù)原型源碼分析
strstr
函數(shù)原型

源碼分析 版本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是一個(gè)變量結(jié)構(gòu)體,對(duì)應(yīng)php strstr 函數(shù)參數(shù) mixed $needle
1、char *haystack
char *haystack s是一個(gè)字符指針,對(duì)應(yīng) php strstr函數(shù)參數(shù) 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;
}最簡(jiǎn)單的獲取函數(shù)調(diào)用者傳遞過(guò)來(lái)的參數(shù)便是使用zend_parse_parameters()函數(shù)。
zend_parse_parameters() 函數(shù)的前幾個(gè)參數(shù)我們直接用內(nèi)核里宏來(lái)生成便可以了,形式為:ZEND_NUM_ARGS() TSRMLS_CC,注意兩者之間有個(gè)空格,但是沒(méi)有逗號(hào)。從名字可以看出,ZEND_NUM_ARGS()代表著參數(shù)的個(gè)數(shù)。
緊接著需要傳遞給zend_parse_parameters()函數(shù)的參數(shù)是一個(gè)用于格式化的字符串,就像printf的第一個(gè)參數(shù)一樣。下面表示了最常用的幾個(gè)符號(hào)。
type_spec是格式化字符串,其常見(jiàn)的含義如下:
參數(shù) 代表著的類型
b Boolean
l Integer 整型
d Floating point 浮點(diǎn)型
s String 字符串
r Resource 資源
a Array 數(shù)組
o Object instance 對(duì)象
O Object instance of a specified type 特定類型的對(duì)象
z Non-specific zval 任意類型~
Z zval**類型
f 表示函數(shù)、方法名稱,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;
}核心函數(shù)
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 尾部單個(gè)字符 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
http://m.fzitv.net/article/77667.htm
http://m.fzitv.net/article/210253.htm
以上就是PHP strstr源碼分析的詳細(xì)內(nèi)容,更多關(guān)于PHP strstr的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php如何把表單內(nèi)容提交到數(shù)據(jù)庫(kù)
這篇文章主要介紹了php如何吧表單內(nèi)容提交到數(shù)據(jù)庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
基于 Swoole 的微信掃碼登錄功能實(shí)現(xiàn)代碼
隨著微信的普及,掃碼登錄方式越來(lái)越被現(xiàn)在的應(yīng)用所使用。它因?yàn)椴挥萌ビ涀∶艽a,只要有微信號(hào)即可方便快捷登錄.這里基于微信公眾平臺(tái)的帶參數(shù)臨時(shí)二維碼,并且結(jié)合 Swoole 的 WebSocket 服務(wù)實(shí)現(xiàn)掃碼登錄2018-01-01
yii2中使用webuploader實(shí)現(xiàn)圖片上傳的實(shí)戰(zhàn)項(xiàng)目
本篇文章主要主要介紹了yii2中使用webuploader實(shí)現(xiàn)圖片上傳的實(shí)戰(zhàn)項(xiàng)目,具有一定的參考價(jià)值,有興趣的同學(xué)可以了解一下2017-09-09
PHP獲取當(dāng)前時(shí)間的5種實(shí)現(xiàn)方式
這篇文章主要介紹了PHP獲取當(dāng)前時(shí)間的5種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
在Mac OS的PHP環(huán)境下安裝配置MemCache的全過(guò)程解析
這篇文章主要介紹了在Mac OS的PHP環(huán)境下安裝配置MemCache的全過(guò)程解析,MemCache是一套分布式的高速緩存系統(tǒng),需要的朋友可以參考下2016-02-02
laravel 時(shí)間格式轉(zhuǎn)時(shí)間戳的例子
今天小編就為大家分享一篇laravel 時(shí)間格式轉(zhuǎn)時(shí)間戳的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
讓CodeIgniter數(shù)據(jù)庫(kù)緩存自動(dòng)過(guò)期的處理的方法
按官方的說(shuō)法,緩存設(shè)置后永不過(guò)期,除非你調(diào)用方法主動(dòng)刪除。這篇文章主要介紹了CodeIgniter數(shù)據(jù)庫(kù)緩存自動(dòng)過(guò)期的處理,需要的朋友可以參考下2014-06-06
php實(shí)現(xiàn)微信小程序授權(quán)登錄功能(實(shí)現(xiàn)流程)
這篇文章主要介紹了php實(shí)現(xiàn)微信小程序授權(quán)登錄功能,本文通過(guò)一段詳細(xì)的代碼給大家講解的非常詳細(xì),需要的朋友參考下2019-11-11

