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. VC程序禁用提示框

    程序需要24小时不中断 如果错误提示了的话 runtime error 监控程序就不能重启 下面是网上找的 方便以后用到 http://blog.csdn.net/yuzhiyuxia/article ...

  2. ffplay播放PCM裸流

    ffplay -f s16le -ar 48000 -ac 2 d:\lei.pcm

  3. java7和java8新特性

    以下来至网址: http://blog.csdn.net/samjustin1/article/details/52268004 Java7 新特性 1.switch中可以使用字符串了 String ...

  4. 解决VirtualBox虚拟机装XP无声问题的简便办法

    原文地址;http://www.2cto.com/os/201206/134887.html 解决VirtualBox虚拟机装XP无声问题的简便办法 解决VirtualBox虚拟机装XP无声问题的简便 ...

  5. linux shell 中"2>&1"含义-完美理解-费元星

    笨鸟先飞,先理解.   脚本是:      nohup /mnt/Nand3/H2000G  >/dev/null  2>&1  &      对于& 1 更准确的 ...

  6. MYSQL常见安装错误集:[ERROR] --initialize specified but the data directory has files in it. Abort

    1.[ERROR] --initialize specified but the data directory has files in it. Abort [错误] -初始化指定,但数据目录中有文件 ...

  7. python学习笔记:(二)基本数据类型

    python中的变量不需要声明,每个变量中使用前都必须赋值,变量赋值以后该变量才会被创建. 在python中变量就是变量,他没有类型,我们所说的类型是变量所指的内存中对象的类型. python3中有六 ...

  8. oracle data guard --理论知识回顾02

    继上一篇 管理影响物理standby的事件 1 创建表空间或数据文件初始化参数standby_file_management用来控制是否自动将primary数据库增加表空间或数据文件的改动,传播到st ...

  9. Spring MVC 中RequestContextHolder获取request和response

    1.最简单方式:处理方法入参 例如: @RequestMapping("/test") @ResponseBody public void saveTest(HttpServlet ...

  10. 【FICO系列】SAP FICO总账余额相关的事务码

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[FICO系列]SAP FICO总账余额相关的事 ...