Arrays are often used in PHP, PHP's array is powerful, and fast, read and write can be done in O (1), because it is the size of each element is consistent, as long as you know the subscript, you can instantly calculate its corresponding elements in the position of the memory, so that directly remove or write. So how does an array in the kernel implement it?
Most of PHP's functions are implemented through Hashtable, which includes arrays.
Hashtable has the advantage of bidirectional linked list, and has the ability to match the data.
The variables defined in PHP are stored in a symbol table, which is actually a hashtable, and every element of it is a zval* type variable. Furthermore, containers that save user-defined functions, classes, resources, and so on are implemented in the kernel in hashtable form.
Here's how to define an array in PHP, in the kernel, respectively.
Implementation of array definitions
Define Arrays in PHP:
Use macros in the kernel to implement:
zval* Array;
Array_init (array);
Add_assoc_string (Array, "key", "value", 1);
Expand the macros in the preceding code:
zval* Array;
Alloc_init_zval (array);
Z_type_p (array) = Is_array;
HashTable *h;
Alloc_hashtable (h);
Z_arrval_p (array) =h;
Zend_hash_init (H, M, Null,zval_ptr_dtor, 0);
zval* Barzval;
Make_std_zval (Barzval);
Zval_string (Barzval, "value", 0);
Zend_hash_add (H, "key", 4, &barzval, sizeof (zval*), NULL);
Convenient array macro operations
The kernel provides us with a convenient macro to manage arrays.
Add_assoc_* Series functions:
Add_assoc_null (Zval *aval, char *key);
Add_assoc_bool (Zval *aval, Char *key, Zend_bool bval);
Add_assoc_long (Zval *aval, Char *key, long lval);
Add_assoc_double (Zval *aval, Char *key, double dval);
Add_assoc_string (Zval *aval, Char *key, char *strval, int dup);
Add_assoc_stringl (Zval *aval, char *key,char *strval, uint strlen, int dup);
Add_assoc_zval (Zval *aval, Char *key, Zval *value);
Note: In fact these functions are all macros, are the encapsulation of the ADD_ASSOC_*_EX function.
Add_index_* Series functions:
Zend_api int Add_index_long (zval *arg, ulong idx, long N);
Zend_api int Add_index_null (zval *arg, ulong idx);
Zend_api int Add_index_bool (zval *arg, ulong idx, int b);
Zend_api int Add_index_resource (zval *arg, ulong idx, int R);
Zend_api int add_index_double (zval *arg, ulong idx, double D);
Zend_api int add_index_string (zval *arg, ulong idx, const char *STR, int duplicate);
Zend_api int Add_index_stringl (zval *arg, ulong idx, const char *STR, UINT length, int duplicate);
Zend_api int Add_index_zval (zval *arg, ULONG Index, Zval *value);
add_next_index_* function:
Zend_api int Add_next_index_long (Zval *arg, long N);
Zend_api int Add_next_index_null (Zval *arg);
Zend_api int Add_next_index_bool (zval *arg, int b);
Zend_api int Add_next_index_resource (zval *arg, int R);
Zend_api int add_next_index_double (Zval *arg, double D);
Zend_api int add_next_index_string (zval *arg, const char *STR, int duplicate);
Zend_api int Add_next_index_stringl (zval *arg, const char *STR, UINT length, int duplicate);
Zend_api int Add_next_index_zval (zval *arg, Zval *value);
Here's a comparison of the macros that are common to the array operations.
Add_next_index_* ()
In the kernel of PHP
$arr [] = NULL; Add_next_index_null (arr);
$arr [] = 42; Add_next_index_long (arr, 42);
$arr [] = true; Add_next_index_bool (arr, 1);
$arr [] = 3.14; Add_next_index_double (arr, 3.14);
$arr [] = ' foo '; Add_next_index_string (arr, "foo");
$arr [] = $var; Add_next_index_zval (arr, zval);
Add_index_* ()
In the kernel of PHP
$arr [0] = NULL; Add_index_null (arr, 0);
$arr [1] = 42; Add_index_long (arr, 1, 42);
$arr [2] = true; Add_index_bool (arr, 2, 1);
$arr [3] = 3.14; Add_index_double (arr, 3, 3.14);
$arr [4] = ' Foo '; Add_index_string (arr, 4, "foo", 1);
$arr [5] = $var; Add_index_zval (arr, 5, zval);
Add_assoc_* ()
In the kernel of PHP
$arr ["abc"] = NULL; Add_assoc_null (arr, "abc");
$arr ["def"] = 42; Add_assoc_long (arr, "Def", 42);
$arr ["ghi"] = true; Add_assoc_bool (arr, "Ghi", 1);
$arr ["jkl"] = 3.14 add_assoc_double (arr, "JKL", 3.14);
$arr ["MnO"]= "foo" add_assoc_string (arr, "MnO", "foo", 1);
$arr ["PQR"] = $var; Add_assoc_zval (arr, "PQR", zval);
A complete instance of
The following defines a function in PHP and uses an array in it. Then look at how it is implemented in the kernel.
Implementation in kernel:
Php_function (array_test) {
Char* mystr;
zval* Mysubarray;
Array_init (Return_value);
Add_index_long (Return_value, 42, 123);
Add_next_index_string (Return_value, "test", 1);
Add_next_index_stringl (Return_value, "Test_stringl", 10, 1);
MyStr = Estrdup ("Forty Five");
Add_next_index_string (Return_value, mystr, 0);
Add_assoc_double (Return_value, "double", 3.14);
Alloc_init_zval (Mysubarray);
Array_init (Mysubarray);
Add_next_index_string (Mysubarray, "Hello", 1);
Add_assoc_zval (Return_value, "Subarray", Mysubarray);
}
You may be wondering where the variable return_value in the above code is defined. The following will php_function unfold, you will understand.
Zif_array_test (int ht, zval *return_value, Zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);
Yes, virtually every function has a default return value of Return_value. When you use Retval_* (), return_* () as the function return value, just modify the Return_value.