时间:2021-07-01 10:21:17 帮助过:4人阅读
typedef int (*apply_func_t)(void *pDest TSRMLS_DC);
void zend_hash_apply(HashTable *ht,
apply_func_t apply_func TSRMLS_DC);typedef int (*apply_func_arg_t)(void *pDest,
void *argument TSRMLS_DC);
void zend_hash_apply_with_argument(HashTable *ht,
apply_func_arg_t apply_func, void *data TSRMLS_DC);一个是可以传递参数的,还有一个是不传递参数,只传递哈希表中的值的。对于可传递参数的函数而言,在扩展中应用到可能性更大。
回调函数可能有不同的返回值:
int php_sample_print_zval(zval **val TSRMLS_DC)
{
//重新copy一个zval,防止破坏原数据
zval tmpcopy = **val;
zval_copy_ctor(&tmpcopy);
//转换为字符串
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
//开始输出
php_printf("The value is: ");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf("\n");
//毁尸灭迹
zval_dtor(&tmpcopy);
//返回,继续遍历下一个~
return ZEND_HASH_APPLY_KEEP;
}
然后定义循环函数:zend_hash_apply(arrht, php_sample_print_zval TSRMLS_CC); $val) { echo "The value of $key is: $val\n"; }
?>针对这段php代码的c代码:
int php_sample_print_zval_and_key(zval **val, int num_args, va_list args, zend_hash_key *hash_key) {
/* 复制zval从而使得原来的内容被保存下来 */
zval tmpcopy = **val;
/* tsrm_ls is needed by output functions */
TSRMLS_FETCH();
zval_copy_ctor(&tmpcopy);
/* Reset refcount & Convert */
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
/* 输出 */
php_printf("The value of ");
if (hash_key->nKeyLength) {
/* 如果是字符串类型的key */
PHPWRITE(hash_key->arKey, hash_key->nKeyLength);
} else {
/* 如果是数字类型的key */
php_printf("%ld", hash_key->h);
}
php_printf(" is: ");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy)); php_printf("\n");
/* Toss out old copy */
zval_dtor(&tmpcopy);
/* continue; */
return ZEND_HASH_APPLY_KEEP;
}1, 'b'=>2, 'c'=>3);
reset($arr);
while (list($key, $val) = each($arr)) {
/* Do something with $key and $val */
}
reset($arr);
$firstkey = key($arr);
$firstval = current($arr);
$bval = next($arr);
$cval = next($arr);
?>每一个相应的函数都会有一个zend版本:
* /* reset() */
void zend_hash_internal_pointer_reset(HashTable *ht);
/* key() */
int zend_hash_get_current_key(HashTable *ht,
char **strIdx, unit *strIdxLen,
ulong *numIdx, zend_bool duplicate);
* /* current() */
int zend_hash_get_current_data(HashTable *ht, void **pData);
* /* next()/each() */
int zend_hash_move_forward(HashTable *ht);
* /* prev() */
int zend_hash_move_backwards(HashTable *ht);
* /* end() */
void zend_hash_internal_pointer_end(HashTable *ht);
* /* Other... */
int zend_hash_get_current_key_type(HashTable *ht);
int zend_hash_has_more_elements(HashTable *ht);
next() prev() end()其实都是找到相应的索引值,再用zend_hash_get_current_data()返回元素值void php_sample_print_var_hash(HashTable *arrht)
{
for(zend_hash_internal_pointer_reset(arrht);
zend_hash_has_more_elements(arrht) == SUCCESS;
zend_hash_move_forward(arrht)) {
char *key;
uint keylen;
ulong idx;
int type;
zval **ppzval, tmpcopy;
type = zend_hash_get_current_key_ex(arrht, &key, &keylen,
&idx, 0, NULL);//获得返回的key的类型。这个类型可能有三种
if (zend_hash_get_current_data(arrht, (void**)&ppzval) == FAILURE) {//获得当前索引所指的数据值
/* Should never actually fail
* since the key is known to exist. */
continue;
}
/* 复制zval的值,从而原来的值不会被破坏掉 */
tmpcopy = **ppzval;
zval_copy_ctor(&tmpcopy);
/* 重新设定refcount 并且转换 */
INIT_PZVAL(&tmpcopy);
convert_to_string(&tmpcopy);
/* 输出 */
php_printf("The value of ");
if (type == HASH_KEY_IS_STRING) {
/* String Key / Associative */
PHPWRITE(key, keylen);
} else {
/* Numeric Key */
php_printf("%ld", idx);
}
php_printf(" is: ");
PHPWRITE(Z_STRVAL(tmpcopy), Z_STRLEN(tmpcopy));
php_printf("\n");
/* 销毁原来的副本 */
zval_dtor(&tmpcopy);
}
}来看一下zend_hash_get_current_key_ex返回值的可能性:
Constant Meaningint zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_index_del(HashTable *ht, ulong h);返回SUCCESS OR FAILURE
int sample_strvec_handler(int argc, char **argv TSRMLS_DC)
{
HashTable *ht;
/* 为哈希表分配空间 */
ALLOC_HASHTABLE(ht);
/* 初始化哈希表的内部状态 */
if (zend_hash_init(ht, argc, NULL,
ZVAL_PTR_DTOR, 0) == FAILURE) {
FREE_HASHTABLE(ht);
return FAILURE;
}
/* 把每个字符串变成zval* */
while (argc) {
zval *value;
MAKE_STD_ZVAL(value);
ZVAL_STRING(value, argv[argc], 1);
argv++;
if (zend_hash_next_index_insert(ht, (void**)&value,
sizeof(zval*)) == FAILURE) {
/* 对于分配失败的情况应该跳掉 */
zval_ptr_dtor(&value);
}
}
/* Do some work */
process_hashtable(ht);
/* 毁坏哈希表
* 释放所有的分配的空旷 */
zend_hash_destroy(ht);
/* Free the HashTable itself */
FREE_HASHTABLE(ht);
return SUCCESS;
}
int zend_hash_minmax(HashTable *ht, compare_func_t compar,
int flag, void **pData TSRMLS_DC);flag为0就返回最小值,否则就是最大值。int fname_compare(zend_function *a, zend_function *b TSRMLS_DC)
{
return strcasecmp(a->common.function_name, b->common.function_name);
}
void php_sample_funcname_sort(TSRMLS_D)
{
zend_function *fe;
if (zend_hash_minmax(EG(function_table), fname_compare,
0, (void **)&fe) == SUCCESS) {
php_printf("Min function: %s\n", fe->common.function_name);
}
if (zend_hash_minmax(EG(function_table), fname_compare,
1, (void **)&fe) == SUCCESS) {
php_printf("Max function: %s\n", fe->common.function_name);
}
}
typedef void (*sort_func_t)(void **Buckets, size_t numBuckets,
size_t sizBucket, compare_func_t comp TSRMLS_DC);
int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
compare_func_t compare_func, int renumber TSRMLS_DC);
一般就用zend_qsort作为sort_func就够了。renumber这个参数如果设为1的话,那么就会抛弃原有的索引键值关系,赋予新的数字键值。
zend_hash_sort(target_hash, zend_qsort,array_data_compare, 1 TSRMLS_CC);
array_data_compare是一个返回compare_func_t类型数据的函数,它将按照HashTable中zval*值的大小进行排序。http://www.bkjia.com/PHPjc/635044.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/635044.htmlTechArticle接着上面一节,继续说php扩展中的数组与哈希表的api,这节主要是说回调遍历函数正常遍历函数析构函数排序、对比、极函数 Iteration by ha...