PHP extensions and embedding in--php extensions in arrays and hash tables 2_php Tutorial

Source: Internet
Author: User
Tags php foreach
Then the above section, continue to say the PHP extension of the array with the hash table API, this section is mainly said callback traversal function normal traversal function destructor sorting, contrast, extremum function

iteration by hash Apply:The simplest way to traverse an array is to use a function similar to the one in the PHP language, zend_hash_apply, which receives a callback function and passes each element of 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,                            zend_hash_apply_with_argument(HashTable *ht,        apply_ func_arg_t apply_func, void *data tsrmls_dc);
One is a parameter that can be passed, and one that does not pass the parameter, only passing the value in the hash table. For functions that can pass parameters, it is more likely to be applied to the extension. The callback function may have different return values:
Return value of Table callback function
Constant meaning
Zend_hash_apply_keep ends the current request and enters the next loop. A loop in the PHP language Forech statement is executed or the Continue keyword is encountered.
Zend_hash_apply_stop jumps out, as does the break keyword in the PHP language Forech statement.
Zend_hash_apply_remove deletes the current element and then resumes processing the next. Equivalent in the PHP language: unset ($foo [$key]); continue;

For a simple PHP traversal code
 
  
The extended form is as follows: first define the callback function
int Php_sample_print_zval (zval **val tsrmls_dc) {    //re-copy a zval to prevent destruction of the original data    zval tmpcopy = **val;    Zval_copy_ctor (&tmpcopy);         Convert to String    init_pzval (&tmpcopy);    Convert_to_string (&tmpcopy);        Start output    php_printf ("The value is:");    Phpwrite (Z_strval (tmpcopy), Z_strlen (tmpcopy));    php_printf ("\ n");         Destruction of the body    zval_dtor (&tmpcopy);         Return, continue traversing the next ~    return zend_hash_apply_keep;}
Then define the Loop function: Zend_hash_apply (Arrht, Php_sample_print_zval tsrmls_cc);
Iterates over a hash table named Arrht, which is an element type of zval*.
Note that it is not the element that is stored in the hash table, but the pointer, which is a zval**. When copying a pointer, the Hashtable itself does not move the contents.

In order to be able to accept the value at the time of the loop, also receive the key, the third form zend_hash_apply (): Zend_hash_apply_with_arguments ()
 
  $val) {     echo "The value of $key is: $val \ n";}? >
C code for this PHP code:
int Php_sample_print_zval_and_key (zval **val,         int Num_args, va_list args, Zend_hash_key *hash_key) {/    * Copy Zval so that the original content is saved */         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);         /* Output *    /php_printf ("The Value of");    if (hash_key->nkeylength) {/          * if is a string type of key *            /Phpwrite (Hash_key->arkey, hash_key->nkeylength);         } else {        /* If it is a numeric type 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;}

Execution traversal: zend_hash_apply_with_arguments (Arrht, Php_sample_print_zval_and_key, 0); When we check whether this hash_key is a string type or a numeric type, is detected by the Nkeylength property, not by the Arkey property. This is because the kernel sometimes leaves some dirty data in the Arkey property, but the Nkeylength property is safe and safe to use. Even for an empty string index, it can still be processed. For example: $foo ["] =" Bar ", the value of the index is a null character, but its length is the last null character, so it is 1.

iteration by move forwardHash table traversal can also be implemented without callback. This is the internal pointer to the hash table.
There are many functions available in the user space:
 
  1, ' B ' =>2, ' C ' =>3);    Reset ($arr);    while (list ($key, $val) = each ($arr)) {/        * something with $key and $val *    /} reset ($arr);    $firstkey = key ($arr);    $firstval = current ($arr);    $bval = Next ($arr);    $cval = Next ($arr);? >
Each of the corresponding functions will have a Zend version:
*/* 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 () is actually finding the corresponding index value, and then returning the element value with Zend_hash_get_current_data ()
Each () is the same as the next step, but calls and returns the Zend_hash_get_current_key ()

