andrei          Fri Jul 21 23:25:08 2006 UTC

  Modified files:              
    /php-src    unicode-progress.txt 
    /php-src/ext/standard       array.c 
  Log:
  Make array_*intersect* functions use params API with FCI cache and mark
  them with U.
  
  
http://cvs.php.net/viewvc.cgi/php-src/unicode-progress.txt?r1=1.29&r2=1.30&diff_format=u
Index: php-src/unicode-progress.txt
diff -u php-src/unicode-progress.txt:1.29 php-src/unicode-progress.txt:1.30
--- php-src/unicode-progress.txt:1.29   Thu Jul 20 23:21:32 2006
+++ php-src/unicode-progress.txt        Fri Jul 21 23:25:08 2006
@@ -10,13 +10,6 @@
     Need to fix string_compare_function() to compare Unicode strings
     directly in code point order
 
-    array_intersect(), array_uintersect()
-    array_intersect_assoc(), array_uintersect_assoc()
-    array_intersect_uassoc(), array_uintersect_uassoc()
-    array_intersect_key(), array_intersect_ukey()
-        Should work with minor cleanups provided that underlying comparison
-        functions are fixed, FCI cache, test
-
     array_multisort()
         Add SORT_LOCALE_STRING, test
 
@@ -79,6 +72,12 @@
     array_udiff_assoc(), array_udiff_uassoc()
     array_diff_key(), array_diff_ukey()
 
+    array_intersect(), array_uintersect()
+    array_intersect_assoc(), array_uintersect_assoc()
+    array_intersect_uassoc(), array_uintersect_uassoc()
+    array_intersect_key(), array_intersect_ukey()
+
+
   string.c
   --------
     addslashes()
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.372&r2=1.373&diff_format=u
Index: php-src/ext/standard/array.c
diff -u php-src/ext/standard/array.c:1.372 php-src/ext/standard/array.c:1.373
--- php-src/ext/standard/array.c:1.372  Fri Jul 21 07:34:18 2006
+++ php-src/ext/standard/array.c        Fri Jul 21 23:25:08 2006
@@ -21,7 +21,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: array.c,v 1.372 2006/07/21 07:34:18 dmitry Exp $ */
+/* $Id: array.c,v 1.373 2006/07/21 23:25:08 andrei Exp $ */
 
 #include "php.h"
 #include "php_ini.h"
@@ -1501,6 +1501,7 @@
 /* }}} */
 
 
+/* {{{ php_compact_var */
 static void php_compact_var(HashTable *eg_active_symbol_table, zval 
*return_value, zval *entry)
 {
        zstr key;
@@ -1552,6 +1553,7 @@
                }
        }
 }
+/* }}} */
 
 
 /* {{{ proto array compact(mixed var_names [, mixed ...]) U
@@ -2923,161 +2925,146 @@
 }
 /* }}} */
 
+/* {{{ php_array_intersect */
 static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, 
int data_compare_type, int key_compare_type)
 {
        zval ***args = NULL;
        HashTable *hash;
-       int argc, arr_argc, i, c = 0;
+       int arr_argc, i, c = 0;
        Bucket ***lists, **list, ***ptrs, *p;
-       
-       zval callback_name;
+       int req_args;
+       char *param_spec;
+       zend_fcall_info fci1, fci2;
+       zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = 
empty_fcall_info_cache;
+       zend_fcall_info *fci_key, *fci_data;
+       zend_fcall_info_cache *fci_key_cache, *fci_data_cache;
        PHP_ARRAY_CMP_FUNC_VARS;
-
        
        int (*intersect_key_compare_func)(const void *, const void * TSRMLS_DC);
        int (*intersect_data_compare_func)(const void *, const void * 
TSRMLS_DC);
 
-       /* Get the argument count */
-       argc = ZEND_NUM_ARGS();
-       /* Allocate arguments array and get the arguments, checking for errors. 
*/
-       args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
-       if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
-               efree(args);
-               WRONG_PARAM_COUNT;
-       }
-
-       PHP_ARRAY_CMP_FUNC_BACKUP();
-
        if (behavior == INTERSECT_NORMAL) {
                intersect_key_compare_func = array_key_compare;
+
                if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
                        /* array_intersect() */
 
-                       if (argc < 2) {
-                               efree(args);
-                               WRONG_PARAM_COUNT;
-                       }
-                       arr_argc = argc;
+                       req_args = 2;
+                       param_spec = "+";
                        intersect_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
                        /* array_uintersect() */
-                       if (argc < 3) {
-                               efree(args);
-                               WRONG_PARAM_COUNT;
-                       }
-                       arr_argc = argc - 1;
-                       intersect_data_compare_func = array_user_compare;
-                       if (!zend_is_callable(*args[arr_argc], 0, 
&callback_name)) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Not a valid callback %R", Z_TYPE(callback_name), Z_UNIVAL(callback_name));
-                               zval_dtor(&callback_name);
-                               efree(args);
-                               return;
-                       }
-                       zval_dtor(&callback_name);
 
