diff options
author | Andrei Zmievski <andrei@php.net> | 2000-05-09 19:27:00 +0000 |
---|---|---|
committer | Andrei Zmievski <andrei@php.net> | 2000-05-09 19:27:00 +0000 |
commit | fdbea075fa4c44556249608373f69fd28167861e (patch) | |
tree | 302cc822d78e71ce9449187ec9b49f89fb195507 /ext | |
parent | 30da5fd8fcfd0446f3b7c3a63fc7319b65d65d62 (diff) | |
download | php-git-fdbea075fa4c44556249608373f69fd28167861e.tar.gz |
@- Added array_rand() function. (Andrei)
Diffstat (limited to 'ext')
-rw-r--r-- | ext/standard/array.c | 79 | ||||
-rw-r--r-- | ext/standard/basic_functions.c | 1 | ||||
-rw-r--r-- | ext/standard/php_array.h | 1 |
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); |