aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php')
-rw-r--r--vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php116
1 files changed, 96 insertions, 20 deletions
diff --git a/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php b/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
index 28d9d7563..93ef9fc59 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
@@ -2,9 +2,7 @@
/**
* Class AlphaNum
*
- * @filesource AlphaNum.php
* @created 25.11.2015
- * @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
@@ -12,9 +10,8 @@
namespace chillerlan\QRCode\Data;
-use chillerlan\QRCode\QRCode;
-
-use function ord, sprintf;
+use chillerlan\QRCode\Common\{BitBuffer, Mode};
+use function ceil, intdiv, preg_match, strpos;
/**
* Alphanumeric mode: 0 to 9, A to Z, space, $ % * + - . / :
@@ -22,39 +19,118 @@ use function ord, sprintf;
* ISO/IEC 18004:2000 Section 8.3.3
* ISO/IEC 18004:2000 Section 8.4.3
*/
-final class AlphaNum extends QRDataAbstract{
+final class AlphaNum extends QRDataModeAbstract{
- protected int $datamode = QRCode::DATA_ALPHANUM;
+ /**
+ * ISO/IEC 18004:2000 Table 5
+ *
+ * @var string
+ */
+ private const CHAR_MAP = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';
- protected array $lengthBits = [9, 11, 13];
+ /**
+ * @inheritDoc
+ */
+ public const DATAMODE = Mode::ALPHANUM;
/**
- * @inheritdoc
+ * @inheritDoc
*/
- protected function write(string $data):void{
+ public function getLengthInBits():int{
+ return (int)ceil($this->getCharCount() * (11 / 2));
+ }
- for($i = 0; $i + 1 < $this->strlen; $i += 2){
- $this->bitBuffer->put($this->getCharCode($data[$i]) * 45 + $this->getCharCode($data[$i + 1]), 11);
+ /**
+ * @inheritDoc
+ */
+ public static function validateString(string $string):bool{
+ return (bool)preg_match('/^[A-Z\d %$*+-.:\/]+$/', $string);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function write(BitBuffer $bitBuffer, int $versionNumber):QRDataModeInterface{
+ $len = $this->getCharCount();
+
+ $bitBuffer
+ ->put(self::DATAMODE, 4)
+ ->put($len, $this::getLengthBits($versionNumber))
+ ;
+
+ // encode 2 characters in 11 bits
+ for($i = 0; ($i + 1) < $len; $i += 2){
+ $bitBuffer->put(
+ ($this->ord($this->data[$i]) * 45 + $this->ord($this->data[($i + 1)])),
+ 11,
+ );
}
- if($i < $this->strlen){
- $this->bitBuffer->put($this->getCharCode($data[$i]), 6);
+ // encode a remaining character in 6 bits
+ if($i < $len){
+ $bitBuffer->put($this->ord($this->data[$i]), 6);
}
+ return $this;
}
/**
- * get the code for the given character
+ * @inheritDoc
*
- * @throws \chillerlan\QRCode\Data\QRCodeDataException on an illegal character occurence
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException
+ */
+ public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):string{
+ $length = $bitBuffer->read(self::getLengthBits($versionNumber));
+ $result = '';
+ // Read two characters at a time
+ while($length > 1){
+
+ if($bitBuffer->available() < 11){
+ throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
+ }
+
+ $nextTwoCharsBits = $bitBuffer->read(11);
+ $result .= self::chr(intdiv($nextTwoCharsBits, 45));
+ $result .= self::chr($nextTwoCharsBits % 45);
+ $length -= 2;
+ }
+
+ if($length === 1){
+ // special case: one character left
+ if($bitBuffer->available() < 6){
+ throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
+ }
+
+ $result .= self::chr($bitBuffer->read(6));
+ }
+
+ return $result;
+ }
+
+ /**
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException
+ */
+ private function ord(string $chr):int{
+ /** @phan-suppress-next-line PhanParamSuspiciousOrder */
+ $ord = strpos(self::CHAR_MAP, $chr);
+
+ if($ord === false){
+ throw new QRCodeDataException('invalid character'); // @codeCoverageIgnore
+ }
+
+ return $ord;
+ }
+
+ /**
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
- protected function getCharCode(string $chr):int{
+ private static function chr(int $ord):string{
- if(!isset($this::CHAR_MAP_ALPHANUM[$chr])){
- throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, ord($chr)));
+ if($ord < 0 || $ord > 44){
+ throw new QRCodeDataException('invalid character code'); // @codeCoverageIgnore
}
- return $this::CHAR_MAP_ALPHANUM[$chr];
+ return self::CHAR_MAP[$ord];
}
}