IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 辅助解读PHP源码 ZEND_PARSE_PARAMETERS_START函数 __FAST ZPP方式 -> 正文阅读

[PHP知识库]辅助解读PHP源码 ZEND_PARSE_PARAMETERS_START函数 __FAST ZPP方式

FAST ZPP

FAST ZPP相应的宏方法可以查看官方网站 https://wiki.php.net/rfc/fast_zpp
不建议删除现有的API,但是在PHP7中提供了新方式。提高了参数解析的性能,建议仅对最常用的函数使用FAST ZPP方式。

ZEND_PARSE_PARAMETERS_START(2, 4)
	Z_PARAM_ARRAY(输入)
	Z_PARAM_LONG(偏移量)
	Z_PARAM_OPTIONAL
	Z_PARAM_ZVAL(z_length)
	Z_PARAM_BOOL(preserve_keys)
ZEND_PARSE_PARAMETERS_END();

解读使用方式:
以ZEND_PARSE_PARAMETERS_START(1, 2)开头。
第一个参数表示必传的参数个数,第二个参数表示最多传入的参数个数。
ZEND_PARSE_PARAMETERS_END();结束。
中间是传入参数的解析。
值得注意的是,一般FAST ZPP的宏方法与zend_parse_parameters的specifier是一一对应的。如:
Z_PARAM_OPTIONAL 对应 |
Z_PARAM_STR 对应 S
但是,Z_PARAM_ZVAL_EX方法比较特殊。它对应两个specifier,分别是 ! 和 / 。! 对应宏方法的第二个参数。/ 对应宏方法的第三个参数。如果想开启,只要设置为1即可。(具体的详见下图)

返回值
方法的返回值是使用RETURN_开头的宏方法进行返回的。常用的宏方法有:
RETURN_NULL() 返回null
RETURN_LONG(l) 返回整型
RETURN_DOUBLE(d) 返回浮点型
RETURN_STR(s) 返回一个字符串。参数是一个zend_string * 指针
RETURN_STRING(s) 返回一个字符串。参数是一个char * 指针
RETURN_STRINGL(s, l) 返回一个字符串。第二个参数是字符串长度。
RETURN_EMPTY_STRING() 返回一个空字符串。
RETURN_ARR? 返回一个数组。参数是zend_array *指针。
RETURN_OBJ? 返回一个对象。参数是zend_object *指针。
RETURN_ZVAL(zv, copy, dtor) 返回任意类型。参数是 zval *指针。
RETURN_FALSE 返回false
RETURN_TRUE 返回true
在这里插入图片描述

ZEND_HASH_FOREACH_KEY_VAL_IND

个人理解:遍历当前维度的数组
先来看看正常的函数

#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \
	ZEND_HASH_FOREACH(ht, 0); \
	_h = _p->h; \
	_key = _p->key; \
	_val = _z;

这个是PHP7 新添加的 IS_INDIRECT 相关的遍历类型 (间接 zval)

#define ZEND_HASH_FOREACH_KEY_VAL_IND(ht, _h, _key, _val) \
	ZEND_HASH_FOREACH(ht, 1); \
	_h = _p->h; \
	_key = _p->key; \
	_val = _z;

具体的可以去看看我的另个文章Zend API:深入 PHP 内核
间接 zval 既是 IS_INDIRECT间接类型保存变量 的部分介绍

遍历的操作函数 集合

--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_NUM_KEY_PTR
//取键值对,键为zend_ulong,值为相应的PTR
	HashTable *table;
	zend_ulong id = 0L;
 
	ZEND_HASH_FOREACH_NUM_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table) {
		phpdbg_breakbase_t *brake;
	}ZEND_HASH_FOREACH_END();
 
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_STR_KEY
//取键,键为zend_string*型
			zend_string *file;
			ZEND_HASH_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) {
				HashTable *fileht;
 
				phpdbg_debug("Compare against loaded %s\n", file);
 
				if (!(pending = ((fileht = phpdbg_resolve_pending_file_break_ex(ZSTR_VAL(file), ZSTR_LEN(file), path_str, broken)) == NULL))) {
					new_break = *(phpdbg_breakfile_t *) zend_hash_index_find_ptr(fileht, line_num);
					break;
				}
			} ZEND_HASH_FOREACH_END();
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_KEY_PTR
//取键值对,键为zend_ulong型,zend_string*型,值为相应的PTR
	HashTable **table, zend_ulong *numkey, zend_string **strkey) /* {{{ */
	if ((*table = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id))) {
		phpdbg_breakbase_t *brake;
 
		ZEND_HASH_FOREACH_KEY_PTR(*table, *numkey, *strkey, brake) {
			if (brake->id == id) {
				return brake;
			}
		} ZEND_HASH_FOREACH_END();
		
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_NUM_KEY_VAL
//使用number key取hash中的“值”,值为zval*型,键为zend_ulong型
	zval *trace, *frame, rv;
	zend_ulong index;
	
	trace = zend_read_property(base_ce, object, "trace", sizeof("trace")-1, 1, &rv);
	if (Z_TYPE_P(trace) != IS_ARRAY) {
		RETURN_FALSE;
	}
	ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(trace), index, frame) {
		if (Z_TYPE_P(frame) != IS_ARRAY) {
			zend_error(E_WARNING, "Expected array for frame %pu", index);
			continue;
		}
 
		_build_trace_string(&str, Z_ARRVAL_P(frame), num++);
	} ZEND_HASH_FOREACH_END();
 
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_NUM_KEY
//取hash中的number hash key,键为zend_ulong型
		zend_ulong leaf;
		ZEND_HASH_FOREACH_NUM_KEY(&src->child.ht, leaf) {
			zend_generator_add_single_child(dest, child, (zend_generator *) leaf);
		} ZEND_HASH_FOREACH_END();
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_STR_KEY_PTR
//取hash中的键值对,键为zend_string*型,值为相关的指针型
	zend_property_info *property_info;
	zend_string *key;
	
		ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
			do_inherit_property(property_info, key, ce);
		} ZEND_HASH_FOREACH_END();
		
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_VAL
//直接取hash中的“值”,值为zval*型
	zval* arg
	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
		if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
			ZVAL_NEW_REF(params, arg);
			if (Z_REFCOUNTED_P(arg)) {
				Z_ADDREF_P(arg);
			}
		} else {
			ZVAL_COPY(params, arg);
		}
		params++;
		n++;
	} ZEND_HASH_FOREACH_END();
 
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_STR_KEY_VAL
//取键值对,键为zend_string*型,值为zval*型
				zend_string * key;
				zval * entry_value;
				ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) {
					if (key) { /* HASH_KEY_IS_STRING */
						size_t value_len = Z_STRLEN_P(entry_value);
 
						ca_payload_len += php_mysqlnd_net_store_length_size(ZSTR_LEN(key));
						ca_payload_len += ZSTR_LEN(key);
						ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
						ca_payload_len += value_len;
					}
				} ZEND_HASH_FOREACH_END();
				
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_KEY_VAL
//取hash中的键值对,键为zend_string*, zend_ulong型,值为zval*型
		if (options) {
			zval *attr_value;
			zend_ulong long_key;
			zend_string *str_key = NULL;
 
			ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), long_key, str_key, attr_value) {
				if (str_key) {
					continue;
				}
				pdo_dbh_attribute_set(dbh, long_key, attr_value);
			} ZEND_HASH_FOREACH_END();
		}
		
		
--------------------------------------------------------------------------------------------
//ZEND_HASH_FOREACH_PTR
//直接取hash中存的“值”,值为任意相应指针类型
pdo_driver_t *pdriver;
 
	if (zend_parse_parameters_none() == FAILURE) {
		return;
	}
 
	array_init(return_value);
 
	ZEND_HASH_FOREACH_PTR(&pdo_driver_hash, pdriver) {
		add_next_index_stringl(return_value, (char*)pdriver->driver_name, pdriver->driver_name_len);
	} ZEND_HASH_FOREACH_END();
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 11:35:50  更:2021-10-15 11:36:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 13:22:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计