current()初始指向插入到数组中的第一个单元
next() 将数组的内部指针向前移动一位
prev() 将数组的内部指针倒回一位
reset() 将数组的内部指针指向第一个单元
end() 将数组的内部指针指向最后一个单元

current():

 PHP_FUNCTION(current)
{
HashTable *array;
zval *entry; #ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_ARRAY_OR_OBJECT_HT(array)
ZEND_PARSE_PARAMETERS_END();
#endif
// 获取内部指针指向的当前单元
if ((entry = zend_hash_get_current_data(array)) == NULL) {
RETURN_FALSE;
} if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
} ZVAL_DEREF(entry);
ZVAL_COPY(return_value, entry);
}
 #define zend_hash_get_current_data(ht) \
zend_hash_get_current_data_ex(ht, &(ht)->nInternalPointer)
 ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx = *pos;
Bucket *p; IS_CONSISTENT(ht);
if (idx != HT_INVALID_IDX) {
p = ht->arData + idx; // 数组首地址加偏移量
return &p->val;
} else {
return NULL;
}
}

next():

 PHP_FUNCTION(next)
{
HashTable *array;
zval *entry; #ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, , )
ZEND_PARSE_PARAMETERS_END();
#endif // 向前移动指针
zend_hash_move_forward(array); if (USED_RET()) {
// 获取指针指向的单元
if ((entry = zend_hash_get_current_data(array)) == NULL) {
RETURN_FALSE;
} if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
} ZVAL_DEREF(entry);
ZVAL_COPY(return_value, entry);
}
}
 #define zend_hash_move_forward(ht) \
zend_hash_move_forward_ex(ht, &(ht)->nInternalPointer)
 ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx = *pos; IS_CONSISTENT(ht);
HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == ); if (idx != HT_INVALID_IDX) {
while () {
idx++;
if (idx >= ht->nNumUsed) { // 内部指针超出单元列表的末端(idx从0开始)
*pos = HT_INVALID_IDX; // 保存内部指针为HT_INVALID_IDX
return SUCCESS;
}
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { // 内部指针向前移动后,指向的是有效元素
*pos = idx; // 保存内部指针
return SUCCESS;
}
}
} else {
return FAILURE;
}
}

prev():

 PHP_FUNCTION(prev)
{
HashTable *array;
zval *entry; #ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, , )
ZEND_PARSE_PARAMETERS_END();
#endif
// 内部指针倒回一位
zend_hash_move_backwards(array); if (USED_RET()) {
// 获取当前指针指向的单元
if ((entry = zend_hash_get_current_data(array)) == NULL) {
RETURN_FALSE;
} if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
} ZVAL_DEREF(entry);
ZVAL_COPY(return_value, entry);
}
}
 #define zend_hash_move_backwards(ht) \
zend_hash_move_backwards_ex(ht, &(ht)->nInternalPointer)
 ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx = *pos; IS_CONSISTENT(ht);
HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == ); if (idx != HT_INVALID_IDX) {
while (idx > ) {
idx--;
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { // 内部指针指向的单元有效
*pos = idx;
return SUCCESS;
}
}
// 指针倒回一位后没有找到有效的单元
*pos = HT_INVALID_IDX;
return SUCCESS;
} else {
return FAILURE;
}
}

reset():

 PHP_FUNCTION(reset)
{
HashTable *array;
zval *entry; #ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, , )
ZEND_PARSE_PARAMETERS_END();
#endif // 将内部指针指向第一个单元
zend_hash_internal_pointer_reset(array); if (USED_RET()) {
if ((entry = zend_hash_get_current_data(array)) == NULL) {
RETURN_FALSE;
} if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
} ZVAL_DEREF(entry);
ZVAL_COPY(return_value, entry);
}
}
 #define zend_hash_internal_pointer_reset(ht) \
zend_hash_internal_pointer_reset_ex(ht, &(ht)->nInternalPointer)
 ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx; IS_CONSISTENT(ht);
HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == ); // 内部指针指向数组的一个第一个有效单元
for (idx = ; idx < ht->nNumUsed; idx++) {
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
*pos = idx;
return;
}
}
*pos = HT_INVALID_IDX;
}

