diff options
Diffstat (limited to 'vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php')
-rw-r--r-- | vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php | 116 |
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]; } } |