我要把explode函数的功能分离出来
ext/string.c里有函数PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, int limit)
PHPAPI是什么?这个以后找到了再说
zval是什么?在/Zend/zend.h这个文件里,定义了zval的struct
struct _zval_struct {
继续看explode这个函数
char *p1, *p2, *endp;
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
查找Z_STRVAL_P,在/Zend/zend_operators.h这个文件里
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
ok,找到了。
继续看explode这个函数
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
查找php_memnstr,在/Zend/zend_operators.h这个文件里
137行
static inline char *
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
zend_memnstr这个函数比较查找字串的方法十分巧妙,简洁而有力。
找到位置后
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
用add_next_index_stringl这个函数把结果存入return_value , return_value 也是个zval类型的变量。
它或者是个全局的变量,因为我没有在PHP_FUNCTION(explode)这个函数里发现它初始化的地方。
add_next_index_stringl这个函数在/Zend/zend_API.c里1144行。
麻烦了,在这个函数里又碰到了几个函数,我靠
ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate)
{
zval *tmp;
MAKE_STD_ZVAL(tmp);
ZVAL_STRINGL(tmp, str, length, duplicate);
return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
}
zend_hash_next_index_insert在/Zend/zend_hash.h里定义
116行
#define zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
_zend_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
打开/Zend/zend_hash.c
终于找到了一个复杂的函数,看起来对我们来说应该也是终结的函数了。
342行
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void
zval有个属性就是HashTable的。
HashTable在zend_hash.h里定义
60行
未完待续