今天和同事在讨论关键字过虑的算法实现,前几天刚看过布隆过滤算法,于是就想起我们公司内部的查找关键字程序,好奇是怎么实现的。于是查找了一下源代码,原来可以简单地用stripos函数查找,
<?php if(substr(php_sapi_name(),0,6)=='cli'){ //命令行模式 global $argv; $function = $argv[1]; }else{ //网页方式 $function = $_GET['name']; } $extensions = get_loaded_extensions(); foreach($extensions as $t){ $modules_funcs = get_extension_funcs($t); if(in_array($function, (array)$modules_funcs)){ $is_found = true; echo "$function is in $t module\n"; } } if(!$is_found)echo "$function not found"; ?> |
PHP_FUNCTION(stripos) { char *found = NULL; char *haystack; int haystack_len; long offset = 0; char *needle_dup = NULL, *haystack_dup; char needle_char[2]; zval *needle; 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 (haystack_len == 0) { RETURN_FALSE; } haystack_dup = estrndup(haystack, haystack_len); //与大小写无关,所以先把字符全部转换成小写 php_strtolower(haystack_dup, haystack_len); if (Z_TYPE_P(needle) == IS_STRING) { //第二个参数如果是字符串 if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > haystack_len) { efree(haystack_dup); RETURN_FALSE; } needle_dup = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle)); php_strtolower(needle_dup, Z_STRLEN_P(needle)); //这个是关键,由php_memnstr实现 found = php_memnstr(haystack_dup + offset, needle_dup, Z_STRLEN_P(needle), haystack_dup + haystack_len); } else { //第二个参数是数字的话,则强制转换成(char)类型 switch (Z_TYPE_P(needle)) { case IS_LONG: case IS_BOOL: needle_char[0] = tolower((char) Z_LVAL_P(needle)); break; case IS_DOUBLE: needle_char[0] = tolower((char) Z_DVAL_P(needle)); break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "needle is not a string or an integer"); efree(haystack_dup); RETURN_FALSE; break; } needle_char[1] = '\0'; found = php_memnstr(haystack_dup + offset, needle_char, sizeof(needle_char) - 1, haystack_dup + haystack_len); } efree(haystack_dup); if (needle_dup) { efree(needle_dup); } if (found) { //如何找到,则返回在这个字符串中的位置 RETURN_LONG(found - haystack_dup); } else { RETURN_FALSE; } } |
static inline char * zend_memnstr(char *haystack, char *needle, int needle_len, char *end) { char *p = haystack; char ne = needle[needle_len-1]; 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; } |