summaryrefslogtreecommitdiff
path: root/ext/standard/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r--ext/standard/array.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 91a8833347..fa19737522 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -2563,42 +2563,66 @@ PHP_FUNCTION(array_count_values)
}
/* }}} */
-/* {{{ proto array array_column(array input, mixed key)
- Return the values from a single column in the input array, identified by the key */
+/* {{{ 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, *zoffset, **data, **zvalue;
+ zval *zarray, *zcolumn, *zkey = NULL, **data, **zcolval, **zkeyval;
HashTable *arr_hash;
HashPosition pointer;
- long index = 0;
- char *key = NULL;
- int key_len = 0;
+ ulong column_idx = 0, key_idx = 0, keyval_idx = 0;
+ char *column = NULL, *key = NULL, *keyval = NULL;
+ int column_len = 0, key_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &zarray, &zoffset) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|z", &zarray, &zcolumn, &zkey) == FAILURE) {
return;
}
- switch (Z_TYPE_P(zoffset)) {
+ switch (Z_TYPE_P(zcolumn)) {
case IS_NULL:
- index = 0;
+ column_idx = 0;
break;
case IS_LONG:
- index = Z_LVAL_P(zoffset);
+ column_idx = Z_LVAL_P(zcolumn);
break;
case IS_STRING:
- key = Z_STRVAL_P(zoffset);
- key_len = Z_STRLEN_P(zoffset);
+ column = Z_STRVAL_P(zcolumn);
+ column_len = Z_STRLEN_P(zcolumn);
break;
case IS_OBJECT:
- convert_to_string(zoffset);
- key = Z_STRVAL_P(zoffset);
- key_len = Z_STRLEN_P(zoffset);
+ convert_to_string(zcolumn);
+ column = Z_STRVAL_P(zcolumn);
+ column_len = Z_STRLEN_P(zcolumn);
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "The key should be either a string or an integer");
+ 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_P(zkey)) {
+ case IS_NULL:
+ key_idx = 0;
+ break;
+ case IS_LONG:
+ key_idx = Z_LVAL_P(zkey);
+ break;
+ case IS_STRING:
+ key = Z_STRVAL_P(zkey);
+ key_len = Z_STRLEN_P(zkey);
+ break;
+ case IS_OBJECT:
+ convert_to_string(zkey);
+ key = Z_STRVAL_P(zkey);
+ key_len = Z_STRLEN_P(zkey);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The index key should be either a string or an integer");
+ RETURN_FALSE;
+ }
+ }
+
arr_hash = Z_ARRVAL_P(zarray);
array_init(return_value);
@@ -2607,14 +2631,47 @@ PHP_FUNCTION(array_column)
zend_hash_move_forward_ex(arr_hash, &pointer)) {
if (Z_TYPE_PP(data) == IS_ARRAY) {
- if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zvalue) == FAILURE) {
+ if (column && zend_hash_find(Z_ARRVAL_PP(data), column, column_len + 1, (void**)&zcolval) == FAILURE) {
continue;
- } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), index, (void**)&zvalue) == FAILURE) {
+ } else if (!column && zend_hash_index_find(Z_ARRVAL_PP(data), column_idx, (void**)&zcolval) == FAILURE) {
continue;
}
- Z_ADDREF_PP(zvalue);
- add_next_index_zval(return_value, *zvalue);
+ Z_ADDREF_PP(zcolval);
+
+ keyval = NULL;
+ keyval_idx = NULL;
+
+ if (zkey) {
+ if (key && zend_hash_find(Z_ARRVAL_PP(data), key, key_len + 1, (void**)&zkeyval) == FAILURE) {
+ keyval_idx = NULL;
+ } else if (!key && zend_hash_index_find(Z_ARRVAL_PP(data), key_idx, (void**)&zkeyval) == FAILURE) {
+ keyval_idx = NULL;
+ } 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:
+ convert_to_string(*zkeyval);
+ keyval = Z_STRVAL_PP(zkeyval);
+ break;
+ default:
+ keyval_idx = NULL;
+ }
+ }
+ }
+
+ if (keyval) {
+ add_assoc_zval(return_value, keyval, *zcolval);
+ } else if (keyval_idx != NULL) {
+ add_index_zval(return_value, keyval_idx, *zcolval);
+ } else {
+ add_next_index_zval(return_value, *zcolval);
+ }
}
}