codemasher 5 лет назад
Родитель
Сommit
37a40571e6

+ 88 - 0
src/Common/Mode.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * Class Mode
+ *
+ * @filesource   Mode.php
+ * @created      19.11.2020
+ * @package      chillerlan\QRCode\Common
+ * @author       smiley <smiley@chillerlan.net>
+ * @copyright    2020 smiley
+ * @license      MIT
+ */
+
+namespace chillerlan\QRCode\Common;
+
+use chillerlan\QRCode\Data\{AlphaNum, Byte, Kanji, Number};
+use chillerlan\QRCode\QRCodeException;
+
+/**
+ * ISO 18004:2006, 6.4.1, Tables 2 and 3
+ */
+class Mode{
+
+	// ISO/IEC 18004:2000 Table 2
+
+	/** @var int */
+	public const DATA_TERMINATOR       = 0b0000;
+	/** @var int */
+	public const DATA_NUMBER           = 0b0001;
+	/** @var int */
+	public const DATA_ALPHANUM         = 0b0010;
+	/** @var int */
+	public const DATA_BYTE             = 0b0100;
+	/** @var int */
+	public const DATA_KANJI            = 0b1000;
+	/** @var int */
+	public const DATA_STRCTURED_APPEND = 0b0011;
+	/** @var int */
+	public const DATA_FNC1_FIRST       = 0b0101;
+	/** @var int */
+	public const DATA_FNC1_SECOND      = 0b1001;
+	/** @var int */
+	public const DATA_ECI              = 0b0111;
+
+	/**
+	 * mode length bits for the version breakpoints 1-9, 10-26 and 27-40
+	 *
+	 * ISO/IEC 18004:2000 Table 3 - Number of bits in Character Count Indicator
+	 */
+	public const LENGTH_BITS = [
+		self::DATA_NUMBER   => [10, 12, 14],
+		self::DATA_ALPHANUM => [9, 11, 13],
+		self::DATA_BYTE     => [8, 16, 16],
+		self::DATA_KANJI    => [8, 10, 12],
+	];
+
+	/**
+	 * Map of data mode => interface (detection order)
+	 *
+	 * @var string[]
+	 */
+	public const DATA_INTERFACES = [
+		Mode::DATA_NUMBER   => Number::class,
+		Mode::DATA_ALPHANUM => AlphaNum::class,
+		Mode::DATA_KANJI    => Kanji::class,
+		Mode::DATA_BYTE     => Byte::class,
+	];
+
+	/**
+	 * returns the length bits for the version breakpoints 1-9, 10-26 and 27-40
+	 *
+	 * @throws \chillerlan\QRCode\QRCodeException
+	 */
+	public static function getLengthBitsForVersion(int $mode, int $version):int{
+
+		if(!isset(self::LENGTH_BITS[$mode])){
+			throw new QRCodeException('invalid mode given');
+		}
+
+		foreach([9, 26, 40] as $key => $breakpoint){
+			if($version <= $breakpoint){
+				return self::LENGTH_BITS[$mode][$key];
+			}
+		}
+
+		throw new QRCodeException(sprintf('invalid version number: %d', $version));
+	}
+
+}

+ 4 - 4
src/Data/AlphaNum.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
-use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Common\Mode;
 
 
 use function ceil, ord, sprintf, str_split;
 use function ceil, ord, sprintf, str_split;
 
 
@@ -39,7 +39,7 @@ final class AlphaNum extends QRDataModeAbstract{
 		'+' => 40, '-' => 41, '.' => 42, '/' => 43, ':' => 44,
 		'+' => 40, '-' => 41, '.' => 42, '/' => 43, ':' => 44,
 	];
 	];
 
 
