PHP?strstr函數原型源碼分析
文件位置 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 *haystackchar *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).type4、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.len5、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.hstatic 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舉例:
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 尾部單個字符 dend -= 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] == dif (!memcmp(needle, p, needle_len-1)) //world == worldreturn 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的資料請關注好吧啦網其它相關文章!