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 ...
随机推荐
- 【HTTP/FTP客户端库】
[HTTP/FTP客户端库]资料来源:http://curl.haxx.se/libcurl/competitors.html Free Software and Open Source projec ...
- angular 的配置文件的应用
为什么要使用 angular 的配置文件: 好处:我们可以在一个页面上,实现多个页面的跳转的感觉,但只是在一个页面上进行的操作: 我们的准备工作:下载 angular-route.js 插件 在依赖模 ...
- HDU4497 GCD and LCM(数论,质因子分解)
HDU4497 GCD and LCM 如果 \(G \% L != 0\) ,那么输出 \(0\) . 否则我们有 \(L/G=(p_1^{r_1})\cdot(p_2^{r_2})\cdot(p_ ...
- idea中git回退本地仓库版本
场景:代码commit到本地仓库,还没有push到远程仓库,这时要回退代码. 介绍下Reset Head中三种Reset Type类型: 1.Mixed(默认):它回退到某个版本,本地会保留源码,回退 ...
- 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID -费元星
在公司做数据分析的时候,发现NA端有很多ID,所有来系统的理解一下,有问题大家多指出 [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番搜索资料+请教大神 ...
- DNS 搜索 - dig 命令
dig 命令_互动百科 示例: # 全部 dig www.zjffun.com # 只显示 ANSWER SECTION dig www.zjffun.com +noall +answer
- oauth2.0协议原理
OAuth的授权不会使用第三方触及到用户的帐号信息(如用户密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAuth是安全的. OAuth的作用:就是让“客户端”安全可控 ...
- windows一次无线网卡被关闭事件
使用的是Dell的笔记本,fn+无线图标莫名的是蓝牙的启动. 有一天突然无线网卡无法上网,无法发现无线网络: 1. 在服务中开启"Wired AutoConfig"以及“WLAN ...
- 【算法与数据结构】二叉堆和优先队列 Priority Queue
优先队列的特点 普通队列遵守先进先出(FIFO)的规则,而优先队列虽然也叫队列,规则有所不同: 最大优先队列:优先级最高的元素先出队 最小优先队列:优先级最低的元素先出队 优先队列可以用下面几种数据结 ...
- media查询(来源于bootstrap)
/* 大屏幕 */@media (min-width: 1200px) { ... } /* 平板电脑和小屏电脑之间的分辨率 */@media (min-width: 768px) and (max- ...