php内置函数分析array_diff()

 1 PHP_FUNCTION(array_diff)
 2 {
 3     zval *args;
 4     int argc, i;
 5     uint32_t num;
 6     HashTable exclude;
 7     zval *value;
 8     zend_string *str, *key;
 9     zend_long idx;
10     zval dummy;
11 
12     // 至少两个参数
13     if (ZEND_NUM_ARGS() < 2) {
14         php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
15         return;
16     }
17     // 类型描述符:*  variable arguments list (0 or more)
18     // 类型描述符:+  variable arguments list (1 or more)
19     // 参数存放在数组args中,argc保存参数个数
20     if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
21         return;
22     }
23 
24     // 第一个参数不是数组,则报错
25     if (Z_TYPE(args[0]) != IS_ARRAY) {
26         php_error_docref(NULL, E_WARNING, "Argument #1 is not an array");
27         RETURN_NULL(); // 返回NULL
28     }
29 
30     /* count number of elements */
31     // 检查所有参数是否是数组
32     num = 0;
33     for (i = 1; i < argc; i++) {
34         if (Z_TYPE(args[i]) != IS_ARRAY) {
35             php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
36             RETURN_NULL(); // 返回NULL
37         }
38         num += zend_hash_num_elements(Z_ARRVAL(args[i])); // 所有参数数组的元素个数累加
39     }
40 
41     // 元素个数num为0,返回第一个参数数组(空数组)
42     if (num == 0) {
43         ZVAL_COPY(return_value, &args[0]);
44         return;
45     }
46 
47     ZVAL_NULL(&dummy);
48     /* create exclude map */
49     zend_hash_init(&exclude, num, NULL, NULL, 0);
50     // 从第二个数组开始,所以数组元素保存到exclude
51     for (i = 1; i < argc; i++) {
52         // 遍历数组
53         ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
54             str = zval_get_string(value); // 数组元素值转为字符串
55             zend_hash_add(&exclude, str, &dummy); // 
56             zend_string_release(str);
57         } ZEND_HASH_FOREACH_END();
58     }
59 
60     /* copy all elements of first array that are not in exclude set */
61     // 初始化返回值数组,大小和第一个数组一致。
62     array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
63     // 循环遍历第一个数组
64     ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) {
65         str = zval_get_string(value); // 元素值转为字符串
66         if (!zend_hash_exists(&exclude, str)) { // exclude中找不到该值
67             // 插入到返回值数组中(差集),键名保留不变。
68             if (key) {
69                 value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
70             } else {
71                 value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);
72             }
73             zval_add_ref(value);
74         }
75         zend_string_release(str);
76     } ZEND_HASH_FOREACH_END();
77 
78     zend_hash_destroy(&exclude);
79 }

 

posted @ 2018-06-07 17:44  S3c0ldW4ng  阅读(522)  评论(0编辑  收藏  举报