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 }