-                       BG(user_compare_func_name) = args[arr_argc];
+                       req_args = 3;
+                       param_spec = "+f";
+                       intersect_data_compare_func = array_user_compare;
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"data_compare_type is %d. This should never happen. Please report as a bug", 
data_compare_type);
                        return;
                }
+
+               if (ZEND_NUM_ARGS() < req_args) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 
%d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
+                       return;
+               }
+
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
param_spec, &args,
+                                                                 &arr_argc, 
&fci1, &fci1_cache) == FAILURE) {
+                       return;
+               }
+               fci_data = &fci1;
+               fci_data_cache = &fci1_cache;
+
        } else if (behavior & INTERSECT_ASSOC) { /* triggered also when 
INTERSECT_KEY */
                /*
                        INTERSECT_KEY is subset of INTERSECT_ASSOC. When having 
the former
                        no comparison of the data is done (part of 
INTERSECT_ASSOC)
                */
                intersect_key_compare_func = array_key_compare;
+
                if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL
-                               &&
+                       &&
                        key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
                        /* array_intersect_assoc() or array_intersect_key() */
                        
-                       if (argc < 2) {
-                               efree(args);
-                               WRONG_PARAM_COUNT;
-                       }
-                       arr_argc = argc;
+                       req_args = 2;
+                       param_spec = "+";
+
                        intersect_key_compare_func = array_key_compare;
                        intersect_data_compare_func = php_array_data_compare;
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER 
-                               &&
-                               key_compare_type == 
INTERSECT_COMP_KEY_INTERNAL) {
+                                  &&
+                                  key_compare_type == 
INTERSECT_COMP_KEY_INTERNAL) {
                        /* array_uintersect_assoc() */
                        
-                       if (argc < 3) {
-                               efree(args);
-                               WRONG_PARAM_COUNT;
-                       }
-                       arr_argc = argc - 1;
-                       if (!zend_is_callable(*args[arr_argc], 0, 
&callback_name)) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Not a valid callback %R", Z_TYPE(callback_name), Z_UNIVAL(callback_name));
-                               zval_dtor(&callback_name);
-                               efree(args);
-                               return;
-                       }
-                       zval_dtor(&callback_name);
+                       req_args = 3;
+                       param_spec = "+f";
+
                        intersect_key_compare_func = array_key_compare;
                        intersect_data_compare_func = array_user_compare;
+                       fci_data = &fci1;
+                       fci_data_cache = &fci1_cache;
                } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL
