PHP では、配列の基礎となる実装はハッシュ テーブルであり、キーと値の形式で表示されます。 PHP の Zend エンジンには、さまざまなハッシュ テーブル操作のためのハッシュ テーブルを操作するための特別な API があります。
創造
ハッシュテーブルの場合、初期化方法は毎回同じであり、次の関数zend_hash_initによって完了します:
int zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent)
ALLOC_HASHTABLE(ht)、ht = emalloc(sizeof(HashTable)); と同等。
nSizeは、事前にメモリに適用されると考えられるハッシュテーブルの最大要素数です。 2 の指数倍数でない場合は、nSize = pow(2, ceil(log(nSize, 2))) の式に従って増加します。たとえば、5 が与えられた場合、8 まで増加します。これは、メモリ管理の比較のためのものである必要があります。 便利なメカニズムが採用されています。
pHashFunction は以前のバージョンの zend eigine 関数に属しており、新しいバージョンでは常に NULL に設定できます。
pDestructor は、ハッシュ テーブル内の要素が削除されたときに呼び出されるメソッド (zend_hash_del() zend_hash_update()) の入り口を指します。これは、対応するコールバック関数です。 Method_name 関数が指定されている場合、関数が実装されるとき:
void メソッド名(void *pElement)
pElement は削除された要素を指します
persistent は、永続的なハッシュ テーブルであるかどうかを示すフラグです。永続データはリクエストから独立しており、RSHUTDOWN 中にログアウトされません。ただし、1 に設定すると、ht はメモリを適用するときに pemalloc() を使用する必要があります。
例: 各 PHP リクエスト ライフ サイクルでsymbol_table を初期化すると、zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0); が表示されます。
設定を解除すると、ハッシュ テーブルに格納されている対応する zval* が zval_ptr_dtor() に送信されて破棄されます。
人口:
ハッシュ テーブルにデータを挿入および更新するための主な関数は 4 つあります:
int zend_hash_add(HashTable *ht, char *arKey, uint nKeyLen, void *pData, uint nDataSize, void **pDest); int zend_hash_update(HashTable *ht, char *arKey, uint nKeyLen, void *pData, uint nDataSize, void **pDest); int zend_hash_index_update(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest); int zend_hash_next_index_insert(HashTable *ht, void *pData, uint nDataSize, void **pDest);
zend_hash_add(fooHashTbl, "bar", sizeof("bar"), &barZval, sizeof(zval*), NULL);
対応するキー値と対応するテーブル値がハッシュテーブルに追加されます。
追加と更新の唯一の違いは、キーがすでに存在する場合、追加は失敗することです。
最後の 2 つの関数は、ht に数値インデックス データを追加することです。
zend_hash_next_index_insert() 関数はインデックス値パラメーターを必要としませんが、次の数値インデックス値をそれ自体で直接計算します。
次の要素の数値インデックス値を自分で取得したい場合は、zend_hash_next_free_element() を通じてインデックスを取得することもできます。
ulong nextid = zend_hash_next_free_element(ht);
zend_hash_index_update(ht, nextid, &data, sizeof(data), NULL);
上記のコードは次と同等です:
zend_hash_next_index_insert(HashTable *ht, &data,sizeof(data),NULL).
pDest パラメータは、新しく追加された要素のアドレス値を保存するために使用できます。
を見つけてください 一般的に、ハッシュ テーブル内のデータを取得するには 2 つの方法があります:
りー
これは、以下の例でより明確に見ることができます:
int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData); int zend_hash_index_find(HashTable *ht, ulong h, void **pData);
int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_index_exists(HashTable *ht, ulong h);
if (zend_hash_exists(EG(active_symbol_table), "foo", sizeof("foo"))) {//确定活动的符号表中是否存在foo变量 /* $foo is set */ } else { /* $foo does not exist */ }
ulong zend_get_hash_value(char *arKey, uint nKeyLen);
int zend_hash_quick_add(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void *pData, uint nDataSize, void **pDest); int zend_hash_quick_update(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void *pData, uint nDataSize, void **pDest); int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void **pData); int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval);
void php_sample_hash_copy(HashTable *hta, HashTable *htb, char *arKey, uint nKeyLen TSRMLS_DC) { ulong hashval = zend_get_hash_value(arKey, nKeyLen);//获得用来加速的散列值hashval zval **copyval; if (zend_hash_quick_find(hta, arKey, nKeyLen, hashval, (void**)©val) == FAILURE) {//首先要在hta table里面找到相应的元素,并且存储在copyval中。 /* arKey doesn't actually exist */ return; } /* The zval* is about to be owned by another hash table */ (*copyval)->refcount__gc++;//相应zval*变量的引用次数+1 zend_hash_quick_update(htb, arKey, nKeyLen, hashval, copyval, sizeof(zval*), NULL);//把从hta中拿来的copyval放在htb里面。 }
typedef void (*copy_ctor_func_t)(void *pElement); void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam); void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
zend_bool associative_only(HashTable *ht, void *pData, zend_hash_key *hash_key, void *pParam) { /* True if there's a key, false if there's not */ return (hash_key->arKey && hash_key->nKeyLength);//字符串类型的key,因为存在nKeyLength } void merge_associative(HashTable *target, HashTable *source) { zend_hash_merge_ex(target, source, zval_add_ref, sizeof(zval*), associative_only, NULL); }