-	protected array $lengthBits = [9, 11, 13];
+	protected int $datamode = Mode::DATA_ALPHANUM;
 
 
 	/**
 	/**
 	 * @inheritdoc
 	 * @inheritdoc
@@ -69,8 +69,8 @@ final class AlphaNum extends QRDataModeAbstract{
 		$len = $this->getCharCount();
 		$len = $this->getCharCount();
 
 
 		$bitBuffer
 		$bitBuffer
-			->put(QRCode::DATA_ALPHANUM, 4)
-			->put($len, $this->getLengthBitsForVersion($version))
+			->put($this->datamode, 4)
+			->put($len, Mode::getLengthBitsForVersion($this->datamode, $version))
 		;
 		;
 
 
 		// encode 2 characters in 11 bits
 		// encode 2 characters in 11 bits

+ 4 - 4
src/Data/Byte.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
-use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Common\Mode;
 
 
 use function ord;
 use function ord;
 
 
@@ -25,7 +25,7 @@ use function ord;
  */
  */
 final class Byte extends QRDataModeAbstract{
 final class Byte extends QRDataModeAbstract{
 
 
-	protected array $lengthBits = [8, 16, 16];
+	protected int $datamode = Mode::DATA_BYTE;
 
 
 	/**
 	/**
 	 * @inheritdoc
 	 * @inheritdoc
@@ -48,8 +48,8 @@ final class Byte extends QRDataModeAbstract{
 		$len = $this->getCharCount();
 		$len = $this->getCharCount();
 
 
 		$bitBuffer
 		$bitBuffer
-			->put(QRCode::DATA_BYTE, 4)
-			->put($len, $this->getLengthBitsForVersion($version))
+			->put($this->datamode, 4)
+			->put($len, Mode::getLengthBitsForVersion($this->datamode, $version))
 		;
 		;
 
 
 		$i = 0;
 		$i = 0;

+ 4 - 2
src/Data/ECI.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
-use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Common\Mode;
 
 
 /**
 /**
  * Adds an ECI Designator
  * Adds an ECI Designator
@@ -59,6 +59,8 @@ class ECI extends QRDataModeAbstract{
 	 */
 	 */
 	protected int $encoding;
 	protected int $encoding;
 
 
+	protected int $datamode = Mode::DATA_ECI;
+
 	/**
 	/**
 	 * @inheritDoc
 	 * @inheritDoc
 	 */
 	 */
@@ -87,7 +89,7 @@ class ECI extends QRDataModeAbstract{
 	 */
 	 */
 	public function write(BitBuffer $bitBuffer, int $version):void{
 	public function write(BitBuffer $bitBuffer, int $version):void{
 		$bitBuffer
 		$bitBuffer
-			->put(QRCode::DATA_ECI, 4)
+			->put($this->datamode, 4)
 			->put($this->encoding, 8)
 			->put($this->encoding, 8)
 		;
 		;
 	}
 	}

+ 4 - 4
src/Data/Kanji.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
-use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Common\Mode;
 
 
 use function mb_convert_encoding, mb_detect_encoding, mb_strlen, ord, sprintf, strlen;
 use function mb_convert_encoding, mb_detect_encoding, mb_strlen, ord, sprintf, strlen;
 
 
@@ -25,7 +25,7 @@ use function mb_convert_encoding, mb_detect_encoding, mb_strlen, ord, sprintf, s
  */
  */
 final class Kanji extends QRDataModeAbstract{
 final class Kanji extends QRDataModeAbstract{
 
 
-	protected array $lengthBits = [8, 10, 12];
+	protected int $datamode = Mode::DATA_KANJI;
 
 
 	public function __construct(string $data){
 	public function __construct(string $data){
 		parent::__construct($data);
 		parent::__construct($data);
@@ -76,8 +76,8 @@ final class Kanji extends QRDataModeAbstract{
 	public function write(BitBuffer $bitBuffer, int $version):void{
 	public function write(BitBuffer $bitBuffer, int $version):void{
 
 
 		$bitBuffer
 		$bitBuffer
-			->put(QRCode::DATA_KANJI, 4)
-			->put($this->getCharCount(), $this->getLengthBitsForVersion($version))
+			->put($this->datamode, 4)
+			->put($this->getCharCount(), Mode::getLengthBitsForVersion($this->datamode, $version))
 		;
 		;
 
 
 		$len = strlen($this->data);
 		$len = strlen($this->data);

+ 4 - 4
src/Data/Number.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
-use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Common\Mode;
 
 
 use function ceil, ord, sprintf, str_split, substr;
 use function ceil, ord, sprintf, str_split, substr;
 
 
@@ -32,7 +32,7 @@ final class Number extends QRDataModeAbstract{
 		'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
 		'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
 	];
 	];
 
 
-	protected array $lengthBits = [10, 12, 14];
+	protected int $datamode = Mode::DATA_NUMBER;
 
 
 	/**
 	/**
 	 * @inheritdoc
 	 * @inheritdoc
@@ -62,8 +62,8 @@ final class Number extends QRDataModeAbstract{
 		$len = $this->getCharCount();
 		$len = $this->getCharCount();
 
 
 		$bitBuffer
 		$bitBuffer
-			->put(QRCode::DATA_NUMBER, 4)
-			->put($len, $this->getLengthBitsForVersion($version))
+			->put($this->datamode, 4)
+			->put($len, Mode::getLengthBitsForVersion($this->datamode, $version))
 		;
 		;
 
 
 		$i = 0;
 		$i = 0;

+ 2 - 1
src/Data/QRData.php

@@ -14,6 +14,7 @@ namespace chillerlan\QRCode\Data;
 
 
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\Helpers\{BitBuffer, Polynomial};
 use chillerlan\QRCode\Helpers\{BitBuffer, Polynomial};
+use chillerlan\QRCode\Common\Mode;
 use chillerlan\Settings\SettingsContainerInterface;
 use chillerlan\Settings\SettingsContainerInterface;
 
 
 use function array_column, array_combine, array_fill, array_keys, array_merge, count, max, range, sprintf;
 use function array_column, array_combine, array_fill, array_keys, array_merge, count, max, range, sprintf;
@@ -221,7 +222,7 @@ class QRData{
 
 
 		foreach($this->dataSegments as $segment){
 		foreach($this->dataSegments as $segment){
 			// data length in bits of the current segment +4 bits for each mode descriptor
 			// data length in bits of the current segment +4 bits for each mode descriptor
-			$length += ($segment->getLengthInBits() + $segment->getLengthBits(0) + 4);
+			$length += ($segment->getLengthInBits() + Mode::LENGTH_BITS[$segment->getDataMode()][0] + 4);
 
 
 			if(!$segment instanceof ECI){
 			if(!$segment instanceof ECI){
 				// mode length bits margin to the next breakpoint
 				// mode length bits margin to the next breakpoint

+ 5 - 26
src/Data/QRDataModeAbstract.php

@@ -12,18 +12,14 @@
 
 
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
-use chillerlan\QRCode\Helpers\BitBuffer;
-
 /**
 /**
  */
  */
 abstract class QRDataModeAbstract implements QRDataModeInterface{
 abstract class QRDataModeAbstract implements QRDataModeInterface{
 
 
 	/**
 	/**
-	 * mode length bits for the version breakpoints 1-9, 10-26 and 27-40
-	 *
-	 * ISO/IEC 18004:2000 Table 3 - Number of bits in Character Count Indicator
+	 * the current data mode: Num, Alphanum, Kanji, Byte
 	 */
 	 */
-	protected array $lengthBits = [0, 0, 0];
+	protected int $datamode;
 
 
 	/**
 	/**
 	 * The data to write
 	 * The data to write
@@ -34,7 +30,7 @@ abstract class QRDataModeAbstract implements QRDataModeInterface{
 	 * QRDataModeAbstract constructor.
 	 * QRDataModeAbstract constructor.
 	 */
 	 */
 	public function __construct(string $data){
 	public function __construct(string $data){
-		$this->data      = $data;
+		$this->data = $data;
 	}
 	}
 
 
 	/**
 	/**
@@ -47,25 +43,8 @@ abstract class QRDataModeAbstract implements QRDataModeInterface{
 	/**
 	/**
 	 * @inheritDoc
 	 * @inheritDoc
 	 */
 	 */
-	public function getLengthBits(int $k):int{
-		return $this->lengthBits[$k] ?? 0;
-	}
-
-	/**
-	 * returns the length bits for the version breakpoints 1-9, 10-26 and 27-40
-	 *
-	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
-	 * @codeCoverageIgnore
-	 */
-	protected function getLengthBitsForVersion(int $version):int{
-
-		foreach([9, 26, 40] as $key => $breakpoint){
-			if($version <= $breakpoint){
-				return $this->getLengthBits($key);
-			}
-		}
-
-		throw new QRCodeDataException(sprintf('invalid version number: %d', $version));
+	public function getDataMode():int{
+		return $this->datamode;
 	}
 	}
 
 
 }
 }

+ 2 - 2
src/Data/QRDataModeInterface.php

@@ -21,9 +21,9 @@ use chillerlan\QRCode\Helpers\BitBuffer;
 interface QRDataModeInterface{
 interface QRDataModeInterface{
 
 
 	/**
 	/**
-	 * returns the length bits for the given breakpoint [0,1,2]
+	 * returns the current data mode constant
 	 */
 	 */
-	public function getLengthBits(int $k):int;
+	public function getDataMode():int;
 
 
 	/**
 	/**
 	 * retruns the length in bits of the data string
 	 * retruns the length in bits of the data string

+ 2 - 26
src/QRCode.php

@@ -13,6 +13,7 @@
 namespace chillerlan\QRCode;
 namespace chillerlan\QRCode;
 
 
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, MaskPatternTester, Number, QRData, QRCodeDataException, QRMatrix};
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, MaskPatternTester, Number, QRData, QRCodeDataException, QRMatrix};
+use chillerlan\QRCode\Common\Mode;
 use chillerlan\QRCode\Output\{
 use chillerlan\QRCode\Output\{
 	QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString
 	QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString
 };
 };
@@ -36,19 +37,6 @@ class QRCode{
 	/** @var int */
 	/** @var int */
 	public const MASK_PATTERN_AUTO  = -1;
 	public const MASK_PATTERN_AUTO  = -1;
 
 
-	// ISO/IEC 18004:2000 Table 2
-
-	/** @var int */
-	public const DATA_NUMBER   = 0b0001;
-	/** @var int */
-	public const DATA_ALPHANUM = 0b0010;
-	/** @var int */
-	public const DATA_BYTE     = 0b0100;
-	/** @var int */
-	public const DATA_KANJI    = 0b1000;
-	/** @var int */
-	public const DATA_ECI      = 0b0111;
-
 	// ISO/IEC 18004:2000 Tables 12, 25
 	// ISO/IEC 18004:2000 Tables 12, 25
 
 
 	/** @var int */
 	/** @var int */
@@ -124,18 +112,6 @@ class QRCode{
 		],
 		],
 	];
 	];
 
 
-	/**
-	 * Map of data mode => interface (detection order)
-	 *
-	 * @var string[]
-	 */
-	protected const DATA_INTERFACES = [
-		self::DATA_NUMBER   => Number::class,
-		self::DATA_ALPHANUM => AlphaNum::class,
-		self::DATA_KANJI    => Kanji::class,
-		self::DATA_BYTE     => Byte::class,
-	];
-
 	/**
 	/**
 	 * A collection of one or more data segments of [classname, data] to write
 	 * A collection of one or more data segments of [classname, data] to write
 	 *
 	 *
@@ -175,7 +151,7 @@ class QRCode{
 
 
 		if($data !== null){
 		if($data !== null){
 			/** @var \chillerlan\QRCode\Data\QRDataModeInterface $dataInterface */
 			/** @var \chillerlan\QRCode\Data\QRDataModeInterface $dataInterface */
-			foreach($this::DATA_INTERFACES as $dataInterface){
+			foreach(Mode::DATA_INTERFACES as $dataInterface){
 
 
 				if($dataInterface::validateString($data)){
 				if($dataInterface::validateString($data)){
 					$this->addSegment($data, $dataInterface);
 					$this->addSegment($data, $dataInterface);

+ 5 - 5
tests/Helpers/BitBufferTest.php

@@ -12,8 +12,8 @@
 
 
 namespace chillerlan\QRCodeTest\Helpers;
 namespace chillerlan\QRCodeTest\Helpers;
 
 
-use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\Helpers\BitBuffer;
 use chillerlan\QRCode\Helpers\BitBuffer;
+use chillerlan\QRCode\Common\Mode;
 use PHPUnit\Framework\TestCase;
 use PHPUnit\Framework\TestCase;
 
 
 /**
 /**
@@ -29,10 +29,10 @@ final class BitBufferTest extends TestCase{
 
 
 	public function bitProvider():array{
 	public function bitProvider():array{
 		return [
 		return [
-			'number'   => [QRCode::DATA_NUMBER, 16],
-			'alphanum' => [QRCode::DATA_ALPHANUM, 32],
-			'byte'     => [QRCode::DATA_BYTE, 64],
-			'kanji'    => [QRCode::DATA_KANJI, 128],
+			'number'   => [Mode::DATA_NUMBER, 16],
+			'alphanum' => [Mode::DATA_ALPHANUM, 32],
+			'byte'     => [Mode::DATA_BYTE, 64],
+			'kanji'    => [Mode::DATA_KANJI, 128],
 		];
 		];
 	}
 	}