PHP源码之explode使用说明

2019-04-09 00:59:45于海丽


PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, long limit)
{
char *p1, *p2, *endp;
//先得到的是源字串的末尾位置的指针
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
//记录开始位置
p1 = Z_STRVAL_P(str);
//下面这个是获得分割符在str中的位置,可以看到在strrpos和strpos中也用到了这个方法去定位
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
if (p2 == NULL) {
//因为这个,所以当我们调用explode('|', 'abc');是合法的,出来的的就是array(0 => 'abc')
add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
} else {
//依次循环获得下一个分隔符的位置,直到结束
do {
//将得到的子字串(上个位置到这个位置中间的一段,第一次的时候上个位置就是开始
add_next_index_stringl(return_value, p1, p2 - p1, 1);
//定位到分隔符位置p2+分隔符的长度的位置
//比如,分隔符='|', 原字串= 'ab|c', p2 = 2, 则p1=2+1=3
p1 = p2 + Z_STRLEN_P(delim);
} while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
--limit > 1);
//将最后的一个分隔符后面的字串放到结果数组中
//explode('|', 'avc|sdf'); => array(0 => 'avc', 1= > 'sdf')
if (p1 <= endp)
add_next_index_stringl(return_value, p1, endp-p1, 1);
}
}

2、limit < 0 :
调用php_explode_negative_limit方法

PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, long limit)
{
#define EXPLODE_ALLOC_STEP 64
char *p1, *p2, *endp;
endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
p1 = Z_STRVAL_P(str);
p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
if (p2 == NULL) {
//它这里竟然没有处理,那explode('|', 'abc', -1) 就成非法的了,获得不了任何值
/*
do nothing since limit <= -1, thus if only one chunk - 1 + (limit) <= 0
by doing nothing we return empty array
*/
} else {
int allocated = EXPLODE_ALLOC_STEP, found = 0;
long i, to_return;
char **positions = emalloc(allocated * sizeof(char *));
//注意这里的positions的声明,这个数组是用来保存所有子字串的读取位置
positions[found++] = p1; //当然起始位置还是需要保存
//下面两个循环,第一个是循环所有在字符串中出现的分隔符位置,并保存下一个子字串读取位置起来
do {
if (found >= allocated) {
allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */
positions = erealloc(positions, allocated*sizeof(char *));
}
positions[found++] = p1 = p2 + Z_STRLEN_P(delim);
} while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL);
//这个就是从数组中开始获得返回的结果将从哪个子字串开始读
to_return = limit + found;
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
相关文章 大家在看