Commit:    1a03bd5dee97a0f8b9e74b7f8db5231abd8cc7e4
Author:    Sara Golemon <poll...@php.net>         Mon, 22 Apr 2013 14:57:05 
-0700
Parents:   f63db963c48775e89e7d5f63235733098c2f653d
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=1a03bd5dee97a0f8b9e74b7f8db5231abd8cc7e4

Log:
Allow array_column() to take -1 as a valid value in third param

Also do some cleanup and simplification to make this code more
readable in the long term.

Changed paths:
  M  ext/standard/array.c
  M  ext/standard/tests/array/array_column_basic.phpt


Diff:
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 425d53e..6f769da 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -2524,132 +2524,95 @@ PHP_FUNCTION(array_count_values)
 }
 /* }}} */
 
+/* {{{ array_column_param_helper
+ * Specialized conversion rules for array_column() function
+ */
+static inline
+zend_bool array_column_param_helper(zval **param,
+                                    const char *name TSRMLS_DC) {
+       switch (Z_TYPE_PP(param)) {
+               case IS_NULL:
+               case IS_DOUBLE:
+                       convert_to_long_ex(param);
+                       /* fallthrough */
+               case IS_LONG:
+                       return 1;
+
+               case IS_OBJECT:
+                       convert_to_string_ex(param);
+                       /* fallthrough */
+               case IS_STRING:
+                       return 1;
+
+               default:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "The %s key 
should be either a string or an integer", name);
+                       return 0;
+       }
+}
+
 /* {{{ proto array array_column(array input, mixed column_key[, mixed 
index_key])
    Return the values from a single column in the input array, identified by the
    value_key and optionally indexed by the index_key */
 PHP_FUNCTION(array_column)
 {
-       zval *zarray, **zcolumn, **zkey = NULL, **data, **zcolval, **zkeyval;
+       zval **zcolumn, **zkey = NULL, **data;
        HashTable *arr_hash;
        HashPosition pointer;
-       ulong column_idx = 0, key_idx = 0;
-       char *column = NULL, *key = NULL, *keyval = NULL;
-       int column_len = 0, key_len = 0, keyval_idx = -1;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aZ|Z", &zarray, 
&zcolumn, &zkey) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "hZ|Z!", 
&arr_hash, &zcolumn, &zkey) == FAILURE) {
                return;
        }
 
-       switch (Z_TYPE_PP(zcolumn)) {
-               case IS_NULL:
-                       column_idx = 0;
-                       break;
-               case IS_LONG:
-                       column_idx = Z_LVAL_PP(zcolumn);
-                       break;
-               case IS_DOUBLE:
-                       column_idx = (long)Z_DVAL_PP(zcolumn);
-                       break;
-               case IS_STRING:
-                       column = Z_STRVAL_PP(zcolumn);
-                       column_len = Z_STRLEN_PP(zcolumn);
-                       break;
-               case IS_OBJECT:
-                       convert_to_string_ex(zcolumn);
-                       column = Z_STRVAL_PP(zcolumn);
-                       column_len = Z_STRLEN_PP(zcolumn);
-                       break;
-               default:
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "The column 
key should be either a string or an integer");
-                       RETURN_FALSE;
-       }
-
-       if (zkey) {
-               switch (Z_TYPE_PP(zkey)) {
-                       case IS_NULL:
-                               key_idx = 0;
-                               break;
-                       case IS_LONG:
-                               key_idx = Z_LVAL_PP(zkey);
-                               break;
-                       case IS_DOUBLE:
-                               key_idx = (long)Z_DVAL_PP(zkey);
-                               break;
-                       case IS_STRING:
-                               key = Z_STRVAL_PP(zkey);
-                               key_len = Z_STRLEN_PP(zkey);
-                               break;
-                       case IS_OBJECT:
-                               convert_to_string_ex(zkey);
-                               key = Z_STRVAL_PP(zkey);
-                               key_len = Z_STRLEN_PP(zkey);
-                               break;
-                       default:
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"The index key should be either a string or an integer");
-                               RETURN_FALSE;
-               }
+       if (!array_column_param_helper(zcolumn, "column" TSRMLS_CC) ||
+           (zkey && !array_column_param_helper(zkey, "index" TSRMLS_CC))) {
+               RETURN_FALSE;
        }
 
-       arr_hash = Z_ARRVAL_P(zarray);
        array_init(return_value);
