Home >Backend Development >PHP Tutorial >PHP source code — is_array function source code analysis

PHP source code — is_array function source code analysis

步履不停
步履不停Original
2019-06-25 15:34:562659browse

PHP source code — is_array function source code analysis

is_array in php

is_array in php, its signature is is_array (mixed $var): bool

The source code of the implementation

can be found in \ext\standard\type.c PHP_FUNCTION(is_array) The location is approximately line 273.

In PHP, this series of functions consists of many functions. In addition to itself, there are also is_bool, is_countable, is_callback, is_int, is_object, is_string, etc.

Between them , most of the source code is similar to is_array:

PHP_FUNCTION(is_array)
{
php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY);
}

Its definition is very concise, directly calling php_is_type , the function of the macro INTERNAL_FUNCTION_PARAM_PASSTHRU is , pass the parameters when calling is_array to php_is_type as they are. It is defined as follows:

#define INTERNAL_FUNCTION_PARAM_PASSTHRU execute_data, return_value

The function php_is_type is defined as follows:

static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
{
zval *arg;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(arg)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
if (Z_TYPE_P(arg) == type) {
if (type == IS_RESOURCE) {
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
if (!type_name) {
RETURN_FALSE;
}
}
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}

The first few lines are the parameter parsing part

ZEND_PARSE_PARAMETERS_START(1, 1)
    Z_PARAM_ZVAL(arg)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

Then it passes Z_TYPE_P(arg) Get the type of the variable, and then let the result be equal to IS_ARRAY . If true, it means the variable is an array, otherwise it is not. The role of Z_TYPE_P is obvious, it is to get the type of the variable. After expansion of this macro, it is as follows:

static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
return pz->u1.v.type;
}

where pz is the zval pointer, and zval is the often mentioned _zval_struct:

struct _zval_struct {
zend_value        value;/* 值 */
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar    type,/* 类型 */
zend_uchar    type_flags,
union {
uint16_t  call_info;    /* call info for EX(This) */
uint16_t  extra;        /* not further specified */
} u)
} v;
uint32_t type_info;
} u1;
union {
uint32_t     next;                 /* hash 碰撞时用到的链表 */
uint32_t     cache_slot;           /* cache slot (for RECV_INIT) */
uint32_t     opline_num;           /* opline number (for FAST_CALL) */
uint32_t     lineno;               /* 行号 (ast 节点中) */
uint32_t     num_args;             /* 参数数量 for EX(This) */
uint32_t     fe_pos;               /* foreach 时的所在位置 */
uint32_t     fe_iter_idx;          /* foreach iterator index */
uint32_t     access_flags;         /* 类时的访问权限标志位 */
uint32_t     property_guard;       /* single property guard */
uint32_t     constant_flags;       /* constant flags */
uint32_t     extra;                /* 保留字段 */
} u2;
};

I won’t give an in-depth introduction.

Continue to see php_is_typeWhen judging the type,

There is a strange place: if (type == IS_RESOURCE) {

Why do we need to determine whether it is a resource type?

Extended resource type

Extend here. If php_is_type is used to determine the resource type

it will be called here const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));

There is a call to zend_rsrc_list_get_rsrc_type, which is implemented as follows:

const char *zend_rsrc_list_get_rsrc_type(zend_resource *res)
{
zend_rsrc_list_dtors_entry *lde;
lde = zend_hash_index_find_ptr(&list_destructors, res->type);
if (lde) {
return lde->type_name;
} else {
return NULL;
}
}

There is a static variable called list_destructors , its The function is as follows

list_destructors is a global static HashTable. When the resource type is registered, a zval structure variable zv is stored in the arData of list_destructors, but the value.ptr of zv points to zend_rsrc_list_dtors_entry *lde. The resource release function pointer contained in lde, the release function pointer of the persistent resource, the resource type name, the index basis of the resource in the hashtable (resource_id), etc. --From "Analysis of the third-party extension principle of using resource wrapping in PHP7"

That is to say, when a resource type R1 is created, a resource type R1 will be stored in list_destructors Part zend_rsrc_list_dtors_entry , which contains some information about the resource R1

The zend_hash_index_find_ptr is to find the zend_rsrc_list_dtors_entry corresponding to the resource, and then take the lde->type_name

If the type member exists, it means that it is a resource type.

Summary

is_* series of functions used in PHP to determine the type, most of which use u1 in the underlying zval of the variable .v.type To determine the type value, if it is a resource type, you need to query whether the corresponding resource type exists through list_destructors. If it exists, it means that the resource handle can be used normally.

For more PHP related technical articles, please visit the PHP Tutorial column to learn!

The above is the detailed content of PHP source code — is_array function source code analysis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn