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间接类型保存变量 的部分介绍
遍历的操作函数 集合
--------------------------------------------------------------------------------------------
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_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();
--------------------------------------------------------------------------------------------
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();
--------------------------------------------------------------------------------------------
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_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_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();
--------------------------------------------------------------------------------------------
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_string * key;
zval * entry_value;
ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) {
if (key) {
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();
--------------------------------------------------------------------------------------------
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();
}
--------------------------------------------------------------------------------------------
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();
|