php内置函数分析之array_diff_assoc()

  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 }

猜你喜欢

转载自www.cnblogs.com/natian-ws/p/9153414.html