详解PHP源码
2021/10/12 20:16:32
本文主要是介绍详解PHP源码,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
in_array() php内置函数的源码解读
/* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict]) Searches the array for a given value and returns the corresponding key if successful */ PHP_FUNCTION(array_search) { php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } PHP_FUNCTION(in_array) { php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) * 0 = return boolean * 1 = return key */ static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ { zval *value, /* value to check for */ *array, /* array to check in */ *entry; /* pointer to array entry */ zend_ulong num_idx; zend_string *str_idx; zend_bool strict = 0; /* strict comparison or not */ ZEND_PARSE_PARAMETERS_START(2, 3) /* 开始接收参数 */ /*第一个参数表示必传的参数个数,第二个参数表示最多传入的参数个数。*/ Z_PARAM_ZVAL(value) /* 接收必填参数(这个参数可能是int也可能是str) 所以没有指定类型*/ Z_PARAM_ARRAY(array) /* 接收必填参数数组类型 */ Z_PARAM_OPTIONAL Z_PARAM_BOOL(strict) /* 接收选填参数bool类型 */ ZEND_PARSE_PARAMETERS_END(); /* 结束 */ if (strict) { ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) { ZVAL_DEREF(entry); if (fast_is_identical_function(value, entry)) { if (behavior == 0) { RETURN_TRUE; } else { if (str_idx) { RETVAL_STR_COPY(str_idx); } else { RETVAL_LONG(num_idx); } return; } } } ZEND_HASH_FOREACH_END(); } else { /* 理解下下边这块 _p 是指针,_pp 是指针的指针*/ /* */ if (Z_TYPE_P(value) == IS_LONG) { /* 按照value的值的类型来处理 IS_LONG 是长整型 */ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) {/* ZEND_HASH_FOREACH_KEY_VAL_IND 函数意思是zend遍历 间接zval 类型数据 */ if (fast_equal_check_long(value, entry)) { if (behavior == 0) { /* 这里是 in_array() */ RETURN_TRUE; } else { /* 这里是 array_search() */ if (str_idx) { RETVAL_STR_COPY(str_idx); /* 字符串类型的返回值 */ } else { RETVAL_LONG(num_idx); /* 整型返回值 */ } return;/* 为了提前结束函数 */ } } } ZEND_HASH_FOREACH_END();/* 遍历结束 */ } else if (Z_TYPE_P(value) == IS_STRING) { ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) { if (fast_equal_check_string(value, entry)) { if (behavior == 0) { RETURN_TRUE; } else { if (str_idx) { RETVAL_STR_COPY(str_idx); } else { RETVAL_LONG(num_idx); } return; } } } ZEND_HASH_FOREACH_END(); } else { ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(array), num_idx, str_idx, entry) { if (fast_equal_check_function(value, entry)) { if (behavior == 0) { RETURN_TRUE; } else { if (str_idx) { RETVAL_STR_COPY(str_idx); } else { RETVAL_LONG(num_idx); } return; } } } ZEND_HASH_FOREACH_END(); } } RETURN_FALSE; } static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2) /* zend_always_inline 含义函数开始执行时,需要为函数分配相应的函数栈帧并入栈 */ { zval result; if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { /* 都为整型的时候 */ return Z_LVAL_P(op1) == Z_LVAL_P(op2); /* 直接比较 相同true 不相同 false*/ } compare_function(&result, op1, op2); /* 类型不一样的时候用这个函数 */ return Z_LVAL(result) == 0; /* 把result值读出来比较返回值 */ } ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) { int ret; int converted = 0; zval op1_copy, op2_copy; zval *op_free, tmp_free; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0)); return SUCCESS; case TYPE_PAIR(IS_DOUBLE, IS_LONG): Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2); ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); return SUCCESS; case TYPE_PAIR(IS_LONG, IS_DOUBLE): Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2); ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); return SUCCESS; case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { ZVAL_LONG(result, 0); } else { Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); } return SUCCESS; case TYPE_PAIR(IS_ARRAY, IS_ARRAY): ZVAL_LONG(result, zend_compare_arrays(op1, op2)); return SUCCESS; case TYPE_PAIR(IS_NULL, IS_NULL): case TYPE_PAIR(IS_NULL, IS_FALSE): case TYPE_PAIR(IS_FALSE, IS_NULL): case TYPE_PAIR(IS_FALSE, IS_FALSE): case TYPE_PAIR(IS_TRUE, IS_TRUE): ZVAL_LONG(result, 0); return SUCCESS; case TYPE_PAIR(IS_NULL, IS_TRUE): ZVAL_LONG(result, -1); return SUCCESS; case TYPE_PAIR(IS_TRUE, IS_NULL): ZVAL_LONG(result, 1); return SUCCESS; case TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { ZVAL_LONG(result, 0); return SUCCESS; } ZVAL_LONG(result, zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2))); return SUCCESS; case TYPE_PAIR(IS_NULL, IS_STRING): ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1); return SUCCESS; case TYPE_PAIR(IS_STRING, IS_NULL): ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1); return SUCCESS; case TYPE_PAIR(IS_OBJECT, IS_NULL): ZVAL_LONG(result, 1); return SUCCESS; case TYPE_PAIR(IS_NULL, IS_OBJECT): ZVAL_LONG(result, -1); return SUCCESS; default: if (Z_ISREF_P(op1)) { op1 = Z_REFVAL_P(op1); continue; } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); continue; } if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) { ret = Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2); if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) { convert_compare_result_to_long(result); } return ret; } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) { ret = Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2); if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) { convert_compare_result_to_long(result); } return ret; } if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) { if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) { /* object handles are identical, apparently this is the same object */ ZVAL_LONG(result, 0); return SUCCESS; } if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) { ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2)); return SUCCESS; } } if (Z_TYPE_P(op1) == IS_OBJECT) { if (Z_OBJ_HT_P(op1)->get) { zval rv; op_free = Z_OBJ_HT_P(op1)->get(op1, &rv); ret = compare_function(result, op_free, op2); zend_free_obj_get_result(op_free); return ret; } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { ZVAL_UNDEF(&tmp_free); if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) { ZVAL_LONG(result, 1); zend_free_obj_get_result(&tmp_free); return SUCCESS; } ret = compare_function(result, &tmp_free, op2); zend_free_obj_get_result(&tmp_free); return ret; } } if (Z_TYPE_P(op2) == IS_OBJECT) { if (Z_OBJ_HT_P(op2)->get) { zval rv; op_free = Z_OBJ_HT_P(op2)->get(op2, &rv); ret = compare_function(result, op1, op_free); zend_free_obj_get_result(op_free); return ret; } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { ZVAL_UNDEF(&tmp_free); if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) { ZVAL_LONG(result, -1); zend_free_obj_get_result(&tmp_free); return SUCCESS; } ret = compare_function(result, op1, &tmp_free); zend_free_obj_get_result(&tmp_free); return ret; } else if (Z_TYPE_P(op1) == IS_OBJECT) { ZVAL_LONG(result, 1); return SUCCESS; } } if (!converted) { if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) { ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) { ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0); return SUCCESS; } else if (Z_TYPE_P(op1) == IS_TRUE) { ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_TRUE) { ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1); return SUCCESS; } else { op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 1); op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 1); if (EG(exception)) { if (result != op1) { ZVAL_UNDEF(result); } return FAILURE; } converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { ZVAL_LONG(result, 1); return SUCCESS; } else if (Z_TYPE_P(op2)==IS_ARRAY) { ZVAL_LONG(result, -1); return SUCCESS; } else if (Z_TYPE_P(op1)==IS_OBJECT) { ZVAL_LONG(result, 1); return SUCCESS; } else if (Z_TYPE_P(op2)==IS_OBJECT) { ZVAL_LONG(result, -1); return SUCCESS; } else { ZVAL_LONG(result, 0); return FAILURE; } } } }
这篇关于详解PHP源码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-19php8的协程和hyperf的协程有什么区别?-icode9专业技术文章分享
- 2024-12-19php8 的fiber是什么?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-11-29使用PHP 将ETH账户的资产汇集到一个账户
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享