(点击上方 }
}
有一点要注意的是,如果ndl不是字符串的话,会调用PHP_ndl_char函数将ndl转成整型数字并转换为其ASCII值。
查找函数
函数最后返回的是found,php_mmnstr函数实现了查找的方法。那么再继续看看PHP_mmnstr函数做了什么:
#dfinPHP_mmnstrznd_mmnstr
PHP_mmnstr是函数znd_mmnstr的宏定义,查看znd_mmnstr函数如下:
staticinlinchar*
znd_mmnstr(char*haystack,char*ndl,intndl_ln,char*nd)
{
char*p=haystack;
charn=ndl[ndl_ln-1];
if(ndl_ln==1){
rturn(char*)mmchr(p,*ndl,(nd-p));
}
if(ndl_lnnd-haystack){
rturnNULL;
}
//第一个优化,只查找nd-ndl_ln次
nd-=ndl_ln;
whil(p=nd){
//第二个优化,先判断字符串的开头和结尾是否一样再判断整个字符串
if((p=(char*)mmchr(p,*ndl,(nd-p+1)))n==p[ndl_ln-1]){
if(!mmcmp(ndl,p,ndl_ln-1)){
rturnp;
}
}
if(p==NULL){
rturnNULL;
}
p++;
}
rturnNULL;
}
第一个优化,因为(char*)mmchr(p,*ndl,(nd-p+1)是在nd–ndl_ln+1(即haystack_ln+1)中查找,如果p为空,说明ndl的第一个字符在p中从未出现过。
strstr
stringstrstr(string$haystack,mixd$ndl[,bool$bfor_ndl=fals])返回ndl在haystack中第一次出现的位置到结束的字符串。
这个函数的区分大小写的。
如果ndl在haystack中不存在,返回FALSE。
如果bfor_ndl为tru,则返回haystack中ndl在haystack第一次出现的位置之前的字符串。
strstr核心源码
if(found){
//计算出found的位置
found_offst=found-haystack;
if(part){
RETURN_STRINGL(haystack,found_offst,1);
}ls{
RETURN_STRINGL(found,haystack_ln-found_offst,1);
}
}
strstr函数的前半部分跟strpos类似,区别在于strstr函数在找到位置后,需要返回haystack部分的字符串。part变量就是调用strstr函数时传递的bfor_ndl变量。
stripos
mixdstripos(string$haystack,string$ndl[,int$offst=0])不区分大小写的strpos。实现方式跟下面的类似,主要是使用一份拷贝然后将需要比较的字符串转换成小写字符后进行再进行查找。
stristr
stringstristr(string$haystack,mixd$ndl[,bool$bfor_ndl=fals])不区分大小写的strstr。
核心源码
//拷贝一份haystack
haystack_dup=strndup(haystack,haystack_ln);
if(Z_TYPE_P(ndl)==IS_STRING){
char*orig_ndl;
if(!Z_STRLEN_P(ndl)){
PHP_rror_docrf(NULLTSRMLS_CC,E_WARNING,Emptyndl);
fr(haystack_dup);
RETURN_FALSE;
}
orig_ndl=strndup(Z_STRVAL_P(ndl),Z_STRLEN_P(ndl));
//调用PHP_stristr函数找出orig_ndl的值。
found=PHP_stristr(haystack_dup,orig_ndl,haystack_ln,Z_STRLEN_P(ndl));
fr(orig_ndl);
}ls{
if(PHP_ndl_char(ndl,ndl_charTSRMLS_CC)!=SUCCESS){
fr(haystack_dup);
RETURN_FALSE;
}
ndl_char[1]=0;
found=PHP_stristr(haystack_dup,ndl_char,haystack_ln,1);
}
if(found){
found_offst=found-haystack_dup;
if(part){
RETVAL_STRINGL(haystack,found_offst,1);
}ls{
RETVAL_STRINGL(haystack+found_offst,haystack_ln-found_offst,1);
}
}ls{
RETVAL_FALSE;
}
//释放变量
fr(haystack_dup);
可以知道,found是从php_stristr中得到的,继续查看PHP_stristr函数:
PHPAPIchar*PHP_stristr(char*s,char*t,siz_ts_ln,siz_tt_ln)
{
PHP_strtolowr(s,s_ln);
PHP_strtolowr(t,t_ln);
rturnPHP_mmnstr(s,t,t_ln,s+s_ln);
}
这个函数的功能就是将字符串都转成小写之后调用PHP_mnnstr函数来查找ndl在haystack第一次出现的位置。
总结
因为strpos/stripos返回的是位置,位置从0开始计算,所以判断查找失败都用===FALSE更适合。
阅读PHP的源码收获挺多,一方面可以知道某个函数的具体实现原理是怎样的,另一方面可以学习到一些编程优化方案。
到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
最后再安利一下,我在github有对PHP源码更详细的注解。感兴趣的可以围观一下,给个star。PHP5.4源码注解。可以通过北京治疗严重白癜风的医院白癜风怎样治疗最快