php内置函数分析之current()、next()、prev()、reset()、end()

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

current():

 1 PHP_FUNCTION(current)
 2 {
 3     HashTable *array;
 4     zval *entry;
 5 
 6 #ifndef FAST_ZPP
 7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
 8         return;
 9     }
10 #else
11     ZEND_PARSE_PARAMETERS_START(1, 1)
12         Z_PARAM_ARRAY_OR_OBJECT_HT(array)
13     ZEND_PARSE_PARAMETERS_END();
14 #endif
15     // 获取内部指针指向的当前单元
16     if ((entry = zend_hash_get_current_data(array)) == NULL) {
17         RETURN_FALSE;
18     }
19 
20     if (Z_TYPE_P(entry) == IS_INDIRECT) {
21         entry = Z_INDIRECT_P(entry);
22     }
23 
24     ZVAL_DEREF(entry);
25     ZVAL_COPY(return_value, entry);
26 }
1 #define zend_hash_get_current_data(ht) \
2     zend_hash_get_current_data_ex(ht, &(ht)->nInternalPointer)
 1 ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
 2 {
 3     uint32_t idx = *pos;
 4     Bucket *p;
 5 
 6     IS_CONSISTENT(ht);
 7     if (idx != HT_INVALID_IDX) {
 8         p = ht->arData + idx; // 数组首地址加偏移量
 9         return &p->val;
10     } else {
11         return NULL;
12     }
13 }

next():

 1 PHP_FUNCTION(next)
 2 {
 3     HashTable *array;
 4     zval *entry;
 5 
 6 #ifndef FAST_ZPP
 7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
 8         return;
 9     }
10 #else
11     ZEND_PARSE_PARAMETERS_START(1, 1)
12         Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
13     ZEND_PARSE_PARAMETERS_END();
14 #endif
15 
16     // 向前移动指针
17     zend_hash_move_forward(array);
18 
19     if (USED_RET()) {
20         // 获取指针指向的单元
21         if ((entry = zend_hash_get_current_data(array)) == NULL) {
22             RETURN_FALSE;
23         }
24 
25         if (Z_TYPE_P(entry) == IS_INDIRECT) {
26             entry = Z_INDIRECT_P(entry);
27         }
28 
29         ZVAL_DEREF(entry);
30         ZVAL_COPY(return_value, entry);
31     }
32 }
1 #define zend_hash_move_forward(ht) \
2     zend_hash_move_forward_ex(ht, &(ht)->nInternalPointer)
 1 ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
 2 {
 3     uint32_t idx = *pos;
 4 
 5     IS_CONSISTENT(ht);
 6     HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
 7 
 8     if (idx != HT_INVALID_IDX) {
 9         while (1) {
10             idx++;
11             if (idx >= ht->nNumUsed) { // 内部指针超出单元列表的末端(idx从0开始)
12                 *pos = HT_INVALID_IDX; // 保存内部指针为HT_INVALID_IDX
13                 return SUCCESS;
14             }
15             if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { // 内部指针向前移动后,指向的是有效元素
16                 *pos = idx; // 保存内部指针
17                 return SUCCESS;
18             }
19         }
20     } else {
21          return FAILURE;
22     }
23 }

prev():

 1 PHP_FUNCTION(prev)
 2 {
 3     HashTable *array;
 4     zval *entry;
 5 
 6 #ifndef FAST_ZPP
 7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
 8         return;
 9     }
