php strpose_php strpos 字符串查找函数内部源码实现

此函数查找字符串从前面开始查找。

此函数对应的c函数的代码为:ext/standard/string.c

/* {{{ proto int strpos(string haystack, string needle [, int offset])    Finds position of first occurrence of a string within another */

PHP_FUNCTION(strpos)

{

zval *needle;

char *haystack;

char *found = NULL;

char  needle_char[2];

long  offset = 0;

int   haystack_len;     /* "

sz|l" 表示一个字符串(如果是一个字符串的话,根据zend_parse_parameters的用法,那么haystack后面的第二个参数就是个int类型,也就是haystack的长度haystack_len),一个zval,再加一个可选的long型,因此用"sz|l"来表示。

如果想实现可选参数的话,例如一个字符串,一个浮点,再加一个可选的bool型,可以用"sd|b"来表示。*/

if (zend_parse_parameters(ZEND_NUM_ARGS()

TSRMLS_CC, "sz|l", &haystack, &haystack_len, &needle, &offset) == FAILURE) {

return;

}

if (offset < 0 || offset > haystack_len) {

php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");

RETURN_FALSE;

}

if (Z_TYPE_P(needle) == IS_STRING) {

if (!Z_STRLEN_P(needle)) {

php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty needle");

RETURN_FALSE;

}

found =

php_memnstr(haystack + offset,

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 + offset,

needle_char,

1,

haystack + haystack_len);

}

if (found) {

RETURN_LONG(found - haystack);

} else {

RETURN_FALSE;

}

}

/* }}} */

其中红色函数:php_memnstr则是在main/php.h定义的:#define php_memnstr zend_memnstr,那么就需要找zend_memnstr的位置,通过搜索此函数的位置在:和ext通缉的Zend/zend_operators.h里面实现的。

//此函数的作用是在haystack中查找needle,如果不存在返回null,如果存在,返回指向haystack中needle头字符的指针

static inline char *zend_memnstr(char *haystack, char *needle, int needle_len, char *end)

{

//p代表haystack字符串首地址位置

char *p = haystack;

//needle尾字符

char ne = needle[needle_len-1];

//如果needle中只有1个字符,调用c中memchr查找

if (needle_len == 1) {

return (char *)memchr(p, *needle, (end-p));

}

if (needle_len > end-haystack) {

return NULL;

}

//查找头字符memchr时,最长end - needle_len

end -= needle_len;

while (p <= end) {

//在p中前end-p+1(即haystack_len+1)个字节查找*needle的头字符,如果找到,并且尾字符一致时

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的指针指向下一个字符。

p++;

}

return NULL;

}

/*

Searches atbufferfor the given character, stopping whencharacterisfirst found or cnt bytes have been searched through.

从buffer所指内存区域的前count个字节查找字符ch,当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL。

*/

void* my_memchr(const void * buffer,int ch,int count)

{

while ( count && (*(unsigned char *)buffer != (unsigned char)ch) )

{

buffer = (unsigned char *)buffer + 1;

count--;

}

return(count ? (void *)buffer : NULL);

}

/************************************************************************/

/* 字符串函数memcmp

原型:extern int memcmp(void *buf1, void *buf2, unsigned int count);

功能:比较内存区域buf1和buf2的前count个字节

说明:当buf1

当buf1=buf2时,返回值=0

当buf1>buf2时,返回值>0                                        */

源程序:

int memcmp(const void * cs,const void * ct,size_t count)

{

const unsigned char *su1, *su2;

int res = 0;

for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)

if ((res = *su1 - *su2) != 0)

break;

return res;

}

/************************************************************************/

附上函数zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"ss", &r1, &n, &r2, &m)

其中ss的含义在以下类型表格中说明,

类型说明见下表:

Boolean

b

zend_bool

Long

l

long

Double

d

double

String

s

char*, int

Resource

r

zval*

Array

a

zval*

Object

o

zval*

zval

z

zval*

由此可见如果类型为string的话,那么需要一个字符串的指针和一个int值。

另注释:转载自]中TSRMLS_CC的含义,请参考以下文章:http://bbs.phpchina.com/thread-185497-1-1.html;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值