]> granicus.if.org Git - php/commitdiff
Use zend_bitset
authorLeigh <leigh@php.net>
Thu, 7 Jul 2016 10:16:01 +0000 (11:16 +0100)
committerLeigh <leigh@php.net>
Thu, 7 Jul 2016 10:16:01 +0000 (11:16 +0100)
ext/standard/array.c

index 2cdb117832faf54a3caab1303b7483475ae1bc0f..efe309515c71481d4bc1262965858527fb6e4f7a 100644 (file)
@@ -46,6 +46,7 @@
 #include "php_string.h"
 #include "php_rand.h"
 #include "zend_smart_str.h"
+#include "zend_bitset.h"
 #include "ext/spl/spl_array.h"
 
 /* {{{ defines */
 #define INTERSECT_COMP_DATA_USER     1
 #define INTERSECT_COMP_KEY_INTERNAL  0
 #define INTERSECT_COMP_KEY_USER      1
-
-// For array_rand even distribution
-#define BITFIELD_BYTES(bits) ((bits + 7) >> 3)
-#define BITFIELD_SETBIT(field, bit) field[bit >> 3] |= 1 << (bit & 7)
-#define BITFIELD_BITSET(field, bit) ((field[bit >> 3] & (1 << (bit & 7))) != 0)
-
 /* }}} */
 
 ZEND_DECLARE_MODULE_GLOBALS(array)
@@ -5043,8 +5038,9 @@ PHP_FUNCTION(array_rand)
        zend_ulong num_key;
        int i;
        int num_avail;
-       char *bitfield;
-       int negative_bitfield = 0;
+       zend_bitset bitset;
+       int negative_bitset = 0;
+       uint32_t bitset_len;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &input, &num_req) == FAILURE) {
                return;
@@ -5079,18 +5075,20 @@ PHP_FUNCTION(array_rand)
        /* Make the return value an array only if we need to pass back more than one result. */
        array_init_size(return_value, (uint32_t)num_req);
        if (num_req > (num_avail >> 1)) {
-               negative_bitfield = 1;
+               negative_bitset = 1;
                num_req = num_avail - num_req;
        }
 
-       bitfield = emalloc(BITFIELD_BYTES(num_avail));
-       memset(bitfield, 0, BITFIELD_BYTES(num_avail));
+       ALLOCA_FLAG(use_heap);
+       bitset_len = zend_bitset_len(num_avail);
+       bitset = ZEND_BITSET_ALLOCA(bitset_len, use_heap);
+       zend_bitset_clear(bitset, bitset_len);
 
        i = num_req;
        while (i) {
                randval = php_mt_rand_range(0, num_avail - 1);
-               if (!BITFIELD_BITSET(bitfield, randval)) {
-                       BITFIELD_SETBIT(bitfield, randval);
+               if (!zend_bitset_in(bitset, randval)) {
+                       zend_bitset_incl(bitset, randval);
                        i--;
                }
        }
@@ -5098,7 +5096,7 @@ PHP_FUNCTION(array_rand)
        /* We can't use zend_hash_index_find() because the array may have string keys or gaps. */
        i = 0;
        ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
-               if (BITFIELD_BITSET(bitfield, i) ^ negative_bitfield) {
+               if (zend_bitset_in(bitset, i) ^ negative_bitset) {
                        if (string_key) {
                                add_next_index_str(return_value, zend_string_copy(string_key));
                        } else {
@@ -5108,7 +5106,7 @@ PHP_FUNCTION(array_rand)
                i++;
        } ZEND_HASH_FOREACH_END();
 
-       efree(bitfield);
+       free_alloca(bitset, use_heap);
 }
 /* }}} */