mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
random: Pass algorithm and state together as php_random_algo_with_state (#13350)
* random: Remove `php_random_status`
Since 162e1dce98, the `php_random_status` struct
contains just a single `void*`, resulting in needless indirection when
accessing the engine state and thus decreasing readability because of the
additional non-meaningful `->state` references / the local helper variables.
There is also a small, but measurable performance benefit:
<?php
$e = new Random\Engine\Xoshiro256StarStar(0);
$r = new Random\Randomizer($e);
for ($i = 0; $i < 15; $i++)
var_dump(strlen($r->getBytes(100000000)));
goes from roughly 3.85s down to 3.60s.
The names of the `status` variables have not yet been touched to keep the diff
small. They will be renamed to the more appropriate `state` in a follow-up
cleanup commit.
* Introduce `php_random_algo_with_state`
This commit is contained in:
@@ -109,6 +109,13 @@ PHP 8.4 INTERNALS UPGRADE NOTES
|
||||
the new php_random_result struct, replacing the last_generated_size
|
||||
member of the php_random_status struct and the generate_size member of
|
||||
the php_random_algo struct.
|
||||
- The php_random_status struct has been removed, since the previous change
|
||||
reduced it to a single void* member containing the actual state, resulting
|
||||
in needless indirection. Functions taking a php_random_algo struct pointer
|
||||
and a php_random_status struct pointer as separate parameters now take a
|
||||
single php_random_algo_with_state struct by value, making it easier to
|
||||
pass around the state with its associated algorithm and thus reducing
|
||||
the chance for mistakes.
|
||||
- The CSPRNG API (php_random_(bytes|int)_*) is now provided by the new
|
||||
and much smaller php_random_csprng.h header. The new header is included
|
||||
in php_random.h for compatibility with existing users.
|
||||
|
||||
@@ -32,17 +32,17 @@
|
||||
*/
|
||||
#define MODMULT(a, b, c, m, s) q = s / a; s = b * (s - a * q) - c * q; if (s < 0) s += m
|
||||
|
||||
static void seed(php_random_status *status, uint64_t seed)
|
||||
static void seed(void *status, uint64_t seed)
|
||||
{
|
||||
php_random_status_state_combinedlcg *s = status->state;
|
||||
php_random_status_state_combinedlcg *s = status;
|
||||
|
||||
s->state[0] = seed & 0xffffffffU;
|
||||
s->state[1] = seed >> 32;
|
||||
}
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
php_random_status_state_combinedlcg *s = status->state;
|
||||
php_random_status_state_combinedlcg *s = status;
|
||||
int32_t q, z;
|
||||
|
||||
MODMULT(53668, 40014, 12211, 2147483563L, s->state[0]);
|
||||
@@ -59,14 +59,17 @@ static php_random_result generate(php_random_status *status)
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
return php_random_range(&php_random_algo_combinedlcg, status, min, max);
|
||||
return php_random_range((php_random_algo_with_state){
|
||||
.algo = &php_random_algo_combinedlcg,
|
||||
.status = status,
|
||||
}, min, max);
|
||||
}
|
||||
|
||||
static bool serialize(php_random_status *status, HashTable *data)
|
||||
static bool serialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_combinedlcg *s = status->state;
|
||||
php_random_status_state_combinedlcg *s = status;
|
||||
zval t;
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
@@ -77,9 +80,9 @@ static bool serialize(php_random_status *status, HashTable *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unserialize(php_random_status *status, HashTable *data)
|
||||
static bool unserialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_combinedlcg *s = status->state;
|
||||
php_random_status_state_combinedlcg *s = status;
|
||||
zval *t;
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
|
||||
@@ -139,14 +139,14 @@ static inline void mt19937_seed_state(php_random_status_state_mt19937 *state, ui
|
||||
mt19937_reload(state);
|
||||
}
|
||||
|
||||
static void seed(php_random_status *status, uint64_t seed)
|
||||
static void seed(void *status, uint64_t seed)
|
||||
{
|
||||
mt19937_seed_state(status->state, seed);
|
||||
mt19937_seed_state(status, seed);
|
||||
}
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
php_random_status_state_mt19937 *s = status->state;
|
||||
php_random_status_state_mt19937 *s = status;
|
||||
uint32_t s1;
|
||||
|
||||
if (s->count >= MT_N) {
|
||||
@@ -164,14 +164,17 @@ static php_random_result generate(php_random_status *status)
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
return php_random_range(&php_random_algo_mt19937, status, min, max);
|
||||
return php_random_range((php_random_algo_with_state){
|
||||
.algo = &php_random_algo_mt19937,
|
||||
.status = status,
|
||||
}, min, max);
|
||||
}
|
||||
|
||||
static bool serialize(php_random_status *status, HashTable *data)
|
||||
static bool serialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_mt19937 *s = status->state;
|
||||
php_random_status_state_mt19937 *s = status;
|
||||
zval t;
|
||||
|
||||
for (uint32_t i = 0; i < MT_N; i++) {
|
||||
@@ -186,9 +189,9 @@ static bool serialize(php_random_status *status, HashTable *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unserialize(php_random_status *status, HashTable *data)
|
||||
static bool unserialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_mt19937 *s = status->state;
|
||||
php_random_status_state_mt19937 *s = status;
|
||||
zval *t;
|
||||
|
||||
/* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
|
||||
@@ -251,8 +254,8 @@ PHPAPI void php_random_mt19937_seed_default(php_random_status_state_mt19937 *sta
|
||||
/* {{{ Random\Engine\Mt19937::__construct() */
|
||||
PHP_METHOD(Random_Engine_Mt19937, __construct)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_mt19937 *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_mt19937 *state = engine.status;
|
||||
zend_long seed, mode = MT_RAND_MT19937;
|
||||
bool seed_is_null = true;
|
||||
|
||||
@@ -290,12 +293,12 @@ PHP_METHOD(Random_Engine_Mt19937, __construct)
|
||||
/* {{{ Random\Engine\Mt19937::generate() */
|
||||
PHP_METHOD(Random_Engine_Mt19937, generate)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
zend_string *bytes;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
php_random_result generated = engine->algo->generate(engine->status);
|
||||
php_random_result generated = engine.algo->generate(engine.status);
|
||||
if (EG(exception)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -329,7 +332,7 @@ PHP_METHOD(Random_Engine_Mt19937, __serialize)
|
||||
|
||||
/* state */
|
||||
array_init(&t);
|
||||
if (!engine->algo->serialize(engine->status, Z_ARRVAL(t))) {
|
||||
if (!engine->engine.algo->serialize(engine->engine.status, Z_ARRVAL(t))) {
|
||||
zend_throw_exception(NULL, "Engine serialize failed", 0);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -372,7 +375,7 @@ PHP_METHOD(Random_Engine_Mt19937, __unserialize)
|
||||
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(engine->std.ce->name));
|
||||
RETURN_THROWS();
|
||||
}
|
||||
if (!engine->algo->unserialize(engine->status, Z_ARRVAL_P(t))) {
|
||||
if (!engine->engine.algo->unserialize(engine->engine.status, Z_ARRVAL_P(t))) {
|
||||
zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(engine->std.ce->name));
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -392,9 +395,9 @@ PHP_METHOD(Random_Engine_Mt19937, __debugInfo)
|
||||
}
|
||||
ZVAL_ARR(return_value, zend_array_dup(engine->std.properties));
|
||||
|
||||
if (engine->algo->serialize) {
|
||||
if (engine->engine.algo->serialize) {
|
||||
array_init(&t);
|
||||
if (!engine->algo->serialize(engine->status, Z_ARRVAL(t))) {
|
||||
if (!engine->engine.algo->serialize(engine->engine.status, Z_ARRVAL(t))) {
|
||||
zend_throw_exception(NULL, "Engine serialize failed", 0);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -43,14 +43,14 @@ static inline void seed128(php_random_status_state_pcgoneseq128xslrr64 *s, php_r
|
||||
step(s);
|
||||
}
|
||||
|
||||
static void seed(php_random_status *status, uint64_t seed)
|
||||
static void seed(void *status, uint64_t seed)
|
||||
{
|
||||
seed128(status->state, php_random_uint128_constant(0ULL, seed));
|
||||
seed128(status, php_random_uint128_constant(0ULL, seed));
|
||||
}
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status->state;
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status;
|
||||
|
||||
step(s);
|
||||
|
||||
@@ -60,14 +60,17 @@ static php_random_result generate(php_random_status *status)
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
return php_random_range(&php_random_algo_pcgoneseq128xslrr64, status, min, max);
|
||||
return php_random_range((php_random_algo_with_state){
|
||||
.algo = &php_random_algo_pcgoneseq128xslrr64,
|
||||
.status = status,
|
||||
}, min, max);
|
||||
}
|
||||
|
||||
static bool serialize(php_random_status *status, HashTable *data)
|
||||
static bool serialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status->state;
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status;
|
||||
uint64_t u;
|
||||
zval z;
|
||||
|
||||
@@ -82,9 +85,9 @@ static bool serialize(php_random_status *status, HashTable *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unserialize(php_random_status *status, HashTable *data)
|
||||
static bool unserialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status->state;
|
||||
php_random_status_state_pcgoneseq128xslrr64 *s = status;
|
||||
uint64_t u[2];
|
||||
zval *t;
|
||||
|
||||
@@ -142,8 +145,8 @@ PHPAPI void php_random_pcgoneseq128xslrr64_advance(php_random_status_state_pcgon
|
||||
/* {{{ Random\Engine\PcgOneseq128XslRr64::__construct */
|
||||
PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_pcgoneseq128xslrr64 *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_pcgoneseq128xslrr64 *state = engine.status;
|
||||
zend_string *str_seed = NULL;
|
||||
zend_long int_seed = 0;
|
||||
bool seed_is_null = true;
|
||||
@@ -191,8 +194,8 @@ PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, __construct)
|
||||
/* {{{ Random\Engine\PcgOneseq128XslRr64::jump() */
|
||||
PHP_METHOD(Random_Engine_PcgOneseq128XslRr64, jump)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_pcgoneseq128xslrr64 *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_pcgoneseq128xslrr64 *state = engine.status;
|
||||
zend_long advance = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "Zend/zend_exceptions.h"
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
zend_ulong r = 0;
|
||||
|
||||
@@ -37,7 +37,7 @@ static php_random_result generate(php_random_status *status)
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
zend_long result = 0;
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#include "php.h"
|
||||
#include "php_random.h"
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
php_random_status_state_user *s = status->state;
|
||||
php_random_status_state_user *s = status;
|
||||
uint64_t result = 0;
|
||||
size_t size;
|
||||
zval retval;
|
||||
@@ -65,9 +65,12 @@ static php_random_result generate(php_random_status *status)
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
return php_random_range(&php_random_algo_user, status, min, max);
|
||||
return php_random_range((php_random_algo_with_state){
|
||||
.algo = &php_random_algo_user,
|
||||
.status = status,
|
||||
}, min, max);
|
||||
}
|
||||
|
||||
const php_random_algo php_random_algo_user = {
|
||||
|
||||
@@ -102,27 +102,30 @@ static inline void seed64(php_random_status_state_xoshiro256starstar *state, uin
|
||||
seed256(state, s[0], s[1], s[2], s[3]);
|
||||
}
|
||||
|
||||
static void seed(php_random_status *status, uint64_t seed)
|
||||
static void seed(void *status, uint64_t seed)
|
||||
{
|
||||
seed64(status->state, seed);
|
||||
seed64(status, seed);
|
||||
}
|
||||
|
||||
static php_random_result generate(php_random_status *status)
|
||||
static php_random_result generate(void *status)
|
||||
{
|
||||
return (php_random_result){
|
||||
.size = sizeof(uint64_t),
|
||||
.result = generate_state(status->state),
|
||||
.result = generate_state(status),
|
||||
};
|
||||
}
|
||||
|
||||
static zend_long range(php_random_status *status, zend_long min, zend_long max)
|
||||
static zend_long range(void *status, zend_long min, zend_long max)
|
||||
{
|
||||
return php_random_range(&php_random_algo_xoshiro256starstar, status, min, max);
|
||||
return php_random_range((php_random_algo_with_state){
|
||||
.algo = &php_random_algo_xoshiro256starstar,
|
||||
.status = status,
|
||||
}, min, max);
|
||||
}
|
||||
|
||||
static bool serialize(php_random_status *status, HashTable *data)
|
||||
static bool serialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_xoshiro256starstar *s = status->state;
|
||||
php_random_status_state_xoshiro256starstar *s = status;
|
||||
zval t;
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
@@ -133,9 +136,9 @@ static bool serialize(php_random_status *status, HashTable *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unserialize(php_random_status *status, HashTable *data)
|
||||
static bool unserialize(void *status, HashTable *data)
|
||||
{
|
||||
php_random_status_state_xoshiro256starstar *s = status->state;
|
||||
php_random_status_state_xoshiro256starstar *s = status;
|
||||
zval *t;
|
||||
|
||||
/* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
|
||||
@@ -180,8 +183,8 @@ PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xosh
|
||||
/* {{{ Random\Engine\Xoshiro256StarStar::jump() */
|
||||
PHP_METHOD(Random_Engine_Xoshiro256StarStar, jump)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_xoshiro256starstar *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_xoshiro256starstar *state = engine.status;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
@@ -192,8 +195,8 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, jump)
|
||||
/* {{{ Random\Engine\Xoshiro256StarStar::jumpLong() */
|
||||
PHP_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_xoshiro256starstar *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_xoshiro256starstar *state = engine.status;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
@@ -204,8 +207,8 @@ PHP_METHOD(Random_Engine_Xoshiro256StarStar, jumpLong)
|
||||
/* {{{ Random\Engine\Xoshiro256StarStar::__construct */
|
||||
PHP_METHOD(Random_Engine_Xoshiro256StarStar, __construct)
|
||||
{
|
||||
php_random_engine *engine = Z_RANDOM_ENGINE_P(ZEND_THIS);
|
||||
php_random_status_state_xoshiro256starstar *state = engine->status->state;
|
||||
php_random_algo_with_state engine = Z_RANDOM_ENGINE_P(ZEND_THIS)->engine;
|
||||
php_random_status_state_xoshiro256starstar *state = engine.status;
|
||||
zend_string *str_seed = NULL;
|
||||
zend_long int_seed = 0;
|
||||
bool seed_is_null = true;
|
||||
|
||||
@@ -71,7 +71,7 @@ static uint64_t ceilint(double a, double b, double g)
|
||||
return (s != si) ? (uint64_t)si : (uint64_t)si + (e > 0);
|
||||
}
|
||||
|
||||
PHPAPI double php_random_gammasection_closed_open(const php_random_algo *algo, php_random_status *status, double min, double max)
|
||||
PHPAPI double php_random_gammasection_closed_open(php_random_algo_with_state engine, double min, double max)
|
||||
{
|
||||
double g = gamma_max(min, max);
|
||||
uint64_t hi = ceilint(min, max, g);
|
||||
@@ -80,7 +80,7 @@ PHPAPI double php_random_gammasection_closed_open(const php_random_algo *algo, p
|
||||
return NAN;
|
||||
}
|
||||
|
||||
uint64_t k = 1 + php_random_range64(algo, status, hi - 1); /* [1, hi] */
|
||||
uint64_t k = 1 + php_random_range64(engine, hi - 1); /* [1, hi] */
|
||||
|
||||
if (fabs(min) <= fabs(max)) {
|
||||
if (k == hi) {
|
||||
@@ -99,7 +99,7 @@ PHPAPI double php_random_gammasection_closed_open(const php_random_algo *algo, p
|
||||
}
|
||||
}
|
||||
|
||||
PHPAPI double php_random_gammasection_closed_closed(const php_random_algo *algo, php_random_status *status, double min, double max)
|
||||
PHPAPI double php_random_gammasection_closed_closed(php_random_algo_with_state engine, double min, double max)
|
||||
{
|
||||
double g = gamma_max(min, max);
|
||||
uint64_t hi = ceilint(min, max, g);
|
||||
@@ -108,7 +108,7 @@ PHPAPI double php_random_gammasection_closed_closed(const php_random_algo *algo,
|
||||
return NAN;
|
||||
}
|
||||
|
||||
uint64_t k = php_random_range64(algo, status, hi); /* [0, hi] */
|
||||
uint64_t k = php_random_range64(engine, hi); /* [0, hi] */
|
||||
|
||||
if (fabs(min) <= fabs(max)) {
|
||||
if (k == hi) {
|
||||
@@ -131,7 +131,7 @@ PHPAPI double php_random_gammasection_closed_closed(const php_random_algo *algo,
|
||||
}
|
||||
}
|
||||
|
||||
PHPAPI double php_random_gammasection_open_closed(const php_random_algo *algo, php_random_status *status, double min, double max)
|
||||
PHPAPI double php_random_gammasection_open_closed(php_random_algo_with_state engine, double min, double max)
|
||||
{
|
||||
double g = gamma_max(min, max);
|
||||
uint64_t hi = ceilint(min, max, g);
|
||||
@@ -140,7 +140,7 @@ PHPAPI double php_random_gammasection_open_closed(const php_random_algo *algo, p
|
||||
return NAN;
|
||||
}
|
||||
|
||||
uint64_t k = php_random_range64(algo, status, hi - 1); /* [0, hi - 1] */
|
||||
uint64_t k = php_random_range64(engine, hi - 1); /* [0, hi - 1] */
|
||||
|
||||
if (fabs(min) <= fabs(max)) {
|
||||
double k_hi, k_lo;
|
||||
@@ -159,7 +159,7 @@ PHPAPI double php_random_gammasection_open_closed(const php_random_algo *algo, p
|
||||
}
|
||||
}
|
||||
|
||||
PHPAPI double php_random_gammasection_open_open(const php_random_algo *algo, php_random_status *status, double min, double max)
|
||||
PHPAPI double php_random_gammasection_open_open(php_random_algo_with_state engine, double min, double max)
|
||||
{
|
||||
double g = gamma_max(min, max);
|
||||
uint64_t hi = ceilint(min, max, g);
|
||||
@@ -168,7 +168,7 @@ PHPAPI double php_random_gammasection_open_open(const php_random_algo *algo, php
|
||||
return NAN;
|
||||
}
|
||||
|
||||
uint64_t k = 1 + php_random_range64(algo, status, hi - 2); /* [1, hi - 1] */
|
||||
uint64_t k = 1 + php_random_range64(engine, hi - 2); /* [1, hi - 1] */
|
||||
|
||||
if (fabs(min) <= fabs(max)) {
|
||||
double k_hi, k_lo;
|
||||
|
||||
@@ -66,10 +66,6 @@ PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max);
|
||||
PHPAPI void php_srand(zend_long seed);
|
||||
PHPAPI zend_long php_rand(void);
|
||||
|
||||
typedef struct _php_random_status_ {
|
||||
void *state;
|
||||
} php_random_status;
|
||||
|
||||
typedef struct _php_random_status_state_combinedlcg {
|
||||
int32_t state[2];
|
||||
} php_random_status_state_combinedlcg;
|
||||
@@ -100,13 +96,18 @@ typedef struct _php_random_result {
|
||||
|
||||
typedef struct _php_random_algo {
|
||||
const size_t state_size;
|
||||
void (*seed)(php_random_status *status, uint64_t seed);
|
||||
php_random_result (*generate)(php_random_status *status);
|
||||
zend_long (*range)(php_random_status *status, zend_long min, zend_long max);
|
||||
bool (*serialize)(php_random_status *status, HashTable *data);
|
||||
bool (*unserialize)(php_random_status *status, HashTable *data);
|
||||
void (*seed)(void *status, uint64_t seed);
|
||||
php_random_result (*generate)(void *status);
|
||||
zend_long (*range)(void *status, zend_long min, zend_long max);
|
||||
bool (*serialize)(void *status, HashTable *data);
|
||||
bool (*unserialize)(void *status, HashTable *data);
|
||||
} php_random_algo;
|
||||
|
||||
typedef struct _php_random_algo_with_state {
|
||||
const php_random_algo *algo;
|
||||
void *status;
|
||||
} php_random_algo_with_state;
|
||||
|
||||
extern PHPAPI const php_random_algo php_random_algo_combinedlcg;
|
||||
extern PHPAPI const php_random_algo php_random_algo_mt19937;
|
||||
extern PHPAPI const php_random_algo php_random_algo_pcgoneseq128xslrr64;
|
||||
@@ -115,14 +116,12 @@ extern PHPAPI const php_random_algo php_random_algo_secure;
|
||||
extern PHPAPI const php_random_algo php_random_algo_user;
|
||||
|
||||
typedef struct _php_random_engine {
|
||||
const php_random_algo *algo;
|
||||
php_random_status *status;
|
||||
php_random_algo_with_state engine;
|
||||
zend_object std;
|
||||
} php_random_engine;
|
||||
|
||||
typedef struct _php_random_randomizer {
|
||||
const php_random_algo *algo;
|
||||
php_random_status *status;
|
||||
php_random_algo_with_state engine;
|
||||
bool is_userland_algo;
|
||||
zend_object std;
|
||||
} php_random_randomizer;
|
||||
@@ -155,17 +154,25 @@ static inline php_random_randomizer *php_random_randomizer_from_obj(zend_object
|
||||
|
||||
# define Z_RANDOM_RANDOMIZER_P(zval) php_random_randomizer_from_obj(Z_OBJ_P(zval));
|
||||
|
||||
PHPAPI php_random_status *php_random_status_alloc(const php_random_algo *algo, const bool persistent);
|
||||
PHPAPI php_random_status *php_random_status_copy(const php_random_algo *algo, php_random_status *old_status, php_random_status *new_status);
|
||||
PHPAPI void php_random_status_free(php_random_status *status, const bool persistent);
|
||||
PHPAPI void *php_random_status_alloc(const php_random_algo *algo, const bool persistent);
|
||||
PHPAPI void *php_random_status_copy(const php_random_algo *algo, void *old_status, void *new_status);
|
||||
PHPAPI void php_random_status_free(void *status, const bool persistent);
|
||||
PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, zend_object_handlers *handlers, const php_random_algo *algo);
|
||||
PHPAPI void php_random_engine_common_free_object(zend_object *object);
|
||||
PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object);
|
||||
PHPAPI uint32_t php_random_range32(const php_random_algo *algo, php_random_status *status, uint32_t umax);
|
||||
PHPAPI uint64_t php_random_range64(const php_random_algo *algo, php_random_status *status, uint64_t umax);
|
||||
PHPAPI zend_long php_random_range(const php_random_algo *algo, php_random_status *status, zend_long min, zend_long max);
|
||||
PHPAPI uint32_t php_random_range32(php_random_algo_with_state engine, uint32_t umax);
|
||||
PHPAPI uint64_t php_random_range64(php_random_algo_with_state engine, uint64_t umax);
|
||||
PHPAPI zend_long php_random_range(php_random_algo_with_state engine, zend_long min, zend_long max);
|
||||
PHPAPI const php_random_algo *php_random_default_algo(void);
|
||||
PHPAPI php_random_status *php_random_default_status(void);
|
||||
PHPAPI void *php_random_default_status(void);
|
||||
|
||||
static inline php_random_algo_with_state php_random_default_engine(void)
|
||||
{
|
||||
return (php_random_algo_with_state){
|
||||
.algo = php_random_default_algo(),
|
||||
.status = php_random_default_status(),
|
||||
};
|
||||
}
|
||||
|
||||
PHPAPI zend_string *php_random_bin2hex_le(const void *ptr, const size_t len);
|
||||
PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest);
|
||||
@@ -179,10 +186,10 @@ PHPAPI void php_random_pcgoneseq128xslrr64_advance(php_random_status_state_pcgon
|
||||
PHPAPI void php_random_xoshiro256starstar_jump(php_random_status_state_xoshiro256starstar *state);
|
||||
PHPAPI void php_random_xoshiro256starstar_jump_long(php_random_status_state_xoshiro256starstar *state);
|
||||
|
||||
PHPAPI double php_random_gammasection_closed_open(const php_random_algo *algo, php_random_status *status, double min, double max);
|
||||
PHPAPI double php_random_gammasection_closed_closed(const php_random_algo *algo, php_random_status *status, double min, double max);
|
||||
PHPAPI double php_random_gammasection_open_closed(const php_random_algo *algo, php_random_status *status, double min, double max);
|
||||
PHPAPI double php_random_gammasection_open_open(const php_random_algo *algo, php_random_status *status, double min, double max);
|
||||
PHPAPI double php_random_gammasection_closed_open(php_random_algo_with_state engine, double min, double max);
|
||||
PHPAPI double php_random_gammasection_closed_closed(php_random_algo_with_state engine, double min, double max);
|
||||
PHPAPI double php_random_gammasection_open_closed(php_random_algo_with_state engine, double min, double max);
|
||||
PHPAPI double php_random_gammasection_open_open(php_random_algo_with_state engine, double min, double max);
|
||||
|
||||
extern zend_module_entry random_module_entry;
|
||||
# define phpext_random_ptr &random_module_entry
|
||||
@@ -192,9 +199,9 @@ PHP_MSHUTDOWN_FUNCTION(random);
|
||||
PHP_RINIT_FUNCTION(random);
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(random)
|
||||
php_random_status *combined_lcg;
|
||||
php_random_status_state_combinedlcg *combined_lcg;
|
||||
bool combined_lcg_seeded;
|
||||
php_random_status *mt19937;
|
||||
php_random_status_state_mt19937 *mt19937;
|
||||
bool mt19937_seeded;
|
||||
int random_fd;
|
||||
ZEND_END_MODULE_GLOBALS(random)
|
||||
|
||||
@@ -74,8 +74,11 @@ static zend_object_handlers random_engine_xoshiro256starstar_object_handlers;
|
||||
static zend_object_handlers random_engine_secure_object_handlers;
|
||||
static zend_object_handlers random_randomizer_object_handlers;
|
||||
|
||||
PHPAPI uint32_t php_random_range32(const php_random_algo *algo, php_random_status *status, uint32_t umax)
|
||||
PHPAPI uint32_t php_random_range32(php_random_algo_with_state engine, uint32_t umax)
|
||||
{
|
||||
const php_random_algo *algo = engine.algo;
|
||||
void *status = engine.status;
|
||||
|
||||
uint32_t result, limit;
|
||||
size_t total_size = 0;
|
||||
uint32_t count = 0;
|
||||
@@ -130,8 +133,11 @@ PHPAPI uint32_t php_random_range32(const php_random_algo *algo, php_random_statu
|
||||
return result % umax;
|
||||
}
|
||||
|
||||
PHPAPI uint64_t php_random_range64(const php_random_algo *algo, php_random_status *status, uint64_t umax)
|
||||
PHPAPI uint64_t php_random_range64(php_random_algo_with_state engine, uint64_t umax)
|
||||
{
|
||||
const php_random_algo *algo = engine.algo;
|
||||
void *status = engine.status;
|
||||
|
||||
uint64_t result, limit;
|
||||
size_t total_size = 0;
|
||||
uint32_t count = 0;
|
||||
@@ -220,34 +226,24 @@ static void randomizer_free_obj(zend_object *object) {
|
||||
php_random_randomizer *randomizer = php_random_randomizer_from_obj(object);
|
||||
|
||||
if (randomizer->is_userland_algo) {
|
||||
php_random_status_free(randomizer->status, false);
|
||||
php_random_status_free(randomizer->engine.status, false);
|
||||
}
|
||||
|
||||
zend_object_std_dtor(&randomizer->std);
|
||||
}
|
||||
|
||||
PHPAPI php_random_status *php_random_status_alloc(const php_random_algo *algo, const bool persistent)
|
||||
PHPAPI void *php_random_status_alloc(const php_random_algo *algo, const bool persistent)
|
||||
{
|
||||
php_random_status *status = pecalloc(1, sizeof(php_random_status), persistent);
|
||||
|
||||
status->state = algo->state_size > 0 ? pecalloc(1, algo->state_size, persistent) : NULL;
|
||||
|
||||
return status;
|
||||
return algo->state_size > 0 ? pecalloc(1, algo->state_size, persistent) : NULL;
|
||||
}
|
||||
|
||||
PHPAPI php_random_status *php_random_status_copy(const php_random_algo *algo, php_random_status *old_status, php_random_status *new_status)
|
||||
PHPAPI void *php_random_status_copy(const php_random_algo *algo, void *old_status, void *new_status)
|
||||
{
|
||||
new_status->state = memcpy(new_status->state, old_status->state, algo->state_size);
|
||||
|
||||
return new_status;
|
||||
return memcpy(new_status, old_status, algo->state_size);
|
||||
}
|
||||
|
||||
PHPAPI void php_random_status_free(php_random_status *status, const bool persistent)
|
||||
PHPAPI void php_random_status_free(void *status, const bool persistent)
|
||||
{
|
||||
if (status != NULL) {
|
||||
pefree(status->state, persistent);
|
||||
}
|
||||
|
||||
pefree(status, persistent);
|
||||
}
|
||||
|
||||
@@ -258,8 +254,10 @@ PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, ze
|
||||
zend_object_std_init(&engine->std, ce);
|
||||
object_properties_init(&engine->std, ce);
|
||||
|
||||
engine->algo = algo;
|
||||
engine->status = php_random_status_alloc(engine->algo, false);
|
||||
engine->engine = (php_random_algo_with_state){
|
||||
.algo = algo,
|
||||
.status = php_random_status_alloc(algo, false)
|
||||
};
|
||||
engine->std.handlers = handlers;
|
||||
|
||||
return engine;
|
||||
@@ -269,7 +267,7 @@ PHPAPI void php_random_engine_common_free_object(zend_object *object)
|
||||
{
|
||||
php_random_engine *engine = php_random_engine_from_obj(object);
|
||||
|
||||
php_random_status_free(engine->status, false);
|
||||
php_random_status_free(engine->engine.status, false);
|
||||
zend_object_std_dtor(object);
|
||||
}
|
||||
|
||||
@@ -278,9 +276,9 @@ PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object)
|
||||
php_random_engine *old_engine = php_random_engine_from_obj(object);
|
||||
php_random_engine *new_engine = php_random_engine_from_obj(old_engine->std.ce->create_object(old_engine->std.ce));
|
||||
|
||||
new_engine->algo = old_engine->algo;
|
||||
if (old_engine->status) {
|
||||
new_engine->status = php_random_status_copy(old_engine->algo, old_engine->status, new_engine->status);
|
||||
new_engine->engine.algo = old_engine->engine.algo;
|
||||
if (old_engine->engine.status) {
|
||||
new_engine->engine.status = php_random_status_copy(old_engine->engine.algo, old_engine->engine.status, new_engine->engine.status);
|
||||
}
|
||||
|
||||
zend_objects_clone_members(&new_engine->std, &old_engine->std);
|
||||
@@ -289,15 +287,15 @@ PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object)
|
||||
}
|
||||
|
||||
/* {{{ php_random_range */
|
||||
PHPAPI zend_long php_random_range(const php_random_algo *algo, php_random_status *status, zend_long min, zend_long max)
|
||||
PHPAPI zend_long php_random_range(php_random_algo_with_state engine, zend_long min, zend_long max)
|
||||
{
|
||||
zend_ulong umax = (zend_ulong) max - (zend_ulong) min;
|
||||
|
||||
if (umax > UINT32_MAX) {
|
||||
return (zend_long) (php_random_range64(algo, status, umax) + min);
|
||||
return (zend_long) (php_random_range64(engine, umax) + min);
|
||||
}
|
||||
|
||||
return (zend_long) (php_random_range32(algo, status, umax) + min);
|
||||
return (zend_long) (php_random_range32(engine, umax) + min);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -309,12 +307,12 @@ PHPAPI const php_random_algo *php_random_default_algo(void)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_random_default_status */
|
||||
PHPAPI php_random_status *php_random_default_status(void)
|
||||
PHPAPI void *php_random_default_status(void)
|
||||
{
|
||||
php_random_status *status = RANDOM_G(mt19937);
|
||||
php_random_status_state_mt19937 *status = RANDOM_G(mt19937);
|
||||
|
||||
if (!RANDOM_G(mt19937_seeded)) {
|
||||
php_random_mt19937_seed_default(status->state);
|
||||
php_random_mt19937_seed_default(status);
|
||||
RANDOM_G(mt19937_seeded) = true;
|
||||
}
|
||||
|
||||
@@ -392,10 +390,10 @@ PHPAPI bool php_random_hex2bin_le(zend_string *hexstr, void *dest)
|
||||
/* {{{ php_combined_lcg */
|
||||
PHPAPI double php_combined_lcg(void)
|
||||
{
|
||||
php_random_status *status = RANDOM_G(combined_lcg);
|
||||
php_random_status_state_combinedlcg *status = RANDOM_G(combined_lcg);
|
||||
|
||||
if (!RANDOM_G(combined_lcg_seeded)) {
|
||||
php_random_combinedlcg_seed_default(status->state);
|
||||
php_random_combinedlcg_seed_default(status);
|
||||
RANDOM_G(combined_lcg_seeded) = true;
|
||||
}
|
||||
|
||||
@@ -429,8 +427,7 @@ PHPAPI zend_long php_mt_rand_range(zend_long min, zend_long max)
|
||||
* rand() allows min > max, mt_rand does not */
|
||||
PHPAPI zend_long php_mt_rand_common(zend_long min, zend_long max)
|
||||
{
|
||||
php_random_status *status = php_random_default_status();
|
||||
php_random_status_state_mt19937 *s = status->state;
|
||||
php_random_status_state_mt19937 *s = php_random_default_status();
|
||||
|
||||
if (s->mode == MT_RAND_MT19937) {
|
||||
return php_mt_rand_range(min, max);
|
||||
@@ -476,8 +473,7 @@ PHP_FUNCTION(mt_srand)
|
||||
zend_long seed = 0;
|
||||
bool seed_is_null = true;
|
||||
zend_long mode = MT_RAND_MT19937;
|
||||
php_random_status *status = RANDOM_G(mt19937);
|
||||
php_random_status_state_mt19937 *state = status->state;
|
||||
php_random_status_state_mt19937 *state = RANDOM_G(mt19937);
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, 2)
|
||||
Z_PARAM_OPTIONAL
|
||||
@@ -493,9 +489,9 @@ PHP_FUNCTION(mt_srand)
|
||||
}
|
||||
|
||||
if (seed_is_null) {
|
||||
php_random_mt19937_seed_default(status->state);
|
||||
php_random_mt19937_seed_default(state);
|
||||
} else {
|
||||
php_random_algo_mt19937.seed(status, (uint64_t) seed);
|
||||
php_random_algo_mt19937.seed(state, (uint64_t) seed);
|
||||
}
|
||||
RANDOM_G(mt19937_seeded) = true;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,15 @@ static inline void randomizer_common_init(php_random_randomizer *randomizer, zen
|
||||
php_random_engine *engine = php_random_engine_from_obj(engine_object);
|
||||
|
||||
/* Copy engine pointers */
|
||||
randomizer->algo = engine->algo;
|
||||
randomizer->status = engine->status;
|
||||
randomizer->engine = engine->engine;
|
||||
} else {
|
||||
/* Self allocation */
|
||||
randomizer->status = php_random_status_alloc(&php_random_algo_user, false);
|
||||
php_random_status_state_user *state = randomizer->status->state;
|
||||
php_random_status_state_user *state = php_random_status_alloc(&php_random_algo_user, false);
|
||||
randomizer->engine = (php_random_algo_with_state){
|
||||
.algo = &php_random_algo_user,
|
||||
.status = state,
|
||||
};
|
||||
|
||||
zend_string *mname;
|
||||
zend_function *generate_method;
|
||||
|
||||
@@ -50,9 +53,6 @@ static inline void randomizer_common_init(php_random_randomizer *randomizer, zen
|
||||
state->object = engine_object;
|
||||
state->generate_method = generate_method;
|
||||
|
||||
/* Copy common pointers */
|
||||
randomizer->algo = &php_random_algo_user;
|
||||
|
||||
/* Mark self-allocated for memory management */
|
||||
randomizer->is_userland_algo = true;
|
||||
}
|
||||
@@ -93,6 +93,8 @@ PHP_METHOD(Random_Randomizer, __construct)
|
||||
PHP_METHOD(Random_Randomizer, nextFloat)
|
||||
{
|
||||
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = randomizer->engine;
|
||||
|
||||
uint64_t result;
|
||||
size_t total_size;
|
||||
|
||||
@@ -101,7 +103,7 @@ PHP_METHOD(Random_Randomizer, nextFloat)
|
||||
result = 0;
|
||||
total_size = 0;
|
||||
do {
|
||||
php_random_result r = randomizer->algo->generate(randomizer->status);
|
||||
php_random_result r = engine.algo->generate(engine.status);
|
||||
result = result | (r.result << (total_size * 8));
|
||||
total_size += r.size;
|
||||
if (EG(exception)) {
|
||||
@@ -169,28 +171,28 @@ PHP_METHOD(Random_Randomizer, getFloat)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETURN_DOUBLE(php_random_gammasection_closed_open(randomizer->algo, randomizer->status, min, max));
|
||||
RETURN_DOUBLE(php_random_gammasection_closed_open(randomizer->engine, min, max));
|
||||
case 'C' + sizeof("ClosedClosed") - 1:
|
||||
if (UNEXPECTED(max < min)) {
|
||||
zend_argument_value_error(2, "must be greater than or equal to argument #1 ($min)");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETURN_DOUBLE(php_random_gammasection_closed_closed(randomizer->algo, randomizer->status, min, max));
|
||||
RETURN_DOUBLE(php_random_gammasection_closed_closed(randomizer->engine, min, max));
|
||||
case 'O' + sizeof("OpenClosed") - 1:
|
||||
if (UNEXPECTED(max <= min)) {
|
||||
zend_argument_value_error(2, "must be greater than argument #1 ($min)");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETURN_DOUBLE(php_random_gammasection_open_closed(randomizer->algo, randomizer->status, min, max));
|
||||
RETURN_DOUBLE(php_random_gammasection_open_closed(randomizer->engine, min, max));
|
||||
case 'O' + sizeof("OpenOpen") - 1:
|
||||
if (UNEXPECTED(max <= min)) {
|
||||
zend_argument_value_error(2, "must be greater than argument #1 ($min)");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETVAL_DOUBLE(php_random_gammasection_open_open(randomizer->algo, randomizer->status, min, max));
|
||||
RETVAL_DOUBLE(php_random_gammasection_open_open(randomizer->engine, min, max));
|
||||
|
||||
if (UNEXPECTED(isnan(Z_DVAL_P(return_value)))) {
|
||||
zend_value_error("The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max).");
|
||||
@@ -208,10 +210,11 @@ PHP_METHOD(Random_Randomizer, getFloat)
|
||||
PHP_METHOD(Random_Randomizer, nextInt)
|
||||
{
|
||||
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = randomizer->engine;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
php_random_result result = randomizer->algo->generate(randomizer->status);
|
||||
php_random_result result = engine.algo->generate(engine.status);
|
||||
if (EG(exception)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -228,6 +231,8 @@ PHP_METHOD(Random_Randomizer, nextInt)
|
||||
PHP_METHOD(Random_Randomizer, getInt)
|
||||
{
|
||||
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = randomizer->engine;
|
||||
|
||||
uint64_t result;
|
||||
zend_long min, max;
|
||||
|
||||
@@ -242,10 +247,10 @@ PHP_METHOD(Random_Randomizer, getInt)
|
||||
}
|
||||
|
||||
if (UNEXPECTED(
|
||||
randomizer->algo->range == php_random_algo_mt19937.range
|
||||
&& ((php_random_status_state_mt19937 *) randomizer->status->state)->mode != MT_RAND_MT19937
|
||||
engine.algo->range == php_random_algo_mt19937.range
|
||||
&& ((php_random_status_state_mt19937 *) engine.status)->mode != MT_RAND_MT19937
|
||||
)) {
|
||||
uint64_t r = php_random_algo_mt19937.generate(randomizer->status).result >> 1;
|
||||
uint64_t r = php_random_algo_mt19937.generate(engine.status).result >> 1;
|
||||
|
||||
/* This is an inlined version of the RAND_RANGE_BADSCALING macro that does not invoke UB when encountering
|
||||
* (max - min) > ZEND_LONG_MAX.
|
||||
@@ -254,7 +259,7 @@ PHP_METHOD(Random_Randomizer, getInt)
|
||||
|
||||
result = (zend_long) (offset + min);
|
||||
} else {
|
||||
result = randomizer->algo->range(randomizer->status, min, max);
|
||||
result = engine.algo->range(engine.status, min, max);
|
||||
}
|
||||
|
||||
if (EG(exception)) {
|
||||
@@ -269,6 +274,8 @@ PHP_METHOD(Random_Randomizer, getInt)
|
||||
PHP_METHOD(Random_Randomizer, getBytes)
|
||||
{
|
||||
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = randomizer->engine;
|
||||
|
||||
zend_string *retval;
|
||||
zend_long length;
|
||||
size_t total_size = 0;
|
||||
@@ -285,7 +292,7 @@ PHP_METHOD(Random_Randomizer, getBytes)
|
||||
retval = zend_string_alloc(length, 0);
|
||||
|
||||
while (total_size < length) {
|
||||
php_random_result result = randomizer->algo->generate(randomizer->status);
|
||||
php_random_result result = engine.algo->generate(engine.status);
|
||||
if (EG(exception)) {
|
||||
zend_string_free(retval);
|
||||
RETURN_THROWS();
|
||||
@@ -314,7 +321,7 @@ PHP_METHOD(Random_Randomizer, shuffleArray)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
ZVAL_DUP(return_value, array);
|
||||
if (!php_array_data_shuffle(randomizer->algo, randomizer->status, return_value)) {
|
||||
if (!php_array_data_shuffle(randomizer->engine, return_value)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
}
|
||||
@@ -335,7 +342,7 @@ PHP_METHOD(Random_Randomizer, shuffleBytes)
|
||||
}
|
||||
|
||||
RETVAL_STRINGL(ZSTR_VAL(bytes), ZSTR_LEN(bytes));
|
||||
if (!php_binary_string_shuffle(randomizer->algo, randomizer->status, Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value))) {
|
||||
if (!php_binary_string_shuffle(randomizer->engine, Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value))) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
}
|
||||
@@ -354,8 +361,7 @@ PHP_METHOD(Random_Randomizer, pickArrayKeys)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (!php_array_pick_keys(
|
||||
randomizer->algo,
|
||||
randomizer->status,
|
||||
randomizer->engine,
|
||||
input,
|
||||
num_req,
|
||||
return_value,
|
||||
@@ -377,6 +383,8 @@ PHP_METHOD(Random_Randomizer, pickArrayKeys)
|
||||
PHP_METHOD(Random_Randomizer, getBytesFromString)
|
||||
{
|
||||
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
|
||||
php_random_algo_with_state engine = randomizer->engine;
|
||||
|
||||
zend_long length;
|
||||
zend_string *source, *retval;
|
||||
size_t total_size = 0;
|
||||
@@ -403,7 +411,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString)
|
||||
|
||||
if (max_offset > 0xff) {
|
||||
while (total_size < length) {
|
||||
uint64_t offset = randomizer->algo->range(randomizer->status, 0, max_offset);
|
||||
uint64_t offset = engine.algo->range(engine.status, 0, max_offset);
|
||||
|
||||
if (EG(exception)) {
|
||||
zend_string_free(retval);
|
||||
@@ -424,7 +432,7 @@ PHP_METHOD(Random_Randomizer, getBytesFromString)
|
||||
|
||||
int failures = 0;
|
||||
while (total_size < length) {
|
||||
php_random_result result = randomizer->algo->generate(randomizer->status);
|
||||
php_random_result result = engine.algo->generate(engine.status);
|
||||
if (EG(exception)) {
|
||||
zend_string_free(retval);
|
||||
RETURN_THROWS();
|
||||
|
||||
@@ -3211,8 +3211,11 @@ boundary_error:
|
||||
#undef RANGE_CHECK_LONG_INIT_ARRAY
|
||||
|
||||
/* {{{ php_array_data_shuffle */
|
||||
PHPAPI bool php_array_data_shuffle(const php_random_algo *algo, php_random_status *status, zval *array) /* {{{ */
|
||||
PHPAPI bool php_array_data_shuffle(php_random_algo_with_state engine, zval *array) /* {{{ */
|
||||
{
|
||||
const php_random_algo *algo = engine.algo;
|
||||
void *status = engine.status;
|
||||
|
||||
int64_t idx, j, n_elems, rnd_idx, n_left;
|
||||
zval *zv, temp;
|
||||
HashTable *hash;
|
||||
@@ -3310,7 +3313,7 @@ PHP_FUNCTION(shuffle)
|
||||
Z_PARAM_ARRAY_EX(array, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_array_data_shuffle(php_random_default_algo(), php_random_default_status(), array);
|
||||
php_array_data_shuffle(php_random_default_engine(), array);
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
@@ -6191,8 +6194,11 @@ clean_up:
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_array_pick_keys */
|
||||
PHPAPI bool php_array_pick_keys(const php_random_algo *algo, php_random_status *status, zval *input, zend_long num_req, zval *retval, bool silent)
|
||||
PHPAPI bool php_array_pick_keys(php_random_algo_with_state engine, zval *input, zend_long num_req, zval *retval, bool silent)
|
||||
{
|
||||
const php_random_algo *algo = engine.algo;
|
||||
void *status = engine.status;
|
||||
|
||||
HashTable *ht = Z_ARRVAL_P(input);
|
||||
uint32_t num_avail = zend_hash_num_elements(ht);
|
||||
zend_long i, randval;
|
||||
@@ -6350,8 +6356,7 @@ PHP_FUNCTION(array_rand)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (!php_array_pick_keys(
|
||||
php_random_default_algo(),
|
||||
php_random_default_status(),
|
||||
php_random_default_engine(),
|
||||
input,
|
||||
num_req,
|
||||
return_value,
|
||||
|
||||
@@ -31,8 +31,8 @@ PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src);
|
||||
PHPAPI int php_multisort_compare(const void *a, const void *b);
|
||||
PHPAPI zend_long php_count_recursive(HashTable *ht);
|
||||
|
||||
PHPAPI bool php_array_data_shuffle(const php_random_algo *algo, php_random_status *status, zval *array);
|
||||
PHPAPI bool php_array_pick_keys(const php_random_algo *algo, php_random_status *status, zval *input, zend_long num_req, zval *retval, bool silent);
|
||||
PHPAPI bool php_array_data_shuffle(php_random_algo_with_state engine, zval *array);
|
||||
PHPAPI bool php_array_pick_keys(php_random_algo_with_state engine, zval *input, zend_long num_req, zval *retval, bool silent);
|
||||
|
||||
#define PHP_EXTR_OVERWRITE 0
|
||||
#define PHP_EXTR_SKIP 1
|
||||
|
||||
@@ -62,7 +62,7 @@ PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2
|
||||
PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2);
|
||||
PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2);
|
||||
|
||||
PHPAPI bool php_binary_string_shuffle(const php_random_algo *algo, php_random_status *status, char *str, zend_long len);
|
||||
PHPAPI bool php_binary_string_shuffle(php_random_algo_with_state engine, char *str, zend_long len);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
# ifdef PHP_WIN32
|
||||
|
||||
@@ -5953,8 +5953,11 @@ PHP_FUNCTION(str_rot13)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_binary_string_shuffle */
|
||||
PHPAPI bool php_binary_string_shuffle(const php_random_algo *algo, php_random_status *status, char *str, zend_long len) /* {{{ */
|
||||
PHPAPI bool php_binary_string_shuffle(php_random_algo_with_state engine, char *str, zend_long len) /* {{{ */
|
||||
{
|
||||
const php_random_algo *algo = engine.algo;
|
||||
void *status = engine.status;
|
||||
|
||||
int64_t n_elems, rnd_idx, n_left;
|
||||
char temp;
|
||||
|
||||
@@ -5996,8 +5999,7 @@ PHP_FUNCTION(str_shuffle)
|
||||
RETVAL_STRINGL(ZSTR_VAL(arg), ZSTR_LEN(arg));
|
||||
if (Z_STRLEN_P(return_value) > 1) {
|
||||
php_binary_string_shuffle(
|
||||
php_random_default_algo(),
|
||||
php_random_default_status(),
|
||||
php_random_default_engine(),
|
||||
Z_STRVAL_P(return_value),
|
||||
Z_STRLEN_P(return_value)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user