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 }