From 99084fcb9f2a30e17895bded65177334b3605857 Mon Sep 17 00:00:00 2001 From: smiley Date: Wed, 24 Feb 2016 02:49:53 +0100 Subject: [PATCH] optimization and cleanup --- src/BitBuffer.php | 5 +- src/Data/Byte.php | 4 +- src/Data/QRDataBase.php | 4 +- src/Output/QRImage.php | 9 ++-- src/Output/QROutputInterface.php | 1 - src/Output/QRString.php | 81 ++++++++++++++------------------ src/Polynomial.php | 16 +++++-- src/QRCode.php | 66 ++++++++++++++------------ src/Util.php | 66 ++++++++++++++------------ 9 files changed, 133 insertions(+), 119 deletions(-) diff --git a/src/BitBuffer.php b/src/BitBuffer.php index e3f445579..b8dfc22b6 100644 --- a/src/BitBuffer.php +++ b/src/BitBuffer.php @@ -41,8 +41,9 @@ class BitBuffer{ */ public function put($num, $length){ - for($i = 0; $i < $length; $i++){ - $this->putBit(($num >> ($length - $i - 1))&1 === 1); + $i = 0; + while($i < $length){ + $this->putBit(($num >> ($length - $i - 1))&1 === 1); $i++; } } diff --git a/src/Data/Byte.php b/src/Data/Byte.php index 97f758f39..f570b6334 100644 --- a/src/Data/Byte.php +++ b/src/Data/Byte.php @@ -34,8 +34,10 @@ class Byte extends QRDataBase implements QRDataInterface{ * @param \chillerlan\QRCode\BitBuffer $buffer */ public function write(BitBuffer &$buffer){ - for($i = 0; $i < $this->dataLength; $i++){ + $i = 0; + while($i < $this->dataLength){ $buffer->put(ord($this->data[$i]), 8); + $i++; } } diff --git a/src/Data/QRDataBase.php b/src/Data/QRDataBase.php index 910ca12a7..867056a0e 100644 --- a/src/Data/QRDataBase.php +++ b/src/Data/QRDataBase.php @@ -11,6 +11,7 @@ */ namespace chillerlan\QRCode\Data; +use chillerlan\QRCode\QRCode; /** * @@ -47,7 +48,8 @@ class QRDataBase{ * * @return int * @throws \chillerlan\QRCode\Data\QRCodeDataException - * @codeCoverageIgnore not used in the code but may be useful to others + * @see QRCode::createData() + * @codeCoverageIgnore */ public function getLengthInBits($type){ diff --git a/src/Output/QRImage.php b/src/Output/QRImage.php index bca1c8e0c..e1081e992 100644 --- a/src/Output/QRImage.php +++ b/src/Output/QRImage.php @@ -38,7 +38,7 @@ class QRImage extends QROutputBase implements QROutputInterface{ $this->options->pixelSize = max(1, min(25, (int)$this->options->pixelSize)); $this->options->marginSize = max(0, min(25, (int)$this->options->marginSize)); - foreach(['fgRed', 'fgGreen', 'fgBlue', 'bgRed', 'bgGreen', 'bgBlue',] as $val){ + foreach(['fgRed', 'fgGreen', 'fgBlue', 'bgRed', 'bgGreen', 'bgBlue'] as $val){ $this->options->{$val} = max(0, min(255, (int)$this->options->{$val})); } @@ -60,7 +60,6 @@ class QRImage extends QROutputBase implements QROutputInterface{ /** * @return string - * @throws \chillerlan\QRCode\Output\QRCodeOutputException */ public function dump(){ $length = $this->pixelCount * $this->options->pixelSize + $this->options->marginSize * 2; @@ -74,9 +73,9 @@ class QRImage extends QROutputBase implements QROutputInterface{ imagefilledrectangle($image, 0, 0, $length, $length, $background); - for($r = 0; $r < $this->pixelCount; $r++){ - for($c = 0; $c < $this->pixelCount; $c++){ - if($this->matrix[$r][$c]){ + foreach($this->matrix as $r => $row){ + foreach($row as $c => $pixel){ + if($pixel){ imagefilledrectangle($image, $this->options->marginSize + $c * $this->options->pixelSize, $this->options->marginSize + $r * $this->options->pixelSize, diff --git a/src/Output/QROutputInterface.php b/src/Output/QROutputInterface.php index 2d9d9a409..20046ceaa 100644 --- a/src/Output/QROutputInterface.php +++ b/src/Output/QROutputInterface.php @@ -19,7 +19,6 @@ interface QROutputInterface{ /** * @return mixed - * @throws \chillerlan\QRCode\Output\QRCodeOutputException */ public function dump(); diff --git a/src/Output/QRString.php b/src/Output/QRString.php index 23122a912..940083474 100644 --- a/src/Output/QRString.php +++ b/src/Output/QRString.php @@ -11,6 +11,7 @@ */ namespace chillerlan\QRCode\Output; +use chillerlan\QRCode\Data\QRCodeDataException; use chillerlan\QRCode\QRCode; /** @@ -42,67 +43,53 @@ class QRString extends QROutputBase implements QROutputInterface{ /** * @return string - * @throws \chillerlan\QRCode\Output\QRCodeOutputException */ public function dump(){ - return call_user_func([$this, [ - QRCode::OUTPUT_STRING_TEXT => 'toText', - QRCode::OUTPUT_STRING_JSON => 'toJSON', - QRCode::OUTPUT_STRING_HTML => 'toHTML', - ][$this->options->type]]); - } - /** - * @return string - */ - public function toText(){ - $text = ''; - - foreach($this->matrix as &$row){ - foreach($row as &$col){ - $text .= $col - ? $this->options->textDark - : $this->options->textLight; - } - - $text .= $this->options->textNewline; + if($this->options->type === QRCode::OUTPUT_STRING_JSON){ + return json_encode($this->matrix); } - return $text; - } + else if($this->options->type === QRCode::OUTPUT_STRING_TEXT){ + $text = ''; - /** - * @return string - */ - public function toJSON(){ - return json_encode($this->matrix); - } + foreach($this->matrix as $row){ + foreach($row as $col){ + $text .= $col + ? $this->options->textDark + : $this->options->textLight; + } - /** - * @return string - */ - public function toHTML(){ - $html = ''; + $text .= $this->options->textNewline; + } - foreach($this->matrix as &$row){ - // in order to not bloat the output too much, we use the shortest possible valid HTML tags - $html .= '<'.$this->options->htmlRowTag.'>'; - foreach($row as &$col){ - $tag = $col - ? 'b' // dark - : 'i'; // light + return $text; + } + + else if($this->options->type === QRCode::OUTPUT_STRING_HTML){ + $html = ''; + + foreach($this->matrix as $row){ + // in order to not bloat the output too much, we use the shortest possible valid HTML tags + $html .= '<'.$this->options->htmlRowTag.'>'; + foreach($row as $col){ + $tag = $col + ? 'b' // dark + : 'i'; // light $html .= '<'.$tag.'>'; + } + + if(!(bool)$this->options->htmlOmitEndTag){ + $html .= 'options->htmlRowTag.'>'; + } + + $html .= PHP_EOL; } - if(!(bool)$this->options->htmlOmitEndTag){ - $html .= 'options->htmlRowTag.'>'; - } - - $html .= PHP_EOL; + return $html; } - return $html; } } diff --git a/src/Polynomial.php b/src/Polynomial.php index 71ae4bc16..0fa85bd4d 100644 --- a/src/Polynomial.php +++ b/src/Polynomial.php @@ -58,8 +58,10 @@ class Polynomial{ $this->num = array_fill(0, $numCount - $offset + $shift, 0); - for($i = 0; $i < $numCount - $offset; $i++){ + $i = 0; + while($i < $numCount - $offset){ $this->num[$i] = $num[$i + $offset]; + $i++; } return $this; @@ -71,16 +73,22 @@ class Polynomial{ protected function setTables(){ $this->EXP_TABLE = $this->LOG_TABLE = array_fill(0, 256, 0); - for($i = 0; $i < 8; $i++){ + $i = 0; + while($i < 8){ $this->EXP_TABLE[$i] = 1 << $i; + $i++; } - for($i = 8; $i < 256; $i++){ + $i = 8; + while($i < 256){ $this->EXP_TABLE[$i] = $this->EXP_TABLE[$i - 4] ^ $this->EXP_TABLE[$i - 5] ^ $this->EXP_TABLE[$i - 6] ^ $this->EXP_TABLE[$i - 8]; + $i++; } - for($i = 0; $i < 255; $i++){ + $i = 0; + while($i < 255){ $this->LOG_TABLE[$this->EXP_TABLE[$i]] = $i; + $i++; } } diff --git a/src/QRCode.php b/src/QRCode.php index b52732476..8e32df265 100644 --- a/src/QRCode.php +++ b/src/QRCode.php @@ -144,7 +144,6 @@ class QRCode{ ][$mode]; $this->qrDataInterface = new $qrDataInterface($data); - $this->typeNumber = intval($options->typeNumber); if($this->typeNumber < 1 || $this->typeNumber > 10){ @@ -191,7 +190,7 @@ class QRCode{ $minLostPoint = 0; $maskPattern = 0; - for($pattern = 0; $pattern <= 7; $pattern++){ + foreach(range(0, 7) as $pattern){ $this->getMatrix(true, $pattern); $lostPoint = 0; $darkCount = 0; @@ -199,19 +198,18 @@ class QRCode{ $range1 = range(0, $this->pixelCount-1); $range2 = range(0, $this->pixelCount-2); $range3 = range(0, $this->pixelCount-7); - $range4 = range(-1, 1); // LEVEL1 foreach($range1 as $row){ foreach($range1 as $col){ $sameCount = 0; - foreach($range4 as $rr){ + foreach([-1, 0, 1] as $rr){ if($row + $rr < 0 || $this->pixelCount <= $row + $rr){ continue; } - foreach($range4 as $cr){ + foreach([-1, 0, 1] as $cr){ if(($rr === 0 && $cr === 0) || ($col + $cr < 0 || $this->pixelCount <= $col + $cr)){ continue; @@ -311,7 +309,7 @@ class QRCode{ protected function setTypeNumber($test){ $bits = Util::getBCHTypeNumber($this->typeNumber); - for($i = 0; $i < 18; $i++){ + foreach(range(0, 17) as $i){ $a = (int)floor($i / 3); $b = $i % 3 + $this->pixelCount - 8 - 3; @@ -328,7 +326,7 @@ class QRCode{ $this->setPattern(); $bits = Util::getBCHTypeInfo(($this->errorCorrectLevel << 3) | $pattern); - for($i = 0; $i < 15; $i++){ + foreach(range(0, 14) as $i){ $mod = !$test && (($bits >> $i) & 1) === 1; switch(true){ @@ -355,20 +353,18 @@ class QRCode{ */ protected function createData(){ $this->bitBuffer->clear(); - - $MAX_BITS = QRConst::MAX_BITS; // php5 compat - $MAX_BITS = $MAX_BITS[$this->typeNumber][$this->errorCorrectLevel]; - - /** @noinspection PhpUndefinedFieldInspection */ $this->bitBuffer->put($this->qrDataInterface->mode, 4); - /** @noinspection PhpUndefinedFieldInspection */ $this->bitBuffer->put( - $this->qrDataInterface->mode === QRConst::MODE_KANJI ? floor($this->qrDataInterface->dataLength / 2) : $this->qrDataInterface->dataLength, + $this->qrDataInterface->mode === QRConst::MODE_KANJI + ? floor($this->qrDataInterface->dataLength / 2) + : $this->qrDataInterface->dataLength, $this->qrDataInterface->getLengthInBits($this->typeNumber) ); $this->qrDataInterface->write($this->bitBuffer); + $MAX_BITS = QRConst::MAX_BITS[$this->typeNumber][$this->errorCorrectLevel]; + if($this->bitBuffer->length > $MAX_BITS){ throw new QRCodeException('code length overflow. ('.$this->bitBuffer->length.' > '.$MAX_BITS.'bit)'); } @@ -430,9 +426,11 @@ class QRCode{ $rsPoly = new Polynomial; $modPoly = new Polynomial; - foreach(range(0, $rsBlockTotal - $rsBlockDataCount - 1) as $i){ + $i = 0; + while($i < $rsBlockTotal - $rsBlockDataCount){ $modPoly->setNum([1, $modPoly->gexp($i)]); $rsPoly->multiply($modPoly->num); + $i++; } $rsPolyCount = count($rsPoly->num); @@ -451,20 +449,24 @@ class QRCode{ $data = array_fill(0, $totalCodeCount, null); $rsrange = range(0, $rsBlockCount - 1); - foreach(range(0, $maxDcCount - 1) as $i){ + $i = 0; + while($i < $maxDcCount){ foreach($rsrange as $key){ if($i < count($dcdata[$key])){ $data[$index++] = $dcdata[$key][$i]; } } + $i++; } - foreach(range(0, $maxEcCount - 1) as $i){ + $i = 0; + while($i < $maxEcCount){ foreach($rsrange as $key){ if($i < count($ecdata[$key])){ $data[$index++] = $ecdata[$key][$i]; } } + $i++; } return $data; @@ -490,7 +492,8 @@ class QRCode{ } while(true){ - foreach([0, 1] as $c){ + $c = 0; + while($c < 2){ $_col = $col - $c; if($this->matrix[$row][$_col] === null){ @@ -525,6 +528,7 @@ class QRCode{ $bitIndex = 7; } } + $c++; } $row += $inc; @@ -542,15 +546,18 @@ class QRCode{ * @throws \chillerlan\QRCode\QRCodeException */ protected function setPattern(){ + $range1 = range(-1, 7); + $range2 = QRConst::PATTERN_POSITION[$this->typeNumber - 1]; + $range3 = range(8, $this->pixelCount - 8); // setupPositionProbePattern - $range = range(-1, 7); foreach([[0, 0], [$this->pixelCount - 7, 0], [0, $this->pixelCount - 7]] as $grid){ $row = $grid[0]; $col = $grid[1]; - foreach($range as $r){ - foreach($range as $c){ + $r = -1; + while($r < 8){ + foreach($range1 as $c){ if($row + $r <= -1 || $this->pixelCount <= $row + $r || $col + $c <= -1 || $this->pixelCount <= $col + $c){ continue; @@ -561,32 +568,33 @@ class QRCode{ || (0 <= $c && $c <= 6 && ($r === 0 || $r === 6)) || (2 <= $c && $c <= 4 && 2 <= $r && $r <= 4); } + $r++; } } // setupPositionAdjustPattern - $PATTERN_POSITION = QRConst::PATTERN_POSITION; // PHP5 compat - $pos = $PATTERN_POSITION[$this->typeNumber - 1]; - $range = range(-2, 2); - foreach($pos as $i => $posI){ - foreach($pos as $j => $posJ){ + foreach($range2 as $i => $posI){ + foreach($range2 as $j => $posJ){ if($this->matrix[$posI][$posJ] !== null){ continue; } - foreach($range as $row){ - foreach($range as $col){ + $row = $col = -2; + while($row < 2){ + while($col < 2){ $this->matrix[$posI + $row][$posJ + $col] = $row === -2 || $row === 2 || $col === -2 || $col === 2 ||($row === 0 && $col === 0); + $col++; } + $row++; } } } // setupTimingPattern - foreach(range(8, $this->pixelCount - 8) as $i){ + foreach($range3 as $i){ if($this->matrix[$i][6] !== null){ continue; // @codeCoverageIgnore } diff --git a/src/Util.php b/src/Util.php index cf2bf2d9e..def4a71a0 100644 --- a/src/Util.php +++ b/src/Util.php @@ -23,14 +23,17 @@ class Util{ * @return bool */ public static function isNumber($s){ - $len = strlen($s); - for($i = 0; $i < $len; $i++){ + $i = 0; + + while($i < $len){ $c = ord($s[$i]); if(!(ord('0') <= $c && $c <= ord('9'))){ return false; } + + $i++; } return true; @@ -42,14 +45,17 @@ class Util{ * @return bool */ public static function isAlphaNum($s){ - $len = strlen($s); - for($i = 0; $i < $len; $i++){ + $i = 0; + + while($i < $len){ $c = ord($s[$i]); if(!(ord('0') <= $c && $c <= ord('9')) && !(ord('A') <= $c && $c <= ord('Z')) && strpos(' $%*+-./:', $s[$i]) === false){ return false; } + + $i++; } return true; @@ -87,13 +93,7 @@ class Util{ * @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; + return (($data << 10)|self::getBCHT($data, 10, QRConst::G15))^QRConst::G15_MASK; } /** @@ -102,13 +102,24 @@ class Util{ * @return int */ public static function getBCHTypeNumber($data){ - $d = $data << 12; + return ($data << 12)|self::getBCHT($data, 12, QRConst::G18); + } - while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18) >= 0){ - $d ^= (QRConst::G18 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18))); + /** + * @param int $data + * @param int $bits + * @param int $mask + * + * @return int + */ + protected static function getBCHT($data, $bits, $mask){ + $d = $data << $bits; + + while(self::getBCHDigit($d) - self::getBCHDigit($mask) >= 0){ + $d ^= ($mask << (self::getBCHDigit($d) - self::getBCHDigit($mask))); } - return ($data << 12)|$d; + return $d; } /** @@ -135,22 +146,22 @@ class Util{ * @throws \chillerlan\QRCode\QRCodeException */ public static function getRSBlocks($typeNumber, $errorCorrectLevel){ - // PHP5 compat - $RSBLOCK = QRConst::RSBLOCK; - $BLOCK_TABLE = QRConst::BLOCK_TABLE; - if(!isset($RSBLOCK[$errorCorrectLevel])){ + if(!array_key_exists($errorCorrectLevel, QRConst::RSBLOCK)){ throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel); } - $rsBlock = $BLOCK_TABLE[($typeNumber - 1) * 4 + $RSBLOCK[$errorCorrectLevel]]; - + $rsBlock = QRConst::BLOCK_TABLE[($typeNumber - 1) * 4 + QRConst::RSBLOCK[$errorCorrectLevel]]; $list = []; $length = count($rsBlock) / 3; - for($i = 0; $i < $length; $i++){ - for($j = 0; $j < $rsBlock[$i * 3 + 0]; $j++){ + $i = $j = 0; + + while($i < $length){ + while($j < $rsBlock[$i * 3 + 0]){ $list[] = [$rsBlock[$i * 3 + 1], $rsBlock[$i * 3 + 2]]; + $j++; } + $i++; } return $list; @@ -165,19 +176,16 @@ class Util{ * @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])){ + if(!array_key_exists($ecLevel, QRConst::RSBLOCK)){ throw new QRCodeException('Invalid error correct level: '.$ecLevel); } - if(!isset($MODE[$mode])){ + if(!array_key_exists($mode, QRConst::MODE)){ throw new QRCodeException('Invalid mode: '.$mode); } - return $MAX_LENGTH[$typeNumber - 1][$RSBLOCK[$ecLevel]][$MODE[$mode]]; + return QRConst::MAX_LENGTH[$typeNumber - 1][QRConst::RSBLOCK[$ecLevel]][QRConst::MODE[$mode]]; }