php内置函数分析之current()、next()、prev()、reset()、end()
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()的更多相关文章
- map内置函数分析所得到的思路
map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...
- php内置函数分析之array_diff_assoc()
static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...
- php内置函数分析之array_combine()
PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...
- php内置函数分析之array_chunk()
PHP_FUNCTION(array_chunk) { int argc = ZEND_NUM_ARGS(), num_in; zend_long size, current = ; zend_str ...
- php内置函数分析之ucwords()
PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...
- php内置函数分析之strtoupper()、strtolower()
strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...
- php内置函数分析之ucfirst()、lcfirst()
ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...
- php内置函数分析之trim()
官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...
- php内置函数分析之str_pad()
PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...
随机推荐
- chrome 调试
https://developers.google.com/web/tools/chrome-devtools/javascript/step-code step over next function ...
- iOS应用将强制使用HTTPS安全加密-afn配置https(190926更新)
WWDC 2016苹果开发者大会上,苹果在讲解全新的iOS10中提到了数据安全这一方面,并且苹果宣布iOS应用将从2017年1月起启用名为App Transport Security的安全传输功能. ...
- apue 在 mac 环境编译错误
参考资料:https://unix.stackexchange.com/questions/105483/compiling-code-from-apue 笔者使用 mac 学习 apue, 在编译的 ...
- HTML5 列表、表格、媒体元素
无序列表 <ul> <li>范冰冰演藏族女孩</li> <li>拍集体合影后自拍</li> <li>诗隆甜蜜出游</li& ...
- TCP/IP笔记——UDP
OSI模型中最下面的两层用来解决两个硬件设备在物理上的通信问题(如规定怎么将电平信号转换为数字信号),相对应的TCP/IP模型中,这部分代表将会将机器封装为一个MAC地址来实现通讯.网络层是关于,具体 ...
- mysql中的范式
范式 范式:Normal Format,是一种离散数学中的知识,是为了解决数据的存储与优化的问题:保存数据的存储之后,凡是能够通过关系寻找出来的数据,坚决不再重复存储,终极目标是为了减少数据的冗余.范 ...
- springboot工程启动时,报错:No bean named 'shiroFilter' available
在启动Springboot项目时,报错:org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ' ...
- Ubuntu 解决wifi无法打开的问题 安装NVIDIA显卡驱动的正确姿势
游戏本型号Y7000 win10 Ubuntu16.04双系统 解决wifi无法打开的问题 解决方法: 1.打开终端输入:rfkill list all 出现如下提示:: 可以看到,优先级 ...
- I - The Values You Can Make (背包求具体方案)
题目大意 给你n个数,让你用这n个数在组成k的情况下,找到所有的value,这些value也由这n个数组成,且这些value组合在一起能够组成k 解法 看到题目我的想法就是母函数= =不过wa了,后来 ...
- 豆壳CMS本地安装教程
DouPHP安装教程 一.下载DouPHP程序. 解压后得到三个文件夹 将upload文件夹里面的内容复制到wamp的www的文件夹. 二.打开浏览器,输入127.0.0.1. 勾选后选择下一步 注意 ...