10 #else
11     ZEND_PARSE_PARAMETERS_START(1, 1)
12         Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
13     ZEND_PARSE_PARAMETERS_END();
14 #endif
15     // 内部指针倒回一位
16     zend_hash_move_backwards(array);
17 
18     if (USED_RET()) {
19         // 获取当前指针指向的单元
20         if ((entry = zend_hash_get_current_data(array)) == NULL) {
21             RETURN_FALSE;
22         }
23 
24         if (Z_TYPE_P(entry) == IS_INDIRECT) {
25             entry = Z_INDIRECT_P(entry);
26         }
27 
28         ZVAL_DEREF(entry);
29         ZVAL_COPY(return_value, entry);
30     }
31 }
1 #define zend_hash_move_backwards(ht) \
2     zend_hash_move_backwards_ex(ht, &(ht)->nInternalPointer)
 1 ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
 2 {
 3     uint32_t idx = *pos;
 4 
 5     IS_CONSISTENT(ht);
 6     HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
 7 
 8     if (idx != HT_INVALID_IDX) {
 9         while (idx > 0) {
10             idx--;
11             if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) { // 内部指针指向的单元有效
12                 *pos = idx;
13                 return SUCCESS;
14             }
15         }
16         // 指针倒回一位后没有找到有效的单元
17         *pos = HT_INVALID_IDX;
18          return SUCCESS;
19     } else {
20          return FAILURE;
21     }
22 }

reset():

 1 PHP_FUNCTION(reset)
 2 {
 3     HashTable *array;
 4     zval *entry;
 5 
 6 #ifndef FAST_ZPP
 7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
 8         return;
 9     }
10 #else
11     ZEND_PARSE_PARAMETERS_START(1, 1)
12         Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
13     ZEND_PARSE_PARAMETERS_END();
14 #endif
15 
16     // 将内部指针指向第一个单元
17     zend_hash_internal_pointer_reset(array);
18 
19     if (USED_RET()) {
20         if ((entry = zend_hash_get_current_data(array)) == NULL) {
21             RETURN_FALSE;
22         }
23 
24         if (Z_TYPE_P(entry) == IS_INDIRECT) {
25             entry = Z_INDIRECT_P(entry);
26         }
27 
28         ZVAL_DEREF(entry);
29         ZVAL_COPY(return_value, entry);
30     }
31 }
1 #define zend_hash_internal_pointer_reset(ht) \
2     zend_hash_internal_pointer_reset_ex(ht, &(ht)->nInternalPointer)
 1 ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
 2 {
 3     uint32_t idx;
 4 
 5     IS_CONSISTENT(ht);
 6     HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
 7 
 8     // 内部指针指向数组的一个第一个有效单元
 9     for (idx = 0; idx < ht->nNumUsed; idx++) {
10         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
11             *pos = idx;
12             return;
13         }
14     }
15     *pos = HT_INVALID_IDX;
16 }

end():

 1 PHP_FUNCTION(end)
 2 {
 3     HashTable *array;
 4     zval *entry;
 5 
 6 #ifndef FAST_ZPP
 7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
 8         return;
 9     }
10 #else
11     ZEND_PARSE_PARAMETERS_START(1, 1)
12         Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
13     ZEND_PARSE_PARAMETERS_END();
14 #endif
15     // 将数组的内部指针指向最后一个单元
16     zend_hash_internal_pointer_end(array);
17 
18     if (USED_RET()) {
19         if ((entry = zend_hash_get_current_data(array)) == NULL) {
20             RETURN_FALSE;
21         }
22 
23         if (Z_TYPE_P(entry) == IS_INDIRECT) {
24             entry = Z_INDIRECT_P(entry);
25         }
26 
27         ZVAL_DEREF(entry);
28         ZVAL_COPY(return_value, entry);
29     }
30 }
1 #define zend_hash_internal_pointer_end(ht) \
2     zend_hash_internal_pointer_end_ex(ht, &(ht)->nInternalPointer)
 1 ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
 2 {
 3     uint32_t idx;
 4 
 5     IS_CONSISTENT(ht);
 6     HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
 7 
 8     // idx从最后一个Bucket开始,第一个出现的有效单元就是数组的末元素
 9     idx = ht->nNumUsed;
10     while (idx > 0) {
11         idx--;
12         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
13             *pos = idx;
14             return;
15         }
16     }
17     *pos = HT_INVALID_IDX;
18 }

猜你喜欢

转载自www.cnblogs.com/natian-ws/p/9154264.html
今日推荐