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 ...
随机推荐
- iOS AES-CBC、AES-ECB 加解密
简介 AES是加密的算法,使用128.192 和 256 位密钥,将被加密数据划分为128位(16字节)一块,然后使用某种加密模式进行加密 关键词: 块大小:16字节 密钥长度:AES算法下,key的 ...
- jquery.fileupload-image-editor.js
jquery.fileupload-image-editor.js中 _initEventHandlers: function () { this._super(); var handlers = { ...
- es6 语法的
es5 中提供了 两个声明变量的方式 var function es6 中提供了 四种声明变量的方式 let const class import 现在,定义变量的关键字有 6 个了 备注:不能忽略函 ...
- Array Stack Implement using C
- leetcode-mid-design-380. Insert Delete GetRandom O(1)
mycode import random class RandomizedSet(object): def __init__(self): """ Initialize ...
- 怎么用jira写bug
工具/原料 有网的电脑 方法/步骤1: 打开公司给的访问JIRA的链接,输入公司给你注册的账号和密码,点击登录 方法/步骤2: 点击JIRA主菜单上的“创建”,进入编辑bug界面 方法/步骤3: 项目 ...
- 测开之路一百四十七:用WTForms实现编辑功能
接上一篇的内容 把原先的数据库模型全部给默认值,后面form赋值的时候就不用传位置参数了 把视图逻辑修改一下 # 视图层from datetime import datetimefrom flask. ...
- Maven使用WEB-INF/lib下面的jar编译和打包
在某些情况下,maven无法下载依赖的jar,或者依赖的m2会非常的大,上G那是随随便便的事.为了方便修改和编译,在打出的war包基础上,或者直接把tomcat的webapps下的项目拿出来,就可以用 ...
- Java面试题集(86-115)
Java程序员面试题集(86-115) 摘要:下面的内容包括Struts 2和Hibernate的常见面试题,虽然Struts 2在2013年6月曝出高危漏洞后已经显得江河日下,而Spring MVC ...
- Java之类的继承
说起来Java的类,不得不说以下几个方面:继承.转型.重写.多态和接口. 今天来说一说继承,转型和重写几个方面: 继承(extends)即子类继承父类,就好比玻璃杯.保温杯等子类继承了杯子这个父类,子 ...