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. 新年春节EDM邮件内容设计案例分享

    春节自古以来都是中国最重要的节日.随着中国的发展,中国的春节在世界上都已受到越来越多人的关注,有许多国家和地区都将春节定为法定假日.与此同时,许多品牌营销商也选择在这个时候为中国客户发送马年新年邮件, ...

  2. pwa 总结

    概述 前几天了解并按照官方文档,成功实现了一个小型的 pwa demo,现在把总结记录下来,供以后开发时参考,相信对其他人也有用. pwa pwa 包括很多内容,我这里只介绍一部分,因为比如 Push ...

  3. USB转换PS2接线原理

    https://blog.csdn.net/dfyy88/article/details/4540170 USB转换PS2接线原理 2009年09月10日 18:36:00 阅读数:13285 USB ...

  4. 解析jmeter阶梯加压与请求的计算

    用百度做例子 我们设置阶梯加压线程组的请求参数,如下图 上图表示 1:每隔2秒钟,会在1秒内启动5个线程 2:每次线程加载之后都会运行2s然后开始下一次线程加载 3:最终会加载50个线程并持续运行30 ...

  5. LeetCode算法题-Flipping an Image(Java实现)

    这是悦乐书的第324次更新,第347篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第194题(顺位题号是832).给定二进制矩阵A,我们想要水平翻转图像,然后反转它,并返 ...

  6. Linux-定时任务-打包与压缩

    figure:first-child { margin-top: -20px; } #write ol, #write ul { position: relative; } img { max-wid ...

  7. linux 文件属性文件权限

    权限 -rw-------. root root Mar : anaconda-ks.cfg drwxr-xr-x root root May : dir1 drwxr-xr-x root root ...

  8. vue组件注册(极客时间Vue视频笔记)

    vue组件注册 组件是为了方便代码复用,只需引入组件即可在不同的地方使用想同的功能代码 <body> <div class="app"> <todo- ...

  9. AngularJS——基础小知识(一)

    $time0ut :定时器 $rootscope :全局的 $scope : 局部的作用域:   它下面的方法: $scope.$watch $scope.$apply   1)$scope.$wat ...

  10. maven中央仓库太慢的解决办法

    在.m2目录下创建settings.xml文件,文件内容如下: <?xml version="1.0" encoding="UTF-8"?> < ...