-                               &&
-                               key_compare_type == INTERSECT_COMP_KEY_USER) {
-                               /* array_intersect_uassoc() or 
array_intersect_ukey() */
+                                  &&
+                                  key_compare_type == INTERSECT_COMP_KEY_USER) 
{
+                       /* array_intersect_uassoc() or array_intersect_ukey() */
                                
-                               if (argc < 3) {
-                                       efree(args);
-                                       WRONG_PARAM_COUNT;
-                               }
-                               arr_argc = argc - 1;
-                               if (!zend_is_callable(*args[arr_argc], 0, 
&callback_name)) {
-                                       php_error_docref(NULL TSRMLS_CC, 
E_WARNING, "Not a valid callback %R", Z_TYPE(callback_name), 
Z_UNIVAL(callback_name));
-                                       zval_dtor(&callback_name);
-                                       efree(args);
-                                       return;
-                               }
-                               zval_dtor(&callback_name);
-                               intersect_key_compare_func = 
array_user_key_compare;
-                               intersect_data_compare_func = 
php_array_data_compare;
-                               BG(user_compare_func_name) = args[arr_argc];
+                       req_args = 3;
+                       param_spec = "+f";
+
+                       intersect_key_compare_func = array_user_key_compare;
+                       intersect_data_compare_func = php_array_data_compare;
+                       fci_key = &fci1;
+                       fci_key_cache = &fci1_cache;
                } else if (data_compare_type == INTERSECT_COMP_DATA_USER
-                               &&
-                               key_compare_type == INTERSECT_COMP_KEY_USER) {
-                               /* array_uintersect_uassoc() */
-
-                               if (argc < 4) {
-                                       efree(args);
-                                       WRONG_PARAM_COUNT;
-                               }
-                               arr_argc = argc - 2;
-                               if (!zend_is_callable(*args[arr_argc], 0, 
&callback_name)) {
-                                       php_error_docref(NULL TSRMLS_CC, 
E_WARNING, "Not a valid callback %R", Z_TYPE(callback_name), 
Z_UNIVAL(callback_name));
-                                       zval_dtor(&callback_name);
-                                       efree(args);
-                                       return;
-                               } 
-                               zval_dtor(&callback_name);
-                               if (!zend_is_callable(*args[arr_argc + 1], 0, 
&callback_name)) {
-                                       php_error_docref(NULL TSRMLS_CC, 
E_WARNING, "Not a valid callback %R", Z_TYPE(callback_name), 
Z_UNIVAL(callback_name));
-                                       zval_dtor(&callback_name);
-                                       efree(args);
-                                       return;
-                               }
-                               zval_dtor(&callback_name);
-                               intersect_key_compare_func = 
array_user_key_compare;
-                               intersect_data_compare_func = 
array_user_compare;
-                               BG(user_compare_func_name) = args[arr_argc + 
1];/* data - key */
+                                  &&
+                                  key_compare_type == INTERSECT_COMP_KEY_USER) 
{
+                       /* array_uintersect_uassoc() */
+
+                       req_args = 4;
+                       param_spec = "+ff";
+
+                       intersect_key_compare_func = array_user_key_compare;
+                       intersect_data_compare_func = array_user_compare;
+                       fci_data = &fci1;
+                       fci_data_cache = &fci1_cache;
+                       fci_key = &fci2;
+                       fci_key_cache = &fci2_cache;
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"data_compare_type is %d. key_compare_type is %d. This should never happen. 
Please report as a bug.", data_compare_type, key_compare_type);
                        return;
-               }               
+               }
+
+               if (ZEND_NUM_ARGS() < req_args) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 
%d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
+                       return;
+               }
+
+               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
param_spec, &args, &arr_argc,
+                                                                 &fci1, 
&fci1_cache, &fci2, &fci2_cache) == FAILURE) {
+                       return;
+               }
+
        } else {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "behavior is %d. 
This should never happen. Please report as a bug", behavior);
                return;
        }
 
+       PHP_ARRAY_CMP_FUNC_BACKUP();
 
        /* for each argument, create and sort list with pointers to the hash 
buckets */
        lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
        ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
        php_set_compare_func(SORT_STRING TSRMLS_CC);
