此函数查找字符串从前面开始查找。
此函数对应的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 at bufferfor the given character, stopping when characteris first 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<buf2时,返回值<0 当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;
|