So the following is a hash table traversal method without a callback function:
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, &id X, 0, NULL);//Gets the type of the key returned. This type may have three if (Zend_hash_get_current_data (Arrht, (void**) &ppzval) = = FAILURE) {//Get the data value indicated by the current index/* Shou LD never actually fail * Since the key is known to exist.        */Continue;        }/* Copy the value of Zval so that the original value will not be destroyed */tmpcopy = **ppzval;        Zval_copy_ctor (&tmpcopy);        /* Reset RefCount and convert */Init_pzval (&tmpcopy);        Convert_to_string (&tmpcopy);        /* Output */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");    /* Destroy the original copy */Zval_dtor (&tmpcopy); }}
Take a look at the possibility of ZEND_HASH_GET_CURRENT_KEY_EX return value: Constant meaning

Hash_key_is_string the index of the current element is of type string. Therefore, a pointer to the element ' s key name is populated into Stridx, and its length would be populated into stdidx Len. If the duplicate flag is set to a nonzero value, the key would be estrndup () ' d before being populated into stridx. The calling application is expected to free this duplicated string.

Hash_key_is_long the index of the current element is a numeric type.
The internal pointer in Hash_key_non_existant Hashtable has been moved to the tail, not pointing to any elements.


DestructionNote There are only four destructors: the first two are used to delete a single element from the hash table:
int Zend_hash_del (HashTable *ht, char *arkey, uint nkeylen); int Zend_hash_index_del (HashTable *ht, ulong h);
Returns success OR FAILURE
Corresponds to the version of the string and the numeric index, respectively.
When an element is removed from the hash table, the destructor of the Hashtable is called with a pointer to the element.

When the hash table is completely deleted: void Zend_hash_clean (HashTable *ht), which is the equivalent of looping through Zend_hash_del. Call this function in addition to execute clean, but also the zend_hash_init application of space to get rid of: void Zend_hash_destroy (HashTable *ht);
Look at the life cycle of a hash table to get a clearer picture of the whole process:
int Sample_strvec_handler (int argc, char **argv tsrmls_dc) {    HashTable *ht;    /* Allocate space for hash table *    /alloc_hashtable (HT);    /* Initialize the internal state of the hash table *    /if (Zend_hash_init (HT, argc, NULL,                        zval_ptr_dtor, 0) = = FAILURE) {        free_hashtable (HT);        return FAILURE;    }    /* Turn each string into 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) {/            * should be skipped in case of allocation failure */            Zval_ptr_dtor (&value);        }    }    /* Do some work *    /process_hashtable (HT);    /* Destroy hash Table     * Release all allocated empty *    /Zend_hash_destroy (HT);    /* Free the HashTable itself *    /free_hashtable (HT);    return SUCCESS;}


sorting, comparing, and going to the Extreme (s)For two hash tables, size comparison: typedef int (*compare_func_t) (void *a, void *b tsrmls_dc); This function is like qsort, expecting your own function to compare A and B, return-1 0 1

Here is an example of size comparison:
int Zend_hash_minmax (HashTable *ht, compare_func_t compar,                        int flag, void **pdata tsrmls_dc);
A flag of 0 returns the minimum value, otherwise it is the maximum value.

A more specific example is given below, with different flags to control whether the maximum or minimum value is returned:
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);    }}

There is also a hash comparison function: int zend_hash_compare (HashTable *hta, HashTable *HTB,
compare_func_t Compar, Zend_bool ordered TSRMLS_DC); compare the number of hash tables, whichever is larger. If there are as many, compare each element.

There's also a special sort function:
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);
The general use of Zend_qsort as a sort_func is enough. Renumber this parameter is set to 1, then the original index key value relationship is discarded, and the new numeric key value is given. Zend_hash_sort (Target_hash, Zend_qsort,array_data_compare, 1 tsrmls_cc); Array_data_compare is a return compare_func_ A function of type T data that will be sorted according to the size of the zval* value in Hashtable.


http://www.bkjia.com/PHPjc/635044.html www.bkjia.com true http://www.bkjia.com/PHPjc/635044.html techarticle then the above section, continue to say the PHP extension in the array with the hash table API, this section is mainly said callback traversal function normal traversal function destructor Sort, contrast, pole function iteration by Ha ...

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.