mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-08-24 15:17:55 +00:00
refactoring
This commit is contained in:
+38
-3
@@ -13,14 +13,26 @@
|
||||
namespace chillerlan\QRCode\Data;
|
||||
|
||||
use chillerlan\QRCode\BitBuffer;
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use chillerlan\QRCode\QRConst;
|
||||
use chillerlan\QRCode\Util;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class AlphaNum extends QRDataBase implements QRDataInterface{
|
||||
|
||||
const CHAR_MAP = [
|
||||
36 => ' ',
|
||||
37 => '$',
|
||||
38 => '%',
|
||||
39 => '*',
|
||||
40 => '+',
|
||||
41 => '-',
|
||||
42 => '.',
|
||||
43 => '/',
|
||||
44 => ':',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
@@ -38,14 +50,37 @@ class AlphaNum extends QRDataBase implements QRDataInterface{
|
||||
$i = 0;
|
||||
|
||||
while($i + 1 < $this->dataLength){
|
||||
$buffer->put(Util::getCharCode($this->data[$i]) * 45 + Util::getCharCode($this->data[$i + 1]), 11);
|
||||
$buffer->put($this->getCharCode($this->data[$i]) * 45 + $this->getCharCode($this->data[$i + 1]), 11);
|
||||
$i += 2;
|
||||
}
|
||||
|
||||
if($i < $this->dataLength){
|
||||
$buffer->put(Util::getCharCode($this->data[$i]), 6);
|
||||
$buffer->put($this->getCharCode($this->data[$i]), 6);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $c
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
private static function getCharCode($c){
|
||||
$c = ord($c);
|
||||
|
||||
switch(true){
|
||||
case ord('0') <= $c && $c <= ord('9'): return $c - ord('0');
|
||||
case ord('A') <= $c && $c <= ord('Z'): return $c - ord('A') + 10;
|
||||
default:
|
||||
foreach(self::CHAR_MAP as $i => $char){
|
||||
if(ord($char) === $c){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new QRCodeException('illegal char: '.$c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-4
@@ -13,8 +13,8 @@
|
||||
namespace chillerlan\QRCode\Data;
|
||||
|
||||
use chillerlan\QRCode\BitBuffer;
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use chillerlan\QRCode\QRConst;
|
||||
use chillerlan\QRCode\Util;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -38,21 +38,48 @@ class Number extends QRDataBase implements QRDataInterface{
|
||||
$i = 0;
|
||||
|
||||
while($i + 2 < $this->dataLength){
|
||||
$buffer->put(Util::parseInt(substr($this->data, $i, 3)), 10);
|
||||
$buffer->put($this->parseInt(substr($this->data, $i, 3)), 10);
|
||||
$i += 3;
|
||||
}
|
||||
|
||||
if($i < $this->dataLength){
|
||||
|
||||
if($this->dataLength - $i === 1){
|
||||
$buffer->put(Util::parseInt(substr($this->data, $i, $i + 1)), 4);
|
||||
$buffer->put($this->parseInt(substr($this->data, $i, $i + 1)), 4);
|
||||
}
|
||||
else if($this->dataLength - $i === 2){
|
||||
$buffer->put(Util::parseInt(substr($this->data, $i, $i + 2)), 7);
|
||||
$buffer->put($this->parseInt(substr($this->data, $i, $i + 2)), 7);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
private static function parseInt($string){
|
||||
$num = 0;
|
||||
|
||||
$len = strlen($string);
|
||||
for($i = 0; $i < $len; $i++){
|
||||
$c = ord($string[$i]);
|
||||
$ord0 = ord('0');
|
||||
|
||||
if($ord0 <= $c && $c <= ord('9')){
|
||||
$c = $c - $ord0;
|
||||
}
|
||||
else{
|
||||
throw new QRCodeException('illegal char: '.$c);
|
||||
}
|
||||
|
||||
$num = $num * 10 + $c;
|
||||
}
|
||||
|
||||
return $num;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+116
-5
@@ -16,6 +16,7 @@ use chillerlan\QRCode\Output\QROutputInterface;
|
||||
|
||||
/**
|
||||
* @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
|
||||
* @link http://www.thonky.com/qr-code-tutorial/
|
||||
*/
|
||||
class QRCode{
|
||||
|
||||
@@ -117,7 +118,18 @@ class QRCode{
|
||||
throw new QRCodeException('Invalid error correct level: '.$options->errorCorrectLevel);
|
||||
}
|
||||
|
||||
$mode = Util::getMode($data);
|
||||
switch(true){
|
||||
case Util::isAlphaNum($data):
|
||||
$mode = Util::isNumber($data) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM;
|
||||
break;
|
||||
case Util::isKanji($data) :
|
||||
$mode = QRConst::MODE_KANJI;
|
||||
break;
|
||||
default:
|
||||
$mode = QRConst::MODE_BYTE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$qrDataInterface = __NAMESPACE__.'\\Data\\'.[
|
||||
QRConst::MODE_ALPHANUM => 'AlphaNum',
|
||||
@@ -137,7 +149,7 @@ class QRCode{
|
||||
: $this->qrDataInterface->dataLength;
|
||||
|
||||
for($type = 1; $type <= 10; $type++){
|
||||
if($length <= Util::getMaxLength($type, $mode, $this->errorCorrectLevel)){
|
||||
if($length <= $this->getMaxLength($type, $mode, $this->errorCorrectLevel)){
|
||||
$this->typeNumber = $type;
|
||||
|
||||
return $this;
|
||||
@@ -281,13 +293,83 @@ class QRCode{
|
||||
return $this->matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
* @param int $mode
|
||||
* @param int $ecLevel
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
protected static function getMaxLength($typeNumber, $mode, $ecLevel){
|
||||
$RSBLOCK = QRConst::RSBLOCK;
|
||||
$MAX_LENGTH = QRConst::MAX_LENGTH;
|
||||
$MODE = QRConst::MODE;
|
||||
|
||||
if(!isset($RSBLOCK[$ecLevel])){
|
||||
throw new QRCodeException('$_err: '.$ecLevel);
|
||||
}
|
||||
|
||||
if(!isset($MODE[$mode])){
|
||||
throw new QRCodeException('$_mode: '.$mode);
|
||||
}
|
||||
|
||||
return $MAX_LENGTH[$typeNumber - 1][$RSBLOCK[$ecLevel]][$MODE[$mode]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected static function getBCHTypeInfo($data){
|
||||
$d = $data << 10;
|
||||
|
||||
while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15) >= 0){
|
||||
$d ^= (QRConst::G15 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15)));
|
||||
}
|
||||
|
||||
return (($data << 10)|$d)^QRConst::G15_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected static function getBCHTypeNumber($data){
|
||||
$d = $data << 12;
|
||||
|
||||
while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18) >= 0){
|
||||
$d ^= (QRConst::G18 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18)));
|
||||
}
|
||||
|
||||
return ($data << 12)|$d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected static function getBCHDigit($data){
|
||||
$digit = 0;
|
||||
|
||||
while($data !== 0){
|
||||
$digit++;
|
||||
$data >>= 1;
|
||||
}
|
||||
|
||||
return $digit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $test
|
||||
* @param int $pattern
|
||||
*/
|
||||
protected function setTypeInfo($test, $pattern){
|
||||
$this->setPattern();
|
||||
$bits = Util::getBCHTypeInfo(($this->errorCorrectLevel << 3) | $pattern);
|
||||
$bits = self::getBCHTypeInfo(($this->errorCorrectLevel << 3) | $pattern);
|
||||
|
||||
for($i = 0; $i < 15; $i++){
|
||||
$mod = !$test && (($bits >> $i) & 1) === 1;
|
||||
@@ -376,7 +458,7 @@ class QRCode{
|
||||
* @return $this
|
||||
*/
|
||||
protected function setTypeNumber($test){
|
||||
$bits = Util::getBCHTypeNumber($this->typeNumber);
|
||||
$bits = self::getBCHTypeNumber($this->typeNumber);
|
||||
|
||||
for($i = 0; $i < 18; $i++){
|
||||
$a = (int)floor($i / 3);
|
||||
@@ -540,13 +622,42 @@ class QRCode{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
* @param int $errorCorrectLevel
|
||||
*
|
||||
* @return array
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
protected static function getRSBlocks($typeNumber, $errorCorrectLevel){
|
||||
// PHP5 compat
|
||||
$RSBLOCK = QRConst::RSBLOCK;
|
||||
$BLOCK_TABLE = QRConst::BLOCK_TABLE;
|
||||
|
||||
if(!isset($RSBLOCK[$errorCorrectLevel])){
|
||||
throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel.PHP_EOL.print_r($RSBLOCK, true));
|
||||
}
|
||||
|
||||
$rsBlock = $BLOCK_TABLE[($typeNumber - 1) * 4 + $RSBLOCK[$errorCorrectLevel]];
|
||||
|
||||
$list = [];
|
||||
$length = count($rsBlock) / 3;
|
||||
for($i = 0; $i < $length; $i++){
|
||||
for($j = 0; $j < $rsBlock[$i * 3 + 0]; $j++){
|
||||
$list[] = [$rsBlock[$i * 3 + 1], $rsBlock[$i * 3 + 2]];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
protected function createBytes(){
|
||||
$totalCodeCount = $maxDcCount = $maxEcCount = $offset = $index = 0;
|
||||
$rsBlocks = Util::getRSBlocks($this->typeNumber, $this->errorCorrectLevel);
|
||||
$rsBlocks = $this->getRSBlocks($this->typeNumber, $this->errorCorrectLevel);
|
||||
$rsBlockCount = count($rsBlocks);
|
||||
$dcdata = $ecdata = array_fill(0, $rsBlockCount, null);
|
||||
|
||||
|
||||
@@ -65,18 +65,6 @@ class QRConst{
|
||||
const PAD0 = 0xEC;
|
||||
const PAD1 = 0x11;
|
||||
|
||||
const CHAR_MAP = [
|
||||
36 => ' ',
|
||||
37 => '$',
|
||||
38 => '%',
|
||||
39 => '*',
|
||||
40 => '+',
|
||||
41 => '-',
|
||||
42 => '.',
|
||||
43 => '/',
|
||||
44 => ':',
|
||||
];
|
||||
|
||||
const MAX_LENGTH = [
|
||||
[[ 41, 25, 17, 10], [ 34, 20, 14, 8], [ 27, 16, 11, 7], [ 17, 10, 7, 4]],
|
||||
[[ 77, 47, 32, 20], [ 63, 38, 26, 16], [ 48, 29, 20, 12], [ 34, 20, 14, 8]],
|
||||
|
||||
-165
@@ -17,75 +17,6 @@ namespace chillerlan\QRCode;
|
||||
*/
|
||||
class Util{
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
* @param int $errorCorrectLevel
|
||||
*
|
||||
* @return array
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
public static function getRSBlocks($typeNumber, $errorCorrectLevel){
|
||||
// PHP5 compat
|
||||
$RSBLOCK = QRConst::RSBLOCK;
|
||||
$BLOCK_TABLE = QRConst::BLOCK_TABLE;
|
||||
|
||||
if(!isset($RSBLOCK[$errorCorrectLevel])){
|
||||
throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel.PHP_EOL.print_r($RSBLOCK, true));
|
||||
}
|
||||
|
||||
$rsBlock = $BLOCK_TABLE[($typeNumber - 1) * 4 + $RSBLOCK[$errorCorrectLevel]];
|
||||
|
||||
$list = [];
|
||||
$length = count($rsBlock) / 3;
|
||||
for($i = 0; $i < $length; $i++){
|
||||
for($j = 0; $j < $rsBlock[$i * 3 + 0]; $j++){
|
||||
$list[] = [$rsBlock[$i * 3 + 1], $rsBlock[$i * 3 + 2]];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $typeNumber
|
||||
* @param int $mode
|
||||
* @param int $ecLevel
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
public static function getMaxLength($typeNumber, $mode, $ecLevel){
|
||||
$RSBLOCK = QRConst::RSBLOCK;
|
||||
$MAX_LENGTH = QRConst::MAX_LENGTH;
|
||||
$MODE = QRConst::MODE;
|
||||
|
||||
if(!isset($RSBLOCK[$ecLevel])){
|
||||
throw new QRCodeException('$_err: '.$ecLevel);
|
||||
}
|
||||
|
||||
if(!isset($MODE[$mode])){
|
||||
throw new QRCodeException('$_mode: '.$mode);
|
||||
}
|
||||
|
||||
return $MAX_LENGTH[$typeNumber - 1][$RSBLOCK[$ecLevel]][$MODE[$mode]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getMode($s){
|
||||
|
||||
switch(true){
|
||||
case self::isAlphaNum($s): return self::isNumber($s) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM;
|
||||
case self::isKanji($s) : return QRConst::MODE_KANJI;
|
||||
default:
|
||||
return QRConst::MODE_BYTE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $s
|
||||
*
|
||||
@@ -150,100 +81,4 @@ class Util{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getBCHTypeInfo($data){
|
||||
$d = $data << 10;
|
||||
|
||||
while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15) >= 0){
|
||||
$d ^= (QRConst::G15 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15)));
|
||||
}
|
||||
|
||||
return (($data << 10)|$d)^QRConst::G15_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getBCHTypeNumber($data){
|
||||
$d = $data << 12;
|
||||
|
||||
while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18) >= 0){
|
||||
$d ^= (QRConst::G18 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18)));
|
||||
}
|
||||
|
||||
return ($data << 12)|$d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $data
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getBCHDigit($data){
|
||||
$digit = 0;
|
||||
|
||||
while($data !== 0){
|
||||
$digit++;
|
||||
$data >>= 1;
|
||||
}
|
||||
|
||||
return $digit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $c
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
public static function getCharCode($c){
|
||||
$c = ord($c);
|
||||
|
||||
switch(true){
|
||||
case ord('0') <= $c && $c <= ord('9'): return $c - ord('0');
|
||||
case ord('A') <= $c && $c <= ord('Z'): return $c - ord('A') + 10;
|
||||
default:
|
||||
foreach(QRConst::CHAR_MAP as $i => $char){
|
||||
if(ord($char) === $c){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new QRCodeException('illegal char: '.$c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return int
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
public static function parseInt($string){
|
||||
$num = 0;
|
||||
|
||||
$len = strlen($string);
|
||||
for($i = 0; $i < $len; $i++){
|
||||
$c = ord($string[$i]);
|
||||
$ord0 = ord('0');
|
||||
|
||||
if($ord0 <= $c && $c <= ord('9')){
|
||||
$c = $c - $ord0;
|
||||
}
|
||||
else{
|
||||
throw new QRCodeException('illegal char: '.$c);
|
||||
}
|
||||
|
||||
$num = $num * 10 + $c;
|
||||
}
|
||||
|
||||
return $num;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user