Following the above section, we continue to talk about the array and hash table API in the PHP extension. This section mainly talks about
Callback traversal function, normal traversal function, destructor, sorting, comparison, extreme value function
Iteration by hash Apply:
To traverse the array, the simplest way is to use a function similar to the foreach statement in the PHP language, zend_hash_apply, which receives a callback function and passes each element of the hashtable to it.
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 <strong>zend_hash_apply_with_argument</strong>(HashTable *ht, apply_func_arg_t apply_func, void *data TSRMLS_DC);
<?php foreach($arr as $val) { echo "The value is: $val\n"; } ?>
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; }
<?php foreach($arr as $key => $val) { echo "The value of $key is: $val\n"; } ?>
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; }
<?php $arr = array('a'=>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); ?>
* /* 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);
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); } }
int zend_hash_del(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_index_del(HashTable *ht, ulong h);
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);
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);