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. Make jQuery throw error when it doesn't match an element

    Make jQuery throw error when it doesn't match an element 解答1 You could make a plugin to use to ensur ...

  2. [python] Pythonic语法笔记

    Pythonic语法笔记 __new__ 在类实例化之前执行的,也就是在init之前执行,可以为这个类写操作.接受的参数不是self而是cls.只有在new方法里返回类才会执行init操作,需要返回父 ...

  3. 线性时间求取第 K 大数

    求 Top K 的算法主要有基于快速排序的和基于堆的这两种,它们的时间复杂度都为 \(O(nlogK)\).借助于分治思想,以及快速排序的区间划分,我们可以做到 \(O(n)\) 时间复杂度.具体算法 ...

  4. Spring mvc注解说明

    编号 注解 说明 位置 备注 1 @Controller 将类变成Spring Bean 类 现阶段 @Controller . @Service 以及 @Repository 和 @Componen ...

  5. 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第2节 maven的安装和仓库种类_05仓库的种类和彼此关系

    maven工程里面放的是jar包的坐标. 启动项目的时候会根据jar包的坐标到仓库中找对应的坐标 maven的安装目录.conf/settings.xml文件 ${user.home}表示系统盘,用户 ...

  6. 测开之路一百五十五:jquery-validation前台数据验证

    前面做的wtform验证是服务器端的验证,需要把数据传输到服务器,服务器验证后再吧结果传输到前端,网络慢的时候,用户体验不好,所以需要前端验证,且后端验证不能少 传统的js或者jquery如果要验证信 ...

  7. :hover 鼠标同时触发两个元素变化

    HTML代码: <li> <span>4</span> <a href="#">巨型一号丝瓜水320ML</a>< ...

  8. 科普:PV,UV,VV,IP

    1.PV PV即Page View,即页面浏览量或点击量,用户每一次对网站中的每个网页访问均被记录一次.用户对同一页面的多次访问,访问量累计. 2.UV UV即Unique Visitor,是指通过互 ...

  9. 使用logstash收集java、nginx、系统等常见日志

    目录 1.使用codec的multiline插件收集java日志... 1 2.收集nginx日志... 2 3.收集系统syslog日志... 3 4.使用fliter的grok模块收集mysql日 ...

  10. 数据契约[DataContract]

    数据契约(DataContract)服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型.一旦声明一个类型为DataContract,那么该类型就可以被序列 ...