end():

 PHP_FUNCTION(end)
{
HashTable *array;
zval *entry; #ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(, )
Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, , )
ZEND_PARSE_PARAMETERS_END();
#endif
// 将数组的内部指针指向最后一个单元
zend_hash_internal_pointer_end(array); if (USED_RET()) {
if ((entry = zend_hash_get_current_data(array)) == NULL) {
RETURN_FALSE;
} if (Z_TYPE_P(entry) == IS_INDIRECT) {
entry = Z_INDIRECT_P(entry);
} ZVAL_DEREF(entry);
ZVAL_COPY(return_value, entry);
}
}
 #define zend_hash_internal_pointer_end(ht) \
zend_hash_internal_pointer_end_ex(ht, &(ht)->nInternalPointer)
 ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx; IS_CONSISTENT(ht);
HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == ); // idx从最后一个Bucket开始,第一个出现的有效单元就是数组的末元素
idx = ht->nNumUsed;
while (idx > ) {
idx--;
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
*pos = idx;
return;
}
}
*pos = HT_INVALID_IDX;
}

php内置函数分析之current()、next()、prev()、reset()、end()的更多相关文章

  1. map内置函数分析所得到的思路

    map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...

  2. php内置函数分析之array_diff_assoc()

    static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...

  3. php内置函数分析之array_combine()

    PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...

  4. php内置函数分析之array_chunk()

    PHP_FUNCTION(array_chunk) { int argc = ZEND_NUM_ARGS(), num_in; zend_long size, current = ; zend_str ...

  5. php内置函数分析之ucwords()

    PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...

  6. php内置函数分析之strtoupper()、strtolower()

    strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...

  7. php内置函数分析之ucfirst()、lcfirst()

    ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...

  8. php内置函数分析之trim()

    官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...

  9. php内置函数分析之str_pad()

    PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...

随机推荐

  1. 开发-日常工具:TFS(Team Foundation Server)

    ylbtech-开发-日常工具:TFS(Team Foundation Server) TFS(Team Foundation Server)是一个高可扩展.高可用.高性能.面向互联网服务的分布式文件 ...

  2. 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_2 Mybatis的CRUD-保存操作

    增加的方法 修改映射配置 id是方法名 按照原来jdbc的写法 values里面应该是一堆问号,现在这里不能再去写问号了因为要取值 从我们要执行的方法传的参数里面去取值 所以参数的类型我们必须要告诉这 ...

  3. Delphi中的进制转换

    二进制转换 function binToDec(Value: string): integer; var str: string; i: integer; begin Str := UpperCase ...

  4. 汇编语言——DOSBox 学习网址整理

    汇编语言--使用DOSBox写一个HelloWorld https://blog.csdn.net/whatiwhere/article/details/8035910 windows下汇编工具--d ...

  5. js五种不同的遍历 (filter, map,foreach,every, some,)

    var arr=[1,2,"a",2,4,1,4,"a",5,6,7,8,"aa","bb","c" ...

  6. Java基础语法—数据输入

    我们可以通过 Scanner 类来获取用户的输入.使用步骤如下: 1.导包.Scanner 类在java.util包下,所以需要将该类导入.导包的语句需要定义在类的上面. import java.ut ...

  7. 递归 dfs 记忆化搜索 动态规划

    今天做洛谷P1434 [SHOI2002]滑雪 的时候仔细想了想记忆化搜索 现在总结一下 为了描述问题的某一状态,必须用到该状态的上一状态,而描述上一状态,又必须用到上一状态的上一状态……这种用自已来 ...

  8. [转帖]Docker从入门到动手实践

    Docker从入门到动手实践 https://www.cnblogs.com/nsky/p/10853194.html dockerfile的图很好呢. 但是自己没有做实验 , 其实知识都挺好. do ...

  9. [转帖]Windows下cwRsyncServer双机连续同步部署

    Windows下cwRsyncServer双机连续同步部署 https://www.cnblogs.com/nulige/p/7607503.html 找时间做一下测试 应该能更好的实现 自动部署的功 ...

  10. 《剑指offer》面试题23 从上往下打印二叉树 Java版

    注意层序遍历的时候对每一层的处理方式可能不同,这里把每一层的元素保存进一个List中了,那么就需要记录每一层的数量. public List<List<Integer>> se ...