Hashtable added and updated functions:
There are 4 main functions for inserting and updating Hashtable data:
intZend_hash_add (HashTable *ht,Char*arkey,UINTNkeylen,void**pdata,UINTNdatasize,void*pDest); intZend_hash_update (HashTable *ht,Char*arkey,UINTNkeylen,void*pdata,UINTNdatasize,void**pDest);
intZend_hash_index_update (HashTable *ht,ULONGH,void*pdata,UINTNdatasize,void**pDest);
intZend_hash_next_index_insert (HashTable *HT,void*pdata,UINTNdatasize,void**pdest);
Here the first two functions are used to add associated index data, such as $foo[' bar ' = ' baz '; the corresponding C language code is as follows:
" Bar " sizeof ("bar"sizeof(zval*), NULL);
The only difference between Zend_hash_add () and Zend_hash_update () is that if key exists, Zend_hash_add () will fail.
The next two functions handle the hashtable of a numeric index in a similar way. The difference between these two lines is whether the index is specified or whether it is automatically assigned to the next available index.
If you need to store the index value of an element that is inserted using Zend_hash_next_index_insert (), you can call the Zend_hash_next_free_element () function to obtain:
ulong NextID = zend_hash_next_free_element (HT); sizeof (data), NULL);
Hashtable adding update elements:
After initializing the Hashtable, you can use Zend_hash_add to add elements to the Hashtable, Zend_hash_add is a macro:
#define Zend_hash_add (HT, Arkey, Nkeylength, PData, ndatasize, pDest) \ _zend_hash_add_or_update (HT, Arkey, Nkeylength, PData, Ndatasize, PDest, Hash_add zend_file_line_cc)
Let's take a look at the definition of _zend_hash_add_or_update, also under ZEND/ZEND_HASH.C.
Zend_apiint_zend_hash_add_or_update (HashTable *ht,Const Char*arkey,UINTNkeylength,void*PData,UINTNdatasize,void**pdest,intflag ZEND_FILE_LINE_DC) { ULONGH/*the value of the storage Arkey after the hash*/ UINTNIndex;/*values after storage H & Ntablemask*/Buckets*p; #ifdef zend_signals tsrmls_fetch ();//I don't know what that means.#endifis_consistent (HT);//Debug Information Output if(Nkeylength <=0) {//The string index is added, so nkeylength is not possible <=0#ifZend_debugZend_puts ("Zend_hash_update:can ' t put in empty key\n");#endif returnFAILURE; } /** * Check whether to initialize buckets space, initialize buckets memory space if not initialized * to Arbuckets request memory, assign value to Ntablesize because Zend_hash_init inside Ntablesize is set to 0 */Check_init (HT); H= Zend_inline_hash_func (Arkey, nkeylength);/*calculates the hash value of a key*/NIndex= h & ht->ntablemask;/*Use the mask to get the actual storage location of key*/P= ht->arbuckets[nindex];/*bucket pointer to the specified position*/ while(P! = NULL) {/*If the pointer is not empty, it indicates that the current position has a bucket.*/ if(P->arkey = = Arkey | | ((P->h = = h) && (p->nkeylength = = nkeylength) &&!memcmp (p->Arkey, Arkey, nkeylength))) { /*if the current bucket key is the same as the key to be deposited, then the update is required*/ if(Flag & Hash_add) {/*if the current assignment is an add operation, the return fails at this time*/ returnFAILURE; } /** interruptions, interrupted, interrupted meaning*/handle_block_interruptions ();#ifZend_debugif(P->pdata = =pData) {Zend_puts ("Fatal Error in Zend_hash_update:p->pdata = = pdata\n"); Handle_unblock_interruptions (); returnFAILURE; }#endif if(Ht->pdestructor) {/*call destructor to deconstruct the original value*/HT->pdestructor (p->pData); } update_data (HT, p, PData, ndatasize); /*Replace with new value*/ if(pDest) {*pdest = p->PData; } handle_unblock_interruptions (); returnSUCCESS; } P= p->pnext;/*If the current key is different from the key to be deposited, then find the next bucket of the hash Zipper}/* Run here, indicating that no existing key is found and the key to be deposited is the same, then apply for a sizeof (bucket) + Nkeylength size of new space to key*/ //interned with Google search, found that the ' string resides ' concept, and did not make it clear//Presumably, it maintains a resident pool that retains only one copy of the same string during compilation. if(is_interned (Arkey)) {p= (Bucket *) Pemalloc (sizeof(Bucket), ht->persistent); if(!p) {returnFAILURE; } P->arkey =Arkey; } Else{p= (Bucket *) Pemalloc (sizeof(Bucket) + nkeylength, ht->persistent);//the concept of flexible arrays if(!p) {returnFAILURE; } P->arkey = (Const Char*) (P +1);//P+1 is Arkey's starting address.memcpy ((Char*) p->Arkey, Arkey, nkeylength); } P->nkeylength =nkeylength; Init_data (HT, p, PData, ndatasize); /*Perform Assignment*/P->h =h; Connect_to_bucket_dllist (p, HT->arbuckets[nindex]);/*set the pointer to seven or eight slots*/ if(pDest) {*pdest = p->PData; } handle_block_interruptions (); Connect_to_global_dllist (P, HT); /*Add buckets to Hashtable's doubly linked list*/HT->arbuckets[nindex] =p; Handle_unblock_interruptions (); HT->nnumofelements++; //If the Hashtable is full, resize the hashtable. Zend_hash_if_full_do_resize (HT);/*If The Hash table is full, resize it*/ returnSUCCESS;
The above function involves macro check_init, which is defined in ZEND_HASH.C as follows,
#define Check_init (HT) do { if0)) { (HT)sizeof(Bucket *), (HT) , persistent); (HT) 1 ; } while (0)
Init_data the definition of a macro,
#defineInit_data (HT, p, PData, ndatasize);if(Ndatasize = =sizeof(void*) {memcpy (& (P)->pdataptr, PData,sizeof(void*)); (p)->pdata = & (P)pdataptr; } Else{(p)->pdata = (void*) Pemalloc_rel (ndatasize, (HT),persistent); if(! (p)pData) {Pefree_rel (P, (HT)-persistent); returnFAILURE; } memcpy (P)-PData, PData, ndatasize); (p)->pdataptr=NULL; }
Here's a tricks,php. Judging the size of the data and a void pointer at the same time, do not request additional space for it, but copy the data into the Pdataptr field, that is, if you add to Hashtable is a pointer, Then he is saved directly in the Pdataptr field, and the Pdata field is saved as a copy. If you add to Hashtable is a larger structure, PHP will apply a separate memory space for the structure, copy the data into the new application's memory space, and then set the pdataptr to null.
PHP Hash Table (four) hash table add and update elements