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():ui

 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():spa

 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():code

 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 }
相關文章
相關標籤/搜索