1 static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
2 {
3 uint idx;
4 Bucket *p;
5 int argc, i;
6 zval *args;
7 int (*diff_data_compare_func)(zval *, zval *) = NULL;
8 zend_bool ok;
9 zval *val, *data;
10
11 /* Get the argument count */
12 argc = ZEND_NUM_ARGS();
13 if (data_compare_type == DIFF_COMP_DATA_USER) { // array_diff_uassoc
14 if (argc < 3) {
15 php_error_docref(NULL, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
16 return;
17 }
18 // 类型描述符:f - function or array containing php method call info (returned as zend_fcall_info and zend_fcall_info_cache)
19 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
20 return;
21 }
22 diff_data_compare_func = zval_user_compare; // 用户自定义的回调函数
23 } else {
24 // 至少两个参数
25 if (argc < 2) {
26 php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
27 return;
28 }
29 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
30 return;
31 }
32 // array_diff_assoc
33 if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
34 diff_data_compare_func = zval_compare; //字符串比较函数
35 }
36 }
37
38 // 参数(array_diff_uassoc时回调函数除外)必须是数组
39 for (i = 0; i < argc; i++) {
40 if (Z_TYPE(args[i]) != IS_ARRAY) {
41 php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
42 RETURN_NULL();
43 }
44 }
45
46 array_init(return_value);
47
48 // 循环第一个数组
49 for (idx = 0; idx < Z_ARRVAL(args[0])->nNumUsed; idx++) {
50 p = Z_ARRVAL(args[0])->arData + idx;
51 val = &p->val;
52 if (Z_TYPE_P(val) == IS_UNDEF) continue; // 跳过已销毁的元素。
53 if (UNEXPECTED(Z_TYPE_P(val) == IS_INDIRECT)) { // ???
54 val = Z_INDIRECT_P(val);
55 if (Z_TYPE_P(val) == IS_UNDEF) continue;
56 }
57 if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
58 ZVAL_UNREF(val);
59 }
60 if (p->key == NULL) { // 键为整数
61 ok = 1;
62 // 遍历其他数组,查找
63 for (i = 1; i < argc; i++) {
64 // 键和值都要一致
65 if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) != NULL &&
66 (!diff_data_compare_func ||
67 diff_data_compare_func(val, data) == 0)
68 ) {
69 // 找到之后,ok置为0
70 ok = 0;
71 break;
72 }
73 }
74 // 没有再其他数组中找到,则将该元素(键和值)保存到return_value中
75 if (ok) {
76 if (Z_REFCOUNTED_P(val)) {
77 Z_ADDREF_P(val);
78 }
79 zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
80 }
81 } else { // 键为字符串
82 ok = 1;
83 for (i = 1; i < argc; i++) {
84 // 键和值都要一致
85 if ((data = zend_hash_find_ind(Z_ARRVAL(args[i]), p->key)) != NULL &&
86 (!diff_data_compare_func ||
87 diff_data_compare_func(val, data) == 0)
88 ) {
89 // 找到之后,ok置为0
90 ok = 0;
91 break;
92 }
93 }
94 // 没有再其他数组中找到,则将该元素(键和值)保存到return_value中
95 if (ok) {
96 if (Z_REFCOUNTED_P(val)) {
97 Z_ADDREF_P(val);
98 }
99 zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
100 }
101 }
102 }
103 }