| <?php |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace Zxing\Common; |
|
|
| |
| |
| |
| |
| |
|
|
| final class BitArray |
| { |
|
|
| private $bits; |
| private $size; |
|
|
|
|
| public function __construct($bits = [], $size = 0) |
| { |
|
|
| if (!$bits && !$size) { |
| $this->$size = 0; |
| $this->bits = []; |
| } elseif ($bits && !$size) { |
| $this->size = $bits; |
| $this->bits = $this->makeArray($bits); |
| } else { |
| $this->bits = $bits; |
| $this->size = $size; |
| } |
|
|
| } |
|
|
| private static function makeArray($size) |
| { |
| return []; |
| } |
|
|
| public function getSize() |
| { |
| return $this->size; |
| } |
|
|
| public function getSizeInBytes() |
| { |
| return ($this->size + 7) / 8; |
| } |
|
|
| |
| |
| |
| |
| |
| public function set($i) |
| { |
| $this->bits[(int)($i / 32)] |= 1 << ($i & 0x1F); |
| $this->bits[(int)($i / 32)] = ($this->bits[(int)($i / 32)]); |
| } |
|
|
| |
| |
| |
| |
| |
| public function flip($i) |
| { |
| $this->bits[(int)($i / 32)] ^= 1 << ($i & 0x1F); |
| $this->bits[(int)($i / 32)] = ($this->bits[(int)($i / 32)]); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function getNextSet($from) |
| { |
| if ($from >= $this->size) { |
| return $this->size; |
| } |
| $bitsOffset = (int)($from / 32); |
| $currentBits = (int)$this->bits[$bitsOffset]; |
| |
| $currentBits &= ~((1 << ($from & 0x1F)) - 1); |
| while ($currentBits == 0) { |
| if (++$bitsOffset == count($this->bits)) { |
| return $this->size; |
| } |
| $currentBits = $this->bits[$bitsOffset]; |
| } |
| $result = ($bitsOffset * 32) + numberOfTrailingZeros($currentBits); |
|
|
| return $result > $this->size ? $this->size : $result; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function getNextUnset($from) |
| { |
| if ($from >= $this->size) { |
| return $this->size; |
| } |
| $bitsOffset = (int)($from / 32); |
| $currentBits = ~$this->bits[$bitsOffset]; |
| |
| $currentBits &= ~((1 << ($from & 0x1F)) - 1); |
| while ($currentBits == 0) { |
| if (++$bitsOffset == count($this->bits)) { |
| return $this->size; |
| } |
| $currentBits = (~$this->bits[$bitsOffset]); |
| } |
| $result = ($bitsOffset * 32) + numberOfTrailingZeros($currentBits); |
|
|
| return $result > $this->size ? $this->size : $result; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public function setBulk($i, $newBits) |
| { |
| $this->bits[(int)($i / 32)] = $newBits; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function setRange($start, $end) |
| { |
| if ($end < $start) { |
| throw new \InvalidArgumentException(); |
| } |
| if ($end == $start) { |
| return; |
| } |
| $end--; |
| $firstInt = (int)($start / 32); |
| $lastInt = (int)($end / 32); |
| for ($i = $firstInt; $i <= $lastInt; $i++) { |
| $firstBit = $i > $firstInt ? 0 : $start & 0x1F; |
| $lastBit = $i < $lastInt ? 31 : $end & 0x1F; |
| $mask = 0; |
| if ($firstBit == 0 && $lastBit == 31) { |
| $mask = -1; |
| } else { |
| $mask = 0; |
| for ($j = $firstBit; $j <= $lastBit; $j++) { |
| $mask |= 1 << $j; |
| } |
| } |
| $this->bits[$i] = ($this->bits[$i] | $mask); |
| } |
| } |
|
|
| |
| |
| |
| public function clear() |
| { |
| $max = count($this->bits); |
| for ($i = 0; $i < $max; $i++) { |
| $this->bits[$i] = 0; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function isRange($start, $end, $value) |
| { |
| if ($end < $start) { |
| throw new \InvalidArgumentException(); |
| } |
| if ($end == $start) { |
| return true; |
| } |
| $end--; |
| $firstInt = (int)($start / 32); |
| $lastInt = (int)($end / 32); |
| for ($i = $firstInt; $i <= $lastInt; $i++) { |
| $firstBit = $i > $firstInt ? 0 : $start & 0x1F; |
| $lastBit = $i < $lastInt ? 31 : $end & 0x1F; |
| $mask = 0; |
| if ($firstBit == 0 && $lastBit == 31) { |
| $mask = -1; |
| } else { |
| $mask = 0; |
| for ($j = $firstBit; $j <= $lastBit; $j++) { |
| $mask = ($mask | (1 << $j)); |
| } |
| } |
|
|
| |
| |
| if (($this->bits[$i] & $mask) != ($value ? $mask : 0)) { |
| return false; |
| } |
| } |
|
|
| return true; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public function appendBits($value, $numBits) |
| { |
| if ($numBits < 0 || $numBits > 32) { |
| throw new \InvalidArgumentException("Num bits must be between 0 and 32"); |
| } |
| $this->ensureCapacity($this->size + $numBits); |
| for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) { |
| $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) == 1); |
| } |
| } |
|
|
| private function ensureCapacity($size) |
| { |
| if ($size > count($this->bits) * 32) { |
| $newBits = $this->makeArray($size); |
| $newBits = arraycopy($this->bits, 0, $newBits, 0, count($this->bits)); |
| $this->bits = $newBits; |
| } |
| } |
|
|
| public function appendBit($bit) |
| { |
| $this->ensureCapacity($this->size + 1); |
| if ($bit) { |
| $this->bits[(int)($this->size / 32)] |= 1 << ($this->size & 0x1F); |
| } |
| $this->size++; |
| } |
|
|
| public function appendBitArray($other) |
| { |
| $otherSize = $other->size; |
| $this->ensureCapacity($this->size + $otherSize); |
| for ($i = 0; $i < $otherSize; $i++) { |
| $this->appendBit($other->get($i)); |
| } |
| } |
|
|
| public function _xor($other) |
| { |
| if (count($this->bits) !== count($other->bits)) { |
| throw new \InvalidArgumentException("Sizes don't match"); |
| } |
| $count = count($this->bits); |
| for ($i = 0; $i < $count; $i++) { |
| |
| |
| $this->bits[$i] ^= $other->bits[$i]; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public function toBytes($bitOffset, &$array, $offset, $numBytes) |
| { |
| for ($i = 0; $i < $numBytes; $i++) { |
| $theByte = 0; |
| for ($j = 0; $j < 8; $j++) { |
| if ($this->get($bitOffset)) { |
| $theByte |= 1 << (7 - $j); |
| } |
| $bitOffset++; |
| } |
| $array[(int)($offset + $i)] = $theByte; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| public function get($i) |
| { |
| $key = (int)($i / 32); |
|
|
| return ($this->bits[$key] & (1 << ($i & 0x1F))) != 0; |
| } |
|
|
| |
| |
| |
| |
| public function getBitArray() |
| { |
| return $this->bits; |
| } |
|
|
| |
| |
| |
| public function reverse() |
| { |
| $newBits = []; |
| |
| $len = (($this->size - 1) / 32); |
| $oldBitsLen = $len + 1; |
| for ($i = 0; $i < $oldBitsLen; $i++) { |
| $x = $this->bits[$i]; |
| |
| |
| |
| |
| |
| $x = (($x >> 1) & 0x55555555) | (($x & 0x55555555) << 1); |
| $x = (($x >> 2) & 0x33333333) | (($x & 0x33333333) << 2); |
| $x = (($x >> 4) & 0x0f0f0f0f) | (($x & 0x0f0f0f0f) << 4); |
| $x = (($x >> 8) & 0x00ff00ff) | (($x & 0x00ff00ff) << 8); |
| $x = (($x >> 16) & 0x0000ffff) | (($x & 0x0000ffff) << 16); |
| $newBits[(int)$len - $i] = (int)$x; |
| } |
| |
| if ($this->size != $oldBitsLen * 32) { |
| $leftOffset = $oldBitsLen * 32 - $this->size; |
| $mask = 1; |
| for ($i = 0; $i < 31 - $leftOffset; $i++) { |
| $mask = ($mask << 1) | 1; |
| } |
| $currentInt = ($newBits[0] >> $leftOffset) & $mask; |
| for ($i = 1; $i < $oldBitsLen; $i++) { |
| $nextInt = $newBits[$i]; |
| $currentInt |= $nextInt << (32 - $leftOffset); |
| $newBits[(int)($i) - 1] = $currentInt; |
| $currentInt = ($nextInt >> $leftOffset) & $mask; |
| } |
| $newBits[(int)($oldBitsLen) - 1] = $currentInt; |
| } |
| |
| } |
|
|
| public function equals($o) |
| { |
| if (!($o instanceof BitArray)) { |
| return false; |
| } |
| $other = $o; |
|
|
| return $this->size == $other->size && $this->bits === $other->bits; |
| } |
|
|
| public function hashCode() |
| { |
| return 31 * $this->size + hashCode($this->bits); |
| } |
|
|
| public function toString() |
| { |
| $result = ''; |
| for ($i = 0; $i < $this->size; $i++) { |
| if (($i & 0x07) == 0) { |
| $result .= ' '; |
| } |
| $result .= ($this->get($i) ? 'X' : '.'); |
| } |
|
|
| return (string)$result; |
| } |
|
|
| public function _clone() |
| { |
| return new BitArray($this->bits, $this->size); |
| } |
| } |
|
|