ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

详解PHP源码

2021-10-12 18:02:41  阅读:135  来源: 互联网

标签:return op1 op2 LONG 源码 result PHP TYPE 详解


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;
				}
		}
	}
}

标签:return,op1,op2,LONG,源码,result,PHP,TYPE,详解
来源: https://blog.csdn.net/qq_39999924/article/details/120725613

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有