1. Create hashtable
Int zend_hash_init (hashtable * HT, // point to a hashtableuint nsize, // nsize indicates the maximum number of elements that the hashtable can possess. When we add new elements, this value determines whether to automatically increase based on the situation. This value is always the power of 2, if the value you give it is not in the form of a power of 2 //, it will be automatically adjusted to the power of its smallest 2. Its calculation method is like this: nsize = POW (2, Ceil (log (nsize, 2 ))). (Hashtable can contain any number of elements. This value is only used to apply for a good memory in advance, improve performance, and save the need for rehash operations.) hash_func_t phashfunction, // phashfunction is an early parameter and is not removed for forward compatibility. Assign null values directly. Dtor_func_t pdestructor, // a callback function. It is called when we delete or modify one of hashtable elements. Its function prototype must be like this: void method_name (void * pelement). Generally, the macro zval_ptr_dtor is used. Zend_bool persistent // The value is 0 or 1. If it is 1, The hashtable will always exist in the memory, and will not be automatically deregistered during rshutdown. At this time, the address pointed to by the first parameter HT must be applied through the pemalloc () function .);
Note:
# Define zval_ptr_dtor (void (*) (void *) zval_ptr_dtor_wrapper
Deletes an element and calls back to parse it.
2. Add
Int zend_hash_add (hashtable * HT, // htchar * arkey to be operated, // index, such as "my_key" uint nkeylen, // length of the string index, for example, 6 void ** pdata, // The data to be inserted. Note that it is of the void ** type. Uint ndatasize, // For example, if zval type variables are stored, then ndatasize = sizeof (zval *) void * pdest // if the operation is successful, pdest = * pdata ;); int zend_hash_next_index_insert (hashtable * HT, // htvoid * pdata to be operated, // uint ndatasize, void ** pdest );
3. Update
Int zend_hash_update (hashtable * HT, char * arkey, // index string uint nkeylen, // index String Length void * pdata, uint ndatasize, void ** pdest ); int zend_hash_index_update (hashtable * HT, ulong H, void * pdata, uint ndatasize, void ** pdest );
4. Search
Int zend_hash_find (hashtable * HT, char * arkey, // index string uint nkeylength, // index String Length void ** pdata // locate the element, then point the element to pdata ); int zend_hash_index_find (hashtable * HT, ulong H, // numeric index void ** pdata // locate the element and point it to pdata );
V. Detection
int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLen);int zend_hash_index_exists(HashTable *ht, ulong h);
The two functions return success or failure, which respectively indicate whether or not they exist.
Vi. Acceleration
Ulong zend_get_hash_value (char * arkey, uint nkeylen); // return the hash value of the index
You can use the zend_get_hash_value function to obtain the index hash value, and then add or modify the hashtable. Using the quick functions, you can avoid repeated string hash values and achieve accelerated acceleration.
Int zend_hash_quick_add (hashtable * HT, char * arkey, uint nkeylen, ulong hashval, // The hash value void * pdata, uint ndatasize, void ** pdest obtained by the zend_get_hash_value function ); 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 );
7. Copying and merging Arrays
Void zend_hash_copy (hashtable * target, // all elements in * source will be copied to * target through the pcopyconstructor function to remove hashtable * Source, // The data at the original index position in the target and the source will be replaced, while other elements will be retained and will not be retained. Copy_ctor_func_t pcopyconstructor, void * TMP, // The TMP parameter is used to be compatible with versions earlier than php4.0.3 and is now assigned null. The uint size // size parameter indicates the size of each element. For arrays in PHP, sizeof (zval *) is used here .); Void zend_hash_merge (hashtable * target, hashtable * Source, copy_ctor_func_t pcopyconstructor, void * TMP, uint size, int overwrite );
The unique difference between zend_hash_merge () and zend_hash_copy is that an overwrite parameter of the int type is added. When its value is not 0, the two functions work exactly the same; if the overwrite parameter is 0, the zend_hash_merge function will not replace the existing index value in the target.
void zend_hash_merge_ex(HashTable *target,HashTable *source,copy_ctor_func_t pCopyConstructor, uint size,merge_checker_func_t pMergeSource,void *pParam);
The zend_hash_merge_ex function is cumbersome. Compared with zend_hash_copy, zend_hash_copy has two more parameters. The extra pmergesoure callback function allows us to selectively perform merge instead of all merge.
8. Traversal
The essence of arrays in PHP is hashtable. You can use foreach to traverse arrays in PHP. In the kernel, The zend_hash_apply function is used.
Zend_hash_apply receives a callback function and passes every element of hashtable to the callback function. The callback function is equivalent to the foreach loop body in PHP.
The Return Value of the callback function has a common convention: zend_hash_apply_keep ends the current request and enters the next loop. It works the same way as a forech statement in PHP when a loop is completed or the continue keyword is encountered. Zend_hash_apply_stop jumps out, which is the same as the break keyword in the forech Statement of PHP language. Zend_hash_apply_remove deletes the current element and continues to process the next element. Equivalent to: unset ($ Foo [$ key]); continue;
1. No index Traversal
Typedef int (* apply_func_t) (void * pdest tsrmls_dc );
Void zend_hash_apply (hashtable * HT, apply_func_t apply_func tsrmls_dc );
Look at the forech loop in PHP.
<?phpfunction foreach_test($arr){foreach($arr as $val) { echo "The value is: $val\n";}}?>
Implement the foreach_test function in the kernel.
// The zend_hash_apply callback function, which is equivalent to the foreach body int php_foreach_body (zval ** zval tsrmls_dc) {zval tmpcopy = ** zval; // copy a zval again, prevent Damage to original data zval_copy_ctor (& tmpcopy); init_pzval (& tmpcopy); // initialize refcount _ GC = 1, is_ref _ GC = 0convert_to_string (& tmpcopy ); // convert to the string php_printf ("the value is:"); phpwrite (z_strval (tmpcopy), z_strlen (tmpcopy); php_printf ("\ n "); zval_dtor (& tmpcopy); return parameters;} php_function (foreach_test) {zval * arr; // equivalent to $ Arrif (zend_parse_parameters (zend_num_args () tsrmls_cc, "A", & ARR) {return_null ();} zend_hash_apply (z_arrval_p (ARR), php_foreach_body tsrml_cc); // start traversal}
2. Index Traversal
To receive index values at the same time, you can use void zend_hash_apply_with_arguments:
Typedef int (* struct) (void * pdest, int num_args, va_list ARGs, zend_hash_key * hash_key); void aggregate (hashtable * HT, apply_func_args_t apply_func, int numargs, // specify the number of parameters to determine va_end ()...); // This function receives parameters through the variable parameter feature in C language.
Index traversal in PHP
<?phpforeach($arr as $key => $val){echo "The value of $key is: $val\n";}?>
In the kernel:
Int php_foreach_body_and_key (zval ** Val, int num_args, va_list ARGs, zend_hash_key * hash_key) {zval tmpcopy = ** val; // copy a zval again, prevent the destruction of the original data php_printf ("Number of included parameters % d <br>", num_args); char ** A, ** B; A = va_arg (ARGs, char **); // ARGs is the starting address of the variable parameter B = va_arg (ARGs, char **); php_printf ("parameter 1: % s, parameter 2: % S <br> ", * A, * B); init_pzval (& tmpcopy); zval_copy_ctor (& tmpcopy); convert_to_string (& tmpcopy); php_printf ("the value "); if (hash_key-> nkeylength) {phpwrite (hash_key-> arkey, hash_key-> nkeylength);} else {php_printf ("% lD", hash_key-> H );} php_printf ("is:"); phpwrite (z_strval (tmpcopy), z_strlen (tmpcopy); php_printf ("\ n"); zval_dtor (& tmpcopy); Return zend_hash_apply_keep ;} php_function (foreach_test) {zval * arr; // equivalent to the function parameter $ Arrif (zend_parse_parameters (zend_num_args () tsrmls_cc, "A", & ARR) in PHP )) {return_null ();} Char * A = "var1", * B = "var2"; // variable parameter A, bzend_hash_apply_with_arguments (arrht, php_foreach_body_and_key, 2, &, & B); // start traversing and pass 2 optional parameters}