summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorAndrei Zmievski <andrei@php.net>2000-05-09 19:27:00 +0000
committerAndrei Zmievski <andrei@php.net>2000-05-09 19:27:00 +0000
commitfdbea075fa4c44556249608373f69fd28167861e (patch)
tree302cc822d78e71ce9449187ec9b49f89fb195507 /ext
parent30da5fd8fcfd0446f3b7c3a63fc7319b65d65d62 (diff)
downloadphp-git-fdbea075fa4c44556249608373f69fd28167861e.tar.gz
@- Added array_rand() function. (Andrei)
Diffstat (limited to 'ext')
-rw-r--r--ext/standard/array.c79
-rw-r--r--ext/standard/basic_functions.c1
-rw-r--r--ext/standard/php_array.h1
3 files changed, 81 insertions, 0 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 5dfe37e361..82a6dc448f 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -40,6 +40,7 @@
#include "php_array.h"
#include "basic_functions.h"
#include "php_string.h"
+#include "php_rand.h"
#ifdef ZTS
int array_globals_id;
@@ -2223,6 +2224,84 @@ PHP_FUNCTION(array_multisort)
}
/* }}} */
+
+/* {{{ proto mixed array_rand(array input [, int num_req ])
+ Return key/keys for random entry/entries in the array */
+PHP_FUNCTION(array_rand)
+{
+ zval **input, **num_req;
+ long randval;
+ int num_req_val, num_avail, key_type;
+ char *string_key;
+ ulong num_key;
+
+ if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
+ zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &num_req) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (Z_TYPE_PP(input) != IS_ARRAY) {
+ zend_error(E_WARNING, "Argument to %s() has to be an array",
+ get_active_function_name());
+ return;
+ }
+
+ num_avail = zend_hash_num_elements(Z_ARRVAL_PP(input));
+
+ if (ZEND_NUM_ARGS() > 1) {
+ convert_to_long_ex(num_req);
+ num_req_val = Z_LVAL_PP(num_req);
+ if (num_req_val <= 0 || num_req_val > num_avail) {
+ zend_error(E_WARNING, "Second argument to %s() has to be between 1 and the number of elements in the array", get_active_function_name());
+ return;
+ }
+ } else
+ num_req_val = 1;
+
+ /* Make the return value an array only if we need to pass back more than one
+ result. */
+ if (num_req_val > 1)
+ array_init(return_value);
+
+ /* We can't use zend_hash_index_find() because the array may have string keys or gaps. */
+ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(input));
+ while (num_req_val && (key_type = zend_hash_get_current_key(Z_ARRVAL_PP(input), &string_key, &num_key)) != HASH_KEY_NON_EXISTANT) {
+
+#ifdef HAVE_LRAND48
+ randval = lrand48();
+#else
+#ifdef HAVE_RANDOM
+ randval = random();
+#else
+ randval = rand();
+#endif
+#endif
+
+ if ((double)(randval/(PHP_RAND_MAX+1.0)) < (double)num_req_val/(double)num_avail) {
+ /* If we are returning a single result, just do it. */
+ if (Z_TYPE_P(return_value) != IS_ARRAY) {
+ if (key_type == HASH_KEY_IS_STRING) {
+ RETURN_STRING(string_key, 0);
+ } else {
+ RETURN_LONG(num_key);
+ }
+ } else {
+ /* Append the result to the return value. */
+ if (key_type == HASH_KEY_IS_STRING)
+ add_next_index_string(return_value, string_key, 0);
+ else
+ add_next_index_long(return_value, num_key);
+ }
+ num_req_val--;
+ } else if (key_type == HASH_KEY_IS_STRING)
+ efree(string_key);
+
+ num_avail--;
+ zend_hash_move_forward(Z_ARRVAL_PP(input));
+ }
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 1fa2dab0fd..c4223ce9bd 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -487,6 +487,7 @@ function_entry basic_functions[] = {
PHP_FE(array_reverse, NULL)
PHP_FE(array_pad, NULL)
PHP_FE(array_flip, NULL)
+ PHP_FE(array_rand, NULL)
/* aliases from array.c */
PHP_FALIAS(pos, current, first_arg_force_ref)
PHP_FALIAS(sizeof, count, first_arg_allow_ref)
diff --git a/ext/standard/php_array.h b/ext/standard/php_array.h
index 033953839a..519b4b33af 100644
--- a/ext/standard/php_array.h
+++ b/ext/standard/php_array.h
@@ -67,6 +67,7 @@ PHP_FUNCTION(array_count_values);
PHP_FUNCTION(array_reverse);
PHP_FUNCTION(array_pad);
PHP_FUNCTION(array_flip);
+PHP_FUNCTION(array_rand);
HashTable* _phpi_splice(HashTable *, int, int, zval ***, int, HashTable **);
int multisort_compare(const void *a, const void *b);