aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php')
-rw-r--r--vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php180
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php b/vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php
new file mode 100644
index 000000000..4a59f2b58
--- /dev/null
+++ b/vendor/chillerlan/php-qrcode/src/Common/BitBuffer.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Class BitBuffer
+ *
+ * @created 25.11.2015
+ * @author Smiley <smiley@chillerlan.net>
+ * @copyright 2015 Smiley
+ * @license MIT
+ */
+
+namespace chillerlan\QRCode\Common;
+
+use chillerlan\QRCode\QRCodeException;
+use function count, floor, min;
+
+/**
+ * Holds the raw binary data
+ */
+final class BitBuffer{
+
+ /**
+ * The buffer content
+ *
+ * @var int[]
+ */
+ private array $buffer;
+
+ /**
+ * Length of the content (bits)
+ */
+ private int $length;
+
+ /**
+ * Read count (bytes)
+ */
+ private int $bytesRead = 0;
+
+ /**
+ * Read count (bits)
+ */
+ private int $bitsRead = 0;
+
+ /**
+ * BitBuffer constructor.
+ *
+ * @param int[] $bytes
+ */
+ public function __construct(array $bytes = []){
+ $this->buffer = $bytes;
+ $this->length = count($this->buffer);
+ }
+
+ /**
+ * appends a sequence of bits
+ */
+ public function put(int $bits, int $length):self{
+
+ for($i = 0; $i < $length; $i++){
+ $this->putBit((($bits >> ($length - $i - 1)) & 1) === 1);
+ }
+
+ return $this;
+ }
+
+ /**
+ * appends a single bit
+ */
+ public function putBit(bool $bit):self{
+ $bufIndex = (int)floor($this->length / 8);
+
+ if(count($this->buffer) <= $bufIndex){
+ $this->buffer[] = 0;
+ }
+
+ if($bit === true){
+ $this->buffer[$bufIndex] |= (0x80 >> ($this->length % 8));
+ }
+
+ $this->length++;
+
+ return $this;
+ }
+
+ /**
+ * returns the current buffer length
+ */
+ public function getLength():int{
+ return $this->length;
+ }
+
+ /**
+ * returns the buffer content
+ *
+ * to debug: array_map(fn($v) => sprintf('%08b', $v), $bitBuffer->getBuffer())
+ */
+ public function getBuffer():array{
+ return $this->buffer;
+ }
+
+ /**
+ * @return int number of bits that can be read successfully
+ */
+ public function available():int{
+ return ((8 * ($this->length - $this->bytesRead)) - $this->bitsRead);
+ }
+
+ /**
+ * @author Sean Owen, ZXing
+ *
+ * @param int $numBits number of bits to read
+ *
+ * @return int representing the bits read. The bits will appear as the least-significant bits of the int
+ * @throws \chillerlan\QRCode\QRCodeException if numBits isn't in [1,32] or more than is available
+ */
+ public function read(int $numBits):int{
+
+ if($numBits < 1 || $numBits > $this->available()){
+ throw new QRCodeException('invalid $numBits: '.$numBits);
+ }
+
+ $result = 0;
+
+ // First, read remainder from current byte
+ if($this->bitsRead > 0){
+ $bitsLeft = (8 - $this->bitsRead);
+ $toRead = min($numBits, $bitsLeft);
+ $bitsToNotRead = ($bitsLeft - $toRead);
+ $mask = ((0xff >> (8 - $toRead)) << $bitsToNotRead);
+ $result = (($this->buffer[$this->bytesRead] & $mask) >> $bitsToNotRead);
+ $numBits -= $toRead;
+ $this->bitsRead += $toRead;
+
+ if($this->bitsRead === 8){
+ $this->bitsRead = 0;
+ $this->bytesRead++;
+ }
+ }
+
+ // Next read whole bytes
+ if($numBits > 0){
+
+ while($numBits >= 8){
+ $result = (($result << 8) | ($this->buffer[$this->bytesRead] & 0xff));
+ $this->bytesRead++;
+ $numBits -= 8;
+ }
+
+ // Finally read a partial byte
+ if($numBits > 0){
+ $bitsToNotRead = (8 - $numBits);
+ $mask = ((0xff >> $bitsToNotRead) << $bitsToNotRead);
+ $result = (($result << $numBits) | (($this->buffer[$this->bytesRead] & $mask) >> $bitsToNotRead));
+ $this->bitsRead += $numBits;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Clears the buffer and resets the stats
+ */
+ public function clear():self{
+ $this->buffer = [];
+ $this->length = 0;
+
+ return $this->rewind();
+ }
+
+ /**
+ * Resets the read-counters
+ */
+ public function rewind():self{
+ $this->bytesRead = 0;
+ $this->bitsRead = 0;
+
+ return $this;
+ }
+
+}