static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
{
uint idx;
Bucket *p;
int argc, i;
zval *args;
int (*diff_data_compare_func)(zval *, zval *) = NULL;
zend_bool ok;
zval *val, *data; /* Get the argument count */
argc = ZEND_NUM_ARGS();
if (data_compare_type == DIFF_COMP_DATA_USER) { // array_diff_uassoc
if (argc < ) {
php_error_docref(NULL, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
return;
}
// 类型描述符:f - function or array containing php method call info (returned as zend_fcall_info and zend_fcall_info_cache)
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
return;
}
diff_data_compare_func = zval_user_compare; // 用户自定义的回调函数
} else {
// 至少两个参数
if (argc < ) {
php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
return;
}
if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
return;
}
// array_diff_assoc
if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
diff_data_compare_func = zval_compare; //字符串比较函数
}
} // 参数(array_diff_uassoc时回调函数除外)必须是数组
for (i = ; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + );
RETURN_NULL();
}
} array_init(return_value); // 循环第一个数组
for (idx = ; idx < Z_ARRVAL(args[])->nNumUsed; idx++) {
p = Z_ARRVAL(args[])->arData + idx;
val = &p->val;
if (Z_TYPE_P(val) == IS_UNDEF) continue; // 跳过已销毁的元素。
if (UNEXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) { // ???
val = Z_INDIRECT_P(val);
if (Z_TYPE_P(val) == IS_UNDEF) continue;
}
if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == ) {
ZVAL_UNREF(val);
}
if (p->key == NULL) { // 键为整数
ok = ;
// 遍历其他数组,查找
for (i = ; i < argc; i++) {
// 键和值都要一致
if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) != NULL &&
(!diff_data_compare_func ||
diff_data_compare_func(val, data) == )
) {
// 找到之后,ok置为0
ok = ;
break;
}
}
// 没有再其他数组中找到,则将该元素(键和值)保存到return_value中
if (ok) {
if (Z_REFCOUNTED_P(val)) {
Z_ADDREF_P(val);
}
zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
}
} else { // 键为字符串
ok = ;
for (i = ; i < argc; i++) {
// 键和值都要一致
if ((data = zend_hash_find_ind(Z_ARRVAL(args[i]), p->key)) != NULL &&
(!diff_data_compare_func ||
diff_data_compare_func(val, data) == )
) {
// 找到之后,ok置为0
ok = ;
break;
}
}
// 没有再其他数组中找到,则将该元素(键和值)保存到return_value中
if (ok) {
if (Z_REFCOUNTED_P(val)) {
Z_ADDREF_P(val);
}
zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
}
}
}
}

php内置函数分析之array_diff_assoc()的更多相关文章

  1. map内置函数分析所得到的思路

    map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...

  2. php内置函数分析之array_combine()

    PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...

  3. php内置函数分析之ucwords()

    PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...

  4. php内置函数分析之strtoupper()、strtolower()

    strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...

  5. php内置函数分析之ucfirst()、lcfirst()

    ucfirst($str) 将 str 的首字符(如果首字符是字母)转换为大写字母,并返回这个字符串. 源码位于 ext/standard/string.c /* {{{ php_ucfirst Up ...

  6. php内置函数分析之trim()

    官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...

  7. php内置函数分析之str_pad()

    PHP_FUNCTION(str_pad) { /* Input arguments */ zend_string *input; /* Input string 输入字符串*/ zend_long ...

  8. php内置函数分析之array_fill_keys()

    PHP_FUNCTION(array_fill_keys) { zval *keys, *val, *entry; if (zend_parse_parameters(ZEND_NUM_ARGS(), ...

  9. php内置函数分析range()

    PHP_FUNCTION(range) { zval *zlow, *zhigh, *zstep = NULL, tmp; , is_step_double = ; double step = 1.0 ...

随机推荐

  1. 如何使用Jetbrains Clion 在一个工程里 编译单个C++源文件 (实现一键编译且运行)

    这篇文章主要在下面这篇文章的基础上,先是实现了一键编译和一键运行两个单个功能,最后又进一步使用Clion自带的Custom Build Application实现编译且运行一键实现. https:// ...

  2. python读取文件时遇到非法字符的处理 UnicodeDecodeError: 'gbk' codec can't decode bytes in position

    报错UnicodeDecodeError: 'gbk' codec can't decode bytes in position ipath = 'D:/学习/语料库/SogouC.mini/Samp ...

  3. EDM概念之A/B分类测试法

    相信很多情况下大家都会看到A/B分类测试法这个专业术语,下面博主简要介绍下什么是A/B分类测试法. 这里的A和B主要是指两种不同版本的电子邮件.一般来说,可以将用户分为同等数量的两组,一组发送A版本, ...

  4. 使用C#分层查询多个表数据

    下面我来给大家叙述一下视野分层加载多张表数据: 首先创建一个StudentExtends类: 在DAL层studentDAL类写如下代码: 在BLL层写如下代码,引用DAL层的LoadStudentI ...

  5. 【命令汇总】XSS payload 速查表

    日期:2019-05-15 14:06:21 作者:Bay0net 介绍:收集并且可用的一些 XSS payload,网上的速查表很多,但是测试了下很多 payload 的不可用,这里都是自己能用的 ...

  6. ActionList及Action使用

    ActionList及Action使用 https://blog.csdn.net/adamrao/article/details/7450889 2012年04月11日 19:09:27 阅读数:1 ...

  7. 关于OPC连接读写下位机PLC(转)

    原文转自:http://blog.csdn.net/u012252959/article/details/49736285?locationNum=11 开发OPC客户端程序时,首先应该生成OPC服务 ...

  8. Java ——异常处理

    本节重点思维导图 详细戳——> 异常处理

  9. 【MM系列】SAP MM模块-配置PO的创建时间

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-配置PO的创建时间 ...

  10. 【MM系列】SAP MB5B中FI凭证摘要是激活的/结果可能不正确 的错误

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MB5B中FI凭证摘要是激活 ...