+
+       if (behavior == INTERSECT_NORMAL && data_compare_type == 
INTERSECT_COMP_DATA_USER) {
+               BG(user_compare_fci) = *fci_data;
+               BG(user_compare_fci_cache) = *fci_data_cache;
+       } else if (behavior & INTERSECT_ASSOC && key_compare_type == 
INTERSECT_COMP_KEY_USER) {
+               BG(user_compare_fci) = *fci_key;
+               BG(user_compare_fci_cache) = *fci_key_cache;
+       }
+
        for (i = 0; i < arr_argc; i++) {
                if (Z_TYPE_PP(args[i]) != IS_ARRAY) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument 
#%d is not an array", i+1);
@@ -3087,6 +3074,11 @@
                hash = HASH_OF(*args[i]);
                list = (Bucket **) pemalloc((hash->nNumOfElements + 1) * 
sizeof(Bucket *), hash->persistent);
                if (!list) {
+                       PHP_ARRAY_CMP_FUNC_RESTORE();
+
+                       efree(ptrs);
+                       efree(lists);
+                       efree(args);
                        RETURN_FALSE;
                }
                lists[i] = list;
@@ -3122,10 +3114,11 @@
        /* go through the lists and look for common values */
        while (*ptrs[0]) {
                if ((behavior & INTERSECT_ASSOC) /* triggered also when 
INTERSECT_KEY */
-                               &&
+                       &&
                        key_compare_type == INTERSECT_COMP_KEY_USER) {
 
-                       BG(user_compare_func_name) = args[argc - 1];
+                       BG(user_compare_fci) = *fci_key;
+                       BG(user_compare_fci_cache) = *fci_key_cache;
                }
 
                for (i = 1; i < arr_argc; i++) {
@@ -3146,12 +3139,14 @@
                                                wanted. 
                                        */ 
                                        if (data_compare_type == 
INTERSECT_COMP_DATA_USER) {
-                                               BG(user_compare_func_name) = 
args[arr_argc];
+                                               BG(user_compare_fci) = 
*fci_data;
+                                               BG(user_compare_fci_cache) = 
*fci_data_cache;
                                        }
                                        if 
(intersect_data_compare_func(ptrs[0], ptrs[i] TSRMLS_CC) != 0) {
                                                c = 1;
                                                if (key_compare_type == 
INTERSECT_COMP_KEY_USER) {
-                                                       
BG(user_compare_func_name) = args[argc - 1];
+                                                       BG(user_compare_fci) = 
*fci_key;
+                                                       
BG(user_compare_fci_cache) = *fci_key_cache;
                                                        /* When KEY_USER, the 
last parameter is always the callback */
                                                }
                                                /* we are going to the break */
@@ -3227,14 +3222,15 @@
        }
        
        PHP_ARRAY_CMP_FUNC_RESTORE();
-
        
        efree(ptrs);
        efree(lists);
        efree(args);
 }
+/* }}} */
+
 
-/* {{{ proto array array_intersect_key(array arr1, array arr2 [, array ...])
+/* {{{ proto array array_intersect_key(array arr1, array arr2 [, array ...]) U
    Returns the entries of arr1 that have keys which are present in all the 
other arguments. Kind of equivalent to array_diff(array_keys($arr1), 
array_keys($arr2)[,array_keys(...)]). Equivalent of array_intersect_assoc() but 
does not do compare of the data. */
 PHP_FUNCTION(array_intersect_key)
 {
@@ -3243,7 +3239,7 @@
 }
 /* }}} */
 
-/* {{{ proto array array_intersect_ukey(array arr1, array arr2 [, array ...], 
callback key_compare_func)
+/* {{{ proto array array_intersect_ukey(array arr1, array arr2 [, array ...], 
callback key_compare_func) U
    Returns the entries of arr1 that have keys which are present in all the 
other arguments. Kind of equivalent to array_diff(array_keys($arr1), 
array_keys($arr2)[,array_keys(...)]). The comparison of the keys is performed 
by a user supplied function. Equivalent of array_intersect_uassoc() but does 
not do compare of the data. */
 PHP_FUNCTION(array_intersect_ukey)
 {
@@ -3252,7 +3248,8 @@
 }
 /* }}} */
 
-/* {{{ proto array array_intersect(array arr1, array arr2 [, array ...])
+
+/* {{{ proto array array_intersect(array arr1, array arr2 [, array ...]) U
    Returns the entries of arr1 that have values which are present in all the 
other arguments */
 PHP_FUNCTION(array_intersect)
 {
@@ -3261,7 +3258,7 @@
 }
 /* }}} */
 
-/* {{{ proto array array_uintersect(array arr1, array arr2 [, array ...], 
callback data_compare_func)
+/* {{{ proto array array_uintersect(array arr1, array arr2 [, array ...], 
callback data_compare_func) U
    Returns the entries of arr1 that have values which are present in all the 
other arguments. Data is compared by using an user-supplied callback. */
 PHP_FUNCTION(array_uintersect)
 {
@@ -3271,7 +3268,7 @@
 /* }}} */
 
 
-/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [, array ...])
+/* {{{ proto array array_intersect_assoc(array arr1, array arr2 [, array ...]) 
U
    Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check */
 PHP_FUNCTION(array_intersect_assoc)
 {
@@ -3280,26 +3277,26 @@
 }
 /* }}} */
 
-
-/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array 
...], callback data_compare_func)
-   Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check. Data is compared 
by using an user-supplied callback. */
-PHP_FUNCTION(array_uintersect_assoc)
+/* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array 
...], callback key_compare_func) U
+   Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check and they are 
compared by using an user-supplied callback. */
+PHP_FUNCTION(array_intersect_uassoc)
 {
        php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC,
-                               INTERSECT_COMP_DATA_USER, 
INTERSECT_COMP_KEY_INTERNAL);
+                               INTERSECT_COMP_DATA_INTERNAL, 
INTERSECT_COMP_KEY_USER);
 }
 /* }}} */
 
