44 * chdemko\BitArray\BitArray class
55 *
66 * @author Christophe Demko <[email protected] > 7- * @copyright Copyright (C) 2012-2016 Christophe Demko. All rights reserved.
7+ * @copyright Copyright (C) 2012-2018 Christophe Demko. All rights reserved.
88 *
9- * @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html The CeCILL B license
9+ * @license BSD 3-Clause License
1010 *
1111 * This file is part of the php-bitarray package https://github.com/chdemko/php-bitarray
1212 */
1919 *
2020 * @package BitArray
2121 *
22- * @property-read integer $count The number of bits set to true
23- * @property-read integer $size The number of bits
24- *
22+ * @property-read integer $count The number of bits set to true
23+ * @property-read integer $size The number of bits
24+ *
2525 * @since 1.0.0
2626 */
2727class BitArray implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
2828{
29+ /**
30+ * @var BitArray Empty bit array
31+ */
32+ private static $ empty ;
33+
2934 /**
3035 * @var integer[] Number of bits for each value between 0 and 255
3136 */
32- private static $ count = [
37+ private static $ count = array (
3338 0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 ,
3439 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 ,
3540 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 ,
@@ -46,12 +51,12 @@ class BitArray implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSer
4651 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 ,
4752 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 ,
4853 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8
49- ] ;
54+ ) ;
5055
5156 /**
5257 * @var integer[] Mask for restricting complements
5358 */
54- private static $ restrict = [ 255 , 1 , 3 , 7 , 15 , 31 , 63 , 127 ] ;
59+ private static $ restrict = array ( 255 , 1 , 3 , 7 , 15 , 31 , 63 , 127 ) ;
5560
5661 /**
5762 * @var string Underlying data
@@ -70,14 +75,43 @@ class BitArray implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSer
7075 /**
7176 * Create a new bit array of the given size
7277 *
73- * @param integer $size The BitArray size
78+ * @param integer $size The BitArray size
79+ * @param boolean $default The default value for bits
7480 *
7581 * @since 1.0.0
7682 */
77- protected function __construct ($ size )
83+ protected function __construct ($ size = 0 , $ default = false )
7884 {
7985 $ this ->size = (int ) $ size ;
80- $ this ->data = str_repeat ("\0" , ceil ($ this ->size / 8 ));
86+
87+ if ($ default )
88+ {
89+ $ this ->data = str_repeat (chr (255 ), ceil ($ this ->size / 8 ));
90+ $ this ->restrict ();
91+ }
92+ else
93+ {
94+ $ this ->data = str_repeat (chr (0 ), ceil ($ this ->size / 8 ));
95+ }
96+ }
97+
98+ /**
99+ * Remove useless bits for simplifying count operation.
100+ *
101+ * @return BitArray $this for chaining
102+ *
103+ * @since 1.2.0
104+ */
105+ protected function restrict ()
106+ {
107+ $ length = strlen ($ this ->data );
108+
109+ if ($ length > 0 )
110+ {
111+ $ this ->data [$ length - 1 ] = chr (ord ($ this ->data [$ length - 1 ]) & self ::$ restrict [$ this ->size % 8 ]);
112+ }
113+
114+ return $ this ;
81115 }
82116
83117 /**
@@ -252,7 +286,7 @@ public function count()
252286 */
253287 public function toArray ()
254288 {
255- $ array = [] ;
289+ $ array = array () ;
256290
257291 for ($ index = 0 ; $ index < $ this ->size ; $ index ++)
258292 {
@@ -372,7 +406,7 @@ public function copy(BitArray $bits, $index = 0, $offset = 0, $size = null)
372406 * @param int $offset If offset is non-negative, the offset parameter is used as it is, keeping its real value between 0 and size-1.
373407 * If offset is negative, the offset parameter starts from the end, keeping its real value between 0 and size-1.
374408 *
375- * @return int The real offset
409+ * @return integer The real offset
376410 *
377411 * @since 1.1.0
378412 */
@@ -406,7 +440,7 @@ protected function getRealOffset($offset)
406440 * If size is given and is negative then the real size starts from the end.
407441 * If it is omitted, then the size goes until the end of the BitArray.
408442 *
409- * @return int The real size
443+ * @return integer The real size
410444 *
411445 * @since 1.1.0
412446 */
@@ -441,15 +475,41 @@ protected function getRealSize($offset, $size)
441475 /**
442476 * Create a new BitArray from an integer
443477 *
444- * @param integer $size Size of the BitArray
478+ * @param integer $size Size of the BitArray
479+ * @param boolean $default The default value for bits
445480 *
446481 * @return BitArray A new BitArray
447482 *
448483 * @since 1.0.0
449484 */
450- public static function fromInteger ($ size )
485+ public static function fromInteger ($ size, $ default = false )
451486 {
452- return new BitArray ($ size );
487+ return new BitArray ($ size , (bool ) $ default );
488+ }
489+
490+ /**
491+ * Create a new BitArray from a sequence of bits.
492+ *
493+ * @param integer $size Size of the BitArray
494+ * @param integer $values The values for the bits
495+ *
496+ * @return BitArray A new BitArray
497+ *
498+ * @since 1.2.0
499+ */
500+ public static function fromDecimal ($ size , $ values = 0 )
501+ {
502+ $ size = min ((int ) $ size , PHP_INT_SIZE );
503+ $ values <<= PHP_INT_SIZE - $ size ;
504+ $ bits = new BitArray ($ size );
505+
506+ for ($ i = 0 ; $ i < PHP_INT_SIZE ; $ i ++)
507+ {
508+ $ bits ->data [$ i ] = chr (($ values & (0xff << (PHP_INT_SIZE - 8 ))) >> (PHP_INT_SIZE - 8 ));
509+ $ values <<= 8 ;
510+ }
511+
512+ return $ bits ;
453513 }
454514
455515 /**
@@ -601,13 +661,7 @@ public function applyComplement()
601661 $ this ->data [$ index ] = chr (~ ord ($ this ->data [$ index ]));
602662 }
603663
604- // Remove useless bits
605- if ($ length > 0 )
606- {
607- $ this ->data [$ length - 1 ] = chr (ord ($ this ->data [$ length - 1 ]) & self ::$ restrict [$ this ->size % 8 ]);
608- }
609-
610- return $ this ;
664+ return $ this ->restrict ();
611665 }
612666
613667 /**
@@ -699,4 +753,52 @@ public function applyXor(BitArray $bits)
699753 throw new \InvalidArgumentException ('Argument must be of equal size ' );
700754 }
701755 }
756+
757+ /**
758+ * Shift a bit array.
759+ *
760+ * @param int $size Size to shift.
761+ * Negative value means the shifting is done right to left while
762+ * positive value means the shifting is done left to right.
763+ * @param boolean $value Value to shift
764+ *
765+ * @return BitArray $this for chaining
766+ *
767+ * @since 1.2.0
768+ */
769+ public function shift ($ size = 1 , $ value = false )
770+ {
771+ $ size = (int ) $ size ;
772+
773+ if ($ size > 0 )
774+ {
775+ $ min = min ($ this ->size , $ size );
776+
777+ for ($ i = $ this ->size - 1 ; $ i >= $ min ; $ i --)
778+ {
779+ $ this [$ i ] = $ this [$ i - $ min ];
780+ }
781+
782+ for ($ i = 0 ; $ i < $ min ; $ i ++)
783+ {
784+ $ this [$ i ] = $ value ;
785+ }
786+ }
787+ else
788+ {
789+ $ min = min ($ this ->size , -$ size );
790+
791+ for ($ i = 0 ; $ i < $ this ->size - $ min ; $ i ++)
792+ {
793+ $ this [$ i ] = $ this [$ i + $ min ];
794+ }
795+
796+ for ($ i = $ this ->size - $ min ; $ i < $ this ->size ; $ i ++)
797+ {
798+ $ this [$ i ] = $ value ;
799+ }
800+ }
801+
802+ return $ this ;
803+ }
702804}
0 commit comments