-
        for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
                        zend_hash_get_current_data_ex(arr_hash, (void**)&data, 
&pointer) == SUCCESS;
                        zend_hash_move_forward_ex(arr_hash, &pointer)) {
+               zval **zcolval, **zkeyval = NULL;
+               HashTable *ht;
 
-               if (Z_TYPE_PP(data) == IS_ARRAY) {
-                       zval *strkey = NULL;
-
-                       if (column && zend_hash_find(Z_ARRVAL_PP(data), column, 
column_len + 1, (void**)&zcolval) == FAILURE) {
-                               continue;
-                       } else if (!column && 
zend_hash_index_find(Z_ARRVAL_PP(data), column_idx, (void**)&zcolval) == 
FAILURE) {
-                               continue;
-                       }
-
-                       Z_ADDREF_PP(zcolval);
-
-                       keyval = NULL;
-                       keyval_idx = -1;
-
-                       if (zkey) {
-                               if (key && zend_hash_find(Z_ARRVAL_PP(data), 
key, key_len + 1, (void**)&zkeyval) == FAILURE) {
-                                       keyval_idx = -1;
-                               } else if (!key && 
zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) {
-                                       keyval_idx = -1;
-                               } else {
-                                       switch (Z_TYPE_PP(zkeyval)) {
-                                               case IS_LONG:
-                                                       keyval_idx = 
Z_LVAL_PP(zkeyval);
-                                                       break;
-                                               case IS_STRING:
-                                                       keyval = 
Z_STRVAL_PP(zkeyval);
-                                                       break;
-                                               case IS_OBJECT:
-                                                       {
-                                                               
MAKE_STD_ZVAL(strkey);
-                                                               
MAKE_COPY_ZVAL(zkeyval, strkey);
-                                                               
convert_to_string(strkey);
-                                                               keyval = 
Z_STRVAL_P(strkey);
-                                                       }
-                                                       break;
-                                               default:
-                                                       keyval_idx = -1;
-                                       }
-                               }
-                       }
+               if (Z_TYPE_PP(data) != IS_ARRAY) {
+                       /* Skip elemens which are not sub-arrays */
+                       continue;
+               }
+               ht = Z_ARRVAL_PP(data);
 
-                       if (keyval) {
-                               add_assoc_zval(return_value, keyval, *zcolval);
-                               if (strkey) {
-                                       zval_ptr_dtor(&strkey);
-                               }
-                       } else if (keyval_idx != -1) {
-                               add_index_zval(return_value, keyval_idx, 
*zcolval);
-                       } else {
-                               add_next_index_zval(return_value, *zcolval);
-                       }
+               /* Skip if the value doesn't exist in our subarray */
+               if ((Z_TYPE_PP(zcolumn) == IS_STRING) &&
+                   (zend_hash_find(ht, Z_STRVAL_PP(zcolumn), 
Z_STRLEN_PP(zcolumn) + 1, (void**)&zcolval) == FAILURE)) {
+                       continue;
+               } else if ((Z_TYPE_PP(zcolumn) == IS_LONG) &&
+                   (zend_hash_index_find(ht, Z_LVAL_PP(zcolumn), 
(void**)&zcolval) == FAILURE)) {
+                       continue;
                }
 
+               /* Failure will leave zkeyval alone which will land us on the 
final else block below
+                * which is to append the value as next_index
+                */
+               if (zkey && (Z_TYPE_PP(zkey) == IS_STRING)) {
+                       zend_hash_find(ht, Z_STRVAL_PP(zkey), Z_STRLEN_PP(zkey) 
+ 1, (void**)&zkeyval);
+               } else if (zkey && (Z_TYPE_PP(zkey) == IS_LONG)) {
+                       zend_hash_index_find(ht, Z_LVAL_PP(zkey), 
(void**)&zkeyval);
+               }
+
+               Z_ADDREF_PP(zcolval);
+               if (zkeyval && Z_TYPE_PP(zkeyval) == IS_STRING) {
+                       add_assoc_zval(return_value, Z_STRVAL_PP(zkeyval), 
*zcolval);
+               } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_LONG) {
+                       add_index_zval(return_value, Z_LVAL_PP(zkeyval), 
*zcolval);
+               } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_OBJECT) {
+                       zval copyval;
+                       ZVAL_ZVAL(&copyval, *zkeyval, 1, 0);
+                       convert_to_string(&copyval);
+                       add_assoc_zval(return_value, Z_STRVAL(copyval), 
*zcolval);
+                       zval_dtor(&copyval);
+               } else {
+                       add_next_index_zval(return_value, *zcolval);
+               }
        }
 }
 /* }}} */
diff --git a/ext/standard/tests/array/array_column_basic.phpt 
b/ext/standard/tests/array/array_column_basic.phpt
index eb267da..7c30cdf 100644
--- a/ext/standard/tests/array/array_column_basic.phpt
+++ b/ext/standard/tests/array/array_column_basic.phpt
@@ -84,11 +84,12 @@ echo "\n*** Testing numeric column keys ***\n";
 $numericCols = array(
        array('aaa', '111'),
        array('bbb', '222'),
-       array('ccc', '333')
+       array('ccc', '333', -1 => 'ddd')
 );
 var_dump(array_column($numericCols, 1));
 var_dump(array_column($numericCols, 1, 0));
 var_dump(array_column($numericCols, 1, 0.123));
+var_dump(array_column($numericCols, 1, -1));
 
 echo "\n*** Testing failure to find specified column ***\n";
 var_dump(array_column($numericCols, 2));
@@ -239,6 +240,14 @@ array(3) {
   ["ccc"]=>
   string(3) "333"
 }
+array(3) {
+  [0]=>
+  string(3) "111"
+  [1]=>
+  string(3) "222"
+  ["ddd"]=>
+  string(3) "333"
+}
 
 *** Testing failure to find specified column ***
 array(0) {


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

Reply via email to