Skip to content

Commit 30c6073

Browse files
committed
add buffering Randomizer::getBytes
1 parent fe069a7 commit 30c6073

File tree

3 files changed

+54
-39
lines changed

3 files changed

+54
-39
lines changed

ext/random/php_random.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ typedef struct _php_random_randomizer {
176176
const php_random_engine_algo *algo;
177177
void *state;
178178
bool self_allocate;
179+
uint64_t buffer;
180+
size_t buffer_size;
179181
zend_object std;
180182
} php_random_randomizer;
181183

ext/random/random.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,8 @@ static zend_object *php_random_randomizer_new(zend_class_entry *ce) {
801801
zend_object_std_init(&randomizer->std, ce);
802802
object_properties_init(&randomizer->std, ce);
803803

804+
randomizer->buffer = 0;
805+
randomizer->buffer_size = 0;
804806
randomizer->std.handlers = &random_randomizer_object_handlers;
805807

806808
return &randomizer->std;
@@ -1544,9 +1546,9 @@ PHP_METHOD(Random_Randomizer, getBytes)
15441546
php_random_randomizer *randomizer = Z_RANDOM_RANDOMIZER_P(ZEND_THIS);
15451547
zend_string *retval;
15461548
zend_long length;
1547-
size_t total_size = 0;
1548-
size_t required_size;
1549-
int i;
1549+
uint64_t result;
1550+
size_t generated_size;
1551+
int i = 0;
15501552

15511553
ZEND_PARSE_PARAMETERS_START(1, 1)
15521554
Z_PARAM_LONG(length)
@@ -1558,20 +1560,18 @@ PHP_METHOD(Random_Randomizer, getBytes)
15581560
}
15591561

15601562
retval = zend_string_alloc(length, 0);
1561-
required_size = length;
1562-
1563-
while (total_size < required_size) {
1564-
uint64_t result;
1565-
size_t generated_size;
1566-
1567-
RANDOM_ENGINE_GENERATE_SIZE(randomizer->algo, randomizer->state, result, generated_size);
15681563

1569-
for (i = 0; i < generated_size; i++) {
1570-
ZSTR_VAL(retval)[total_size++] = (result >> (i * 8) & 0xff);
1571-
if (total_size >= required_size) {
1572-
break;
1573-
}
1564+
while (i < length) {
1565+
if (randomizer->buffer_size == 0) {
1566+
RANDOM_ENGINE_GENERATE_SIZE(randomizer->algo, randomizer->state, result, generated_size);
1567+
randomizer->buffer = result;
1568+
randomizer->buffer_size = generated_size;
15741569
}
1570+
1571+
ZSTR_VAL(retval)[i] = randomizer->buffer & 0xff;
1572+
randomizer->buffer >>= 8;
1573+
--randomizer->buffer_size;
1574+
++i;
15751575
}
15761576

15771577
ZSTR_VAL(retval)[length] = '\0';

ext/random/tests/randomizer/get_bytes.phpt

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,46 @@ Random: Randomizer: getBytes
33
--FILE--
44
<?php
55

6-
$randomizer = new \Random\Randomizer (
7-
new class () implements \Random\Engine
8-
{
9-
private int $count = 0;
6+
$engine = new class () implements \Random\Engine {
7+
private int $count = 0;
108

11-
public function generate(): string
12-
{
13-
return match ($this->count++) {
14-
0 => 'H',
15-
1 => 'e',
16-
2 => 'l',
17-
3 => 'l',
18-
4 => 'o',
19-
5 => \random_bytes(32), // 128-bit
20-
default => \random_bytes(16),
21-
};
22-
}
9+
public function generate(): string
10+
{
11+
return match ($this->count++) {
12+
0 => 'H',
13+
1 => 'e',
14+
2 => 'l',
15+
3 => 'l',
16+
4 => 'o',
17+
5 => 'Hello',
18+
6 => 'Hello',
19+
6 => \random_bytes(32), // 128-bit
20+
default => \random_bytes(16),
21+
};
2322
}
24-
);
25-
26-
if ($randomizer->getBytes(5) !== 'Hello') {
27-
die('failure');
28-
}
2923

30-
$randomizer->getBytes(6);
24+
public function getCount(): int
25+
{
26+
return $this->count;
27+
}
28+
};
29+
$randomizer = new \Random\Randomizer ($engine);
3130

32-
die('success');
31+
echo $randomizer->getBytes(5). PHP_EOL;
32+
echo $engine->getCount() . PHP_EOL;
33+
echo $randomizer->getBytes(5). PHP_EOL;
34+
echo $engine->getCount() . PHP_EOL;
35+
echo $randomizer->getBytes(4). PHP_EOL;
36+
echo $engine->getCount() . PHP_EOL;
37+
echo $randomizer->getBytes(1). PHP_EOL;
38+
echo $engine->getCount() . PHP_EOL;
3339
?>
3440
--EXPECTF--
35-
success
41+
Hello
42+
5
43+
Hello
44+
6
45+
Hell
46+
7
47+
o
48+
7

0 commit comments

Comments
 (0)