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. Dataframe的索引问题

    1 两个Dataframe相加时,一定要注意索引是否对应再相加,利用这个特点有时可以先用set_index()将某些列置为索引列,再进行相加. import pandas as pd df1 = pd ...

  2. keepalive + nginx 搭建高可用集群动态网站

    环境准备: 两台节点部署keepalived,并且设为互为主从,实现高可用. 两台从节点部署nginx以及相关组件,作为真实服务器实现动态网站上线. 一.MASTER(BACKUP)节点下载keepa ...

  3. SQLSERVER 和 ORACLE 查询数据库文件大小

    SQLSERVER: SQLSERVER一个库的文件分为数据文件(行数据)和日志文件两个文件,详情可以在数据库的属性->文件中查看. 在资源管理器中打开文件所在路径可以直接看到这两个文件 但是, ...

  4. 远程桌面 使用 本地输入法(虚拟化 终端 远程接入 RemoteApp)

    远程桌面连接组件是微软从Windows 2000 Server开始提供的,该组件一经推出便受到了很多用户的拥护和使用.   在WINDOWS XP和WINDOWS SERVER 2003中微软公司将该 ...

  5. FTP搭建YUM源服务器

    一.FTP搭建YUM源服务器 1.服务器 挂载centos镜像[root@localhost ~]#yum install vsftpd[root@localhost ~]#systemctl sta ...

  6. 知识图谱之图数据库Neo4j

    知识图谱中的知识是通过RDF结构来进行表示的,其基本单元是事实.每个事实是一个三元组(S, P, O),在实际系统中,按照存储方式的不同,知识图谱的存储可以分为基于表结构的存储和基于图结构的存储. 基 ...

  7. eclipse maven 项目突然所有的JS方法都失效了

    原因:JS 或者 jQuery 有严重的语法错误

  8. 前端 CSS 盒子模型 边框 border属性

    边框 border:边框的意思,描述盒子的边框 边框有三个要素: 粗细 线性样式 颜色 border: solid border特性 如果颜色不写,默认是黑色.如果粗细不写,不显示边框.如果只写线性样 ...

  9. CentOSLinux安装Docker容器

    Docker 使用 环境说明 CentOS 7.3(不准确地说:要求必须是 CentOS 7 64位) 不建议在 Windows 上使用 Docker 基本概念 官网:https://www.dock ...

  10. 洛谷 P5661 公交换乘 & [NOIP2019普及组] (模拟)

    传送门 解题思路 先把所有的数据读下来. 对于地铁,答案直接加,然后把编号放入一个数组a内. 对于公交车,从前往后枚举a数组,然后找到出现最早的且符合价钱大于等于公交车的价钱,然后把这个数删除(变为0 ...