summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/array.c71
-rw-r--r--ext/standard/basic_functions.c1
-rw-r--r--ext/standard/php_array.h1
3 files changed, 73 insertions, 0 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 2807129fa0..4e931c76e7 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -3276,6 +3276,77 @@ PHP_FUNCTION(key_exists)
}
/* }}} */
+
+/* {{{ proto array array_chunk(array input, int size [, bool preserve_keys])
+ Split array into chunks */
+PHP_FUNCTION(array_chunk)
+{
+ int argc = ZEND_NUM_ARGS(), key_type;
+ long size, current = 0;
+ char *str_key;
+ uint str_key_len;
+ ulong num_key;
+ zend_bool preserve_keys = 0;
+ zval *input = NULL;
+ zval *chunk = NULL;
+ zval **entry;
+ HashPosition pos;
+
+ if (zend_parse_parameters(argc TSRMLS_CC, "al|b", &input, &size,
+ &preserve_keys) == FAILURE)
+ return;
+
+ /* Do bounds checking for size parameter. */
+ if (size < 1) {
+ php_error(E_WARNING, "%s() expects the size parameter to be > 0",
+ get_active_function_name(TSRMLS_C));
+ return;
+ }
+
+ array_init(return_value);
+
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void**)&entry, &pos) == SUCCESS) {
+ /* If new chunk, create and initialize it. */
+ if (!chunk) {
+ MAKE_STD_ZVAL(chunk);
+ array_init(chunk);
+ }
+
+ /* Add entry to the chunk, preserving keys if necessary. */
+ zval_add_ref(entry);
+
+ if (preserve_keys) {
+ key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key,
+ &str_key_len, &num_key, 0, &pos);
+ if (key_type == HASH_KEY_IS_STRING) {
+ add_assoc_zval_ex(chunk, str_key, str_key_len, *entry);
+ } else {
+ add_index_zval(chunk, num_key, *entry);
+ }
+ } else {
+ add_next_index_zval(chunk, *entry);
+ }
+
+ /*
+ * If reached the chunk size, add it to the result array, and reset the
+ * pointer.
+ */
+ if (!(++current % size)) {
+ add_next_index_zval(return_value, chunk);
+ chunk = NULL;
+ }
+
+ zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
+ }
+
+ /* Add the final chunk if there is one. */
+ if (chunk) {
+ add_next_index_zval(return_value, chunk);
+ }
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 8ee3402374..3b5194a624 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -781,6 +781,7 @@ function_entry basic_functions[] = {
PHP_FE(array_sum, NULL)
PHP_FE(array_filter, NULL)
PHP_FE(array_map, NULL)
+ PHP_FE(array_chunk, NULL)
PHP_FE(key_exists, NULL)
/* aliases from array.c */
diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h
index 880ce2c74d..0292b2416e 100644
--- a/ext/standard/php_array.h
+++ b/ext/standard/php_array.h
@@ -80,6 +80,7 @@ PHP_FUNCTION(array_sum);
PHP_FUNCTION(array_filter);
PHP_FUNCTION(array_map);
PHP_FUNCTION(key_exists);
+PHP_FUNCTION(array_chunk);
HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **);
PHPAPI void php_array_merge(HashTable *dest, HashTable *src, int recursive);