-/* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array 
...], callback key_compare_func)
-   Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check and they are 
compared by using an user-supplied callback. */
-PHP_FUNCTION(array_intersect_uassoc)
+
+/* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array 
...], callback data_compare_func) U
+   Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check. Data is compared 
by using an user-supplied callback. */
+PHP_FUNCTION(array_uintersect_assoc)
 {
        php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC,
-                               INTERSECT_COMP_DATA_INTERNAL, 
INTERSECT_COMP_KEY_USER);
+                               INTERSECT_COMP_DATA_USER, 
INTERSECT_COMP_KEY_INTERNAL);
 }
 /* }}} */
 
-/* {{{ proto array array_uintersect_uassoc(array arr1, array arr2 [, array 
...], callback data_compare_func, callback key_compare_func)
+/* {{{ proto array array_uintersect_uassoc(array arr1, array arr2 [, array 
...], callback data_compare_func, callback key_compare_func) U
    Returns the entries of arr1 that have values which are present in all the 
other arguments. Keys are used to do more restrictive check. Both data and keys 
are compared by using user-supplied callbacks. */
 PHP_FUNCTION(array_uintersect_uassoc)
 {
@@ -3322,14 +3319,11 @@
        zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = 
empty_fcall_info_cache;
        zend_fcall_info *fci_key, *fci_data;
        zend_fcall_info_cache *fci_key_cache, *fci_data_cache;
-       
        PHP_ARRAY_CMP_FUNC_VARS;
 
        int (*diff_key_compare_func)(const void *, const void * TSRMLS_DC);
        int (*diff_data_compare_func)(const void *, const void * TSRMLS_DC);
        
-       PHP_ARRAY_CMP_FUNC_BACKUP();
-
        if (behavior == DIFF_NORMAL) {
                diff_key_compare_func = array_key_compare;
 
@@ -3352,14 +3346,11 @@
 
                if (ZEND_NUM_ARGS() < req_args) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 
%d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
-                       PHP_ARRAY_CMP_FUNC_RESTORE();
-                       efree(args);
                        return;
                }
 
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
param_spec, &args,
                                                                  &arr_argc, 
&fci1, &fci1_cache) == FAILURE) {
-                       PHP_ARRAY_CMP_FUNC_RESTORE();
                        return;
                }
                fci_data = &fci1;
@@ -3427,15 +3418,11 @@
 
                if (ZEND_NUM_ARGS() < req_args) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "at least 
%d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
-                       PHP_ARRAY_CMP_FUNC_RESTORE();
-                       efree(args);
                        return;
                }
 
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
param_spec, &args, &arr_argc,
                                                                  &fci1, 
&fci1_cache, &fci2, &fci2_cache) == FAILURE) {
-                       PHP_ARRAY_CMP_FUNC_RESTORE();
-                       efree(args);
                        return;
                }
 
@@ -3444,6 +3431,8 @@
                return; 
        }
 
+       PHP_ARRAY_CMP_FUNC_BACKUP();
+
        /* for each argument, create and sort list with pointers to the hash 
buckets */
        lists = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);
        ptrs = (Bucket ***)safe_emalloc(arr_argc, sizeof(Bucket **), 0);

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to