🚿 replaced generic exceptions

This commit is contained in:
codemasher
2021-12-02 00:18:51 +01:00
parent 05917f7286
commit 21b414cab0
11 changed files with 79 additions and 56 deletions
+2 -3
View File
@@ -11,7 +11,6 @@
namespace chillerlan\QRCode\Decoder;
use RuntimeException;
use function array_fill, count, max;
/**
@@ -55,7 +54,7 @@ final class Binarizer{
}
/**
* @throws \RuntimeException
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
private function estimateBlackPoint(array $buckets):int{
// Find the tallest peak in the histogram.
@@ -101,7 +100,7 @@ final class Binarizer{
// If there is too little contrast in the image to pick a meaningful black point, throw rather
// than waste time trying to decode the image, and risk false positives.
if($secondPeak - $firstPeak <= $numBuckets / 16){
throw new RuntimeException('no meaningful dark point found');
throw new QRCodeDecoderException('no meaningful dark point found');
}
// Find a valley between them that is low and closer to the white peak.
+14 -15
View File
@@ -12,7 +12,6 @@
namespace chillerlan\QRCode\Decoder;
use chillerlan\QRCode\Common\{FormatInformation, Version};
use InvalidArgumentException, RuntimeException;
use function array_fill, count;
use const PHP_INT_MAX, PHP_INT_SIZE;
@@ -74,23 +73,23 @@ final class BitMatrix{
* @param int $width ; The width of the region
* @param int $height ; The height of the region
*
* @throws \InvalidArgumentException
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
public function setRegion(int $left, int $top, int $width, int $height):self{
if($top < 0 || $left < 0){
throw new InvalidArgumentException('Left and top must be nonnegative');
throw new QRCodeDecoderException('Left and top must be non-negative');
}
if($height < 1 || $width < 1){
throw new InvalidArgumentException('Height and width must be at least 1');
throw new QRCodeDecoderException('Height and width must be at least 1');
}
$right = $left + $width;
$bottom = $top + $height;
if($bottom > $this->dimension || $right > $this->dimension){
throw new InvalidArgumentException('The region must fit inside the matrix');
throw new QRCodeDecoderException('The region must fit inside the matrix');
}
for($y = $top; $y < $bottom; $y++){
@@ -256,7 +255,7 @@ final class BitMatrix{
* QR Code.
*
* @return array bytes encoded within the QR Code
* @throws \RuntimeException if the exact number of bytes expected is not read
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if the exact number of bytes expected is not read
*/
public function readCodewords():array{
$this->formatInfo = $this->readFormatInformation();
@@ -308,7 +307,7 @@ final class BitMatrix{
}
if($resultOffset !== $this->version->getTotalCodewords()){
throw new RuntimeException('offset differs from total codewords for version');
throw new QRCodeDecoderException('offset differs from total codewords for version');
}
return $result;
@@ -317,9 +316,9 @@ final class BitMatrix{
/**
* Reads format information from one of its two locations within the QR Code.
*
* @return \chillerlan\QRCode\Common\FormatInformation encapsulating the QR Code's format info
* @throws \RuntimeException if both format information locations cannot be parsed as
* the valid encoding of format information
* @return \chillerlan\QRCode\Common\FormatInformation encapsulating the QR Code's format info
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if both format information locations cannot be parsed as
* the valid encoding of format information
*/
private function readFormatInformation():FormatInformation{
@@ -372,7 +371,7 @@ final class BitMatrix{
return $this->formatInfo;
}
throw new RuntimeException('failed to read format info');
throw new QRCodeDecoderException('failed to read format info');
}
/**
@@ -424,9 +423,9 @@ final class BitMatrix{
/**
* Reads version information from one of its two locations within the QR Code.
*
* @return \chillerlan\QRCode\Common\Version encapsulating the QR Code's version
* @throws \RuntimeException if both version information locations cannot be parsed as
* the valid encoding of version information
* @return \chillerlan\QRCode\Common\Version encapsulating the QR Code's version
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if both version information locations cannot be parsed as
* the valid encoding of version information
*/
private function readVersion():Version{
@@ -471,7 +470,7 @@ final class BitMatrix{
return $this->version;
}
throw new RuntimeException('failed to read version');
throw new QRCodeDecoderException('failed to read version');
}
/**
+10 -12
View File
@@ -11,7 +11,7 @@
namespace chillerlan\QRCode\Decoder;
use InvalidArgumentException, RuntimeException, Throwable;
use Throwable;
use chillerlan\QRCode\Common\{BitBuffer, EccLevel, Mode, ReedSolomonDecoder, Version};
use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number};
use chillerlan\QRCode\Detector\Detector;
@@ -33,8 +33,8 @@ final class Decoder{
*
* @param \chillerlan\QRCode\Decoder\LuminanceSourceInterface $source
*
* @return \chillerlan\QRCode\Decoder\DecoderResult text and bytes encoded within the QR Code
* @throws \Throwable if the QR Code cannot be decoded
* @return \chillerlan\QRCode\Decoder\DecoderResult text and bytes encoded within the QR Code
* @throws \Throwable|\chillerlan\QRCode\Decoder\QRCodeDecoderException if the QR Code cannot be decoded
*/
public function decode(LuminanceSourceInterface $source):DecoderResult{
$bitMatrix = (new Detector($source))->detect();
@@ -66,9 +66,7 @@ final class Decoder{
}
/**
* @param \chillerlan\QRCode\Decoder\BitMatrix $bitMatrix
*
* @return \chillerlan\QRCode\Decoder\DecoderResult
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
private function decodeMatrix(BitMatrix $bitMatrix):DecoderResult{
// Read raw codewords
@@ -78,7 +76,7 @@ final class Decoder{
// technically this shouldn't happen as the respective read meathods would throw first
if($version === null || $formatInfo === null){
throw new RuntimeException('unable to read version or ecc level');
throw new QRCodeDecoderException('unable to read version or ecc level');
}
$eccLevel = $formatInfo->getErrorCorrectionLevel();
@@ -114,12 +112,12 @@ final class Decoder{
* @param \chillerlan\QRCode\Common\EccLevel $eccLevel error-correction level of the QR Code
*
* @return array DataBlocks containing original bytes, "de-interleaved" from representation in the QR Code
* @throws \InvalidArgumentException
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
private function getDataBlocks(array $rawCodewords, Version $version, EccLevel $eccLevel):array{
if(count($rawCodewords) !== $version->getTotalCodewords()){
throw new InvalidArgumentException('$rawCodewords differ from total codewords for version');
throw new QRCodeDecoderException('$rawCodewords differ from total codewords for version');
}
// Figure out the number and size of data blocks used by this version and
@@ -210,7 +208,7 @@ final class Decoder{
}
/**
* @throws \RuntimeException
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
private function decodeBitStream(array $bytes, Version $version, EccLevel $ecLevel):DecoderResult{
$bits = new BitBuffer($bytes);
@@ -242,7 +240,7 @@ final class Decoder{
}
elseif($datamode === Mode::STRCTURED_APPEND){
if($bits->available() < 16){
throw new RuntimeException('structured append: not enough bits left');
throw new QRCodeDecoderException('structured append: not enough bits left');
}
// sequence number and parity is added later to the result metadata
// Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
@@ -312,7 +310,7 @@ final class Decoder{
$result .= Kanji::decodeSegment($bits, $versionNumber);
}
else{
throw new RuntimeException('invalid data mode');
throw new QRCodeDecoderException('invalid data mode');
}
# }
}
+2 -3
View File
@@ -13,7 +13,6 @@
namespace chillerlan\QRCode\Decoder;
use InvalidArgumentException;
use function file_get_contents, get_resource_type, imagecolorat, imagecolorsforindex,
imagecreatefromstring, imagesx, imagesy, is_resource;
use const PHP_MAJOR_VERSION;
@@ -34,7 +33,7 @@ final class GDLuminanceSource extends LuminanceSourceAbstract{
*
* @param resource|\GdImage $gdImage
*
* @throws \InvalidArgumentException
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
public function __construct($gdImage){
@@ -43,7 +42,7 @@ final class GDLuminanceSource extends LuminanceSourceAbstract{
(PHP_MAJOR_VERSION >= 8 && !$gdImage instanceof \GdImage)
|| (PHP_MAJOR_VERSION < 8 && (!is_resource($gdImage) || get_resource_type($gdImage) !== 'gd'))
){
throw new InvalidArgumentException('Invalid GD image source.');
throw new QRCodeDecoderException('Invalid GD image source.');
}
parent::__construct(imagesx($gdImage), imagesy($gdImage));
+4 -5
View File
@@ -11,7 +11,6 @@
namespace chillerlan\QRCode\Decoder;
use InvalidArgumentException;
use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
/**
@@ -59,7 +58,7 @@ abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
public function getRow(int $y):array{
if($y < 0 || $y >= $this->getHeight()){
throw new InvalidArgumentException('Requested row is outside the image: '.$y);
throw new QRCodeDecoderException('Requested row is outside the image: '.$y);
}
$arr = [];
@@ -81,19 +80,19 @@ abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
}
/**
*
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
protected static function checkFile(string $path):string{
$path = trim($path);
if(!file_exists($path) || !is_file($path) || !is_readable($path)){
throw new InvalidArgumentException('invalid file: '.$path);
throw new QRCodeDecoderException('invalid file: '.$path);
}
$realpath = realpath($path);
if($realpath === false){
throw new InvalidArgumentException('unable to resolve path: '.$path);
throw new QRCodeDecoderException('unable to resolve path: '.$path);
}
return $realpath;
+1
View File
@@ -44,6 +44,7 @@ interface LuminanceSourceInterface{
* @param int $y The row to fetch, which must be in [0,getHeight())
*
* @return array An array containing the luminance data.
* @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
*/
public function getRow(int $y):array;
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* Class QRCodeDecoderException
*
* @created 01.12.2021
* @author smiley <smiley@chillerlan.net>
* @copyright 2021 smiley
* @license MIT
*/
namespace chillerlan\QRCode\Decoder;
use chillerlan\QRCode\QRCodeException;
class QRCodeDecoderException extends QRCodeException{}
+5 -6
View File
@@ -12,7 +12,6 @@
namespace chillerlan\QRCode\Detector;
use chillerlan\QRCode\Decoder\{Binarizer, LuminanceSourceInterface};
use RuntimeException;
use chillerlan\QRCode\Common\Version;
use chillerlan\QRCode\Decoder\BitMatrix;
use function abs, is_nan, max, min, round;
@@ -78,7 +77,7 @@ final class Detector{
* Computes an average estimated module size based on estimated derived from the positions
* of the three finder patterns.
*
* @throws \RuntimeException
* @throws \chillerlan\QRCode\Detector\QRCodeDetectorException
*/
private function calculateModuleSize(FinderPattern $topLeft, FinderPattern $topRight, FinderPattern $bottomLeft):float{
// Take the average
@@ -88,7 +87,7 @@ final class Detector{
) / 2.0;
if($moduleSize < 1.0){
throw new RuntimeException('module size < 1.0');
throw new QRCodeDetectorException('module size < 1.0');
}
return $moduleSize;
@@ -244,7 +243,7 @@ final class Detector{
* Computes the dimension (number of modules on a size) of the QR Code based on the position
* of the finder patterns and estimated module size.
*
* @throws \RuntimeException
* @throws \chillerlan\QRCode\Detector\QRCodeDetectorException
*/
private function computeDimension(
FinderPattern $topLeft,
@@ -265,11 +264,11 @@ final class Detector{
$dimension--;
break;
case 3:
throw new RuntimeException('estimated dimension: '.$dimension);
throw new QRCodeDetectorException('estimated dimension: '.$dimension);
}
if($dimension % 4 !== 1){
throw new RuntimeException('dimension mod 4 is not 1');
throw new QRCodeDetectorException('dimension mod 4 is not 1');
}
return $dimension;
+3 -4
View File
@@ -13,7 +13,6 @@
namespace chillerlan\QRCode\Detector;
use RuntimeException;
use chillerlan\QRCode\Decoder\BitMatrix;
use function abs, count, usort;
use const PHP_FLOAT_MAX;
@@ -617,13 +616,13 @@ final class FinderPatternFinder{
* @return \chillerlan\QRCode\Detector\FinderPattern[] the 3 best FinderPatterns from our list of candidates. The "best" are
* those that have been detected at least #CENTER_QUORUM times, and whose module
* size differs from the average among those patterns the least
* @throws \RuntimeException if 3 such finder patterns do not exist
* @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if 3 such finder patterns do not exist
*/
private function selectBestPatterns():array{
$startSize = count($this->possibleCenters);
if($startSize < 3){
throw new RuntimeException('could not find enough finder patterns');
throw new QRCodeDetectorException('could not find enough finder patterns');
}
usort(
@@ -708,7 +707,7 @@ final class FinderPatternFinder{
}
if($distortion === PHP_FLOAT_MAX){
throw new RuntimeException('finder patterns may be too distorted');
throw new QRCodeDetectorException('finder patterns may be too distorted');
}
return $bestPatterns;
+8 -8
View File
@@ -11,8 +11,8 @@
namespace chillerlan\QRCode\Detector;
use Exception, RuntimeException;
use chillerlan\QRCode\Decoder\BitMatrix;
use Throwable;
use function array_fill, count, sprintf;
/**
@@ -44,7 +44,7 @@ final class GridSampler{
* @param \chillerlan\QRCode\Decoder\BitMatrix $bitMatrix image into which the points should map
* @param float[] $points actual points in x1,y1,...,xn,yn form
*
* @throws \RuntimeException if an endpoint is lies outside the image boundaries
* @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if an endpoint is lies outside the image boundaries
*/
private function checkAndNudgePoints(BitMatrix $bitMatrix, array $points):void{
$dimension = $bitMatrix->getDimension();
@@ -57,7 +57,7 @@ final class GridSampler{
$y = (int)$points[$offset + 1];
if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
throw new RuntimeException(sprintf('checkAndNudgePoints 1, x: %s, y: %s, d: %s', $x, $y, $dimension));
throw new QRCodeDetectorException(sprintf('checkAndNudgePoints 1, x: %s, y: %s, d: %s', $x, $y, $dimension));
}
$nudged = false;
@@ -87,7 +87,7 @@ final class GridSampler{
$y = (int)$points[$offset + 1];
if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
throw new RuntimeException(sprintf('checkAndNudgePoints 2, x: %s, y: %s, d: %s', $x, $y, $dimension));
throw new QRCodeDetectorException(sprintf('checkAndNudgePoints 2, x: %s, y: %s, d: %s', $x, $y, $dimension));
}
$nudged = false;
@@ -118,13 +118,13 @@ final class GridSampler{
*
* @return \chillerlan\QRCode\Decoder\BitMatrix representing a grid of points sampled from the image within a region
* defined by the "from" parameters
* @throws \RuntimeException if image can't be sampled, for example, if the transformation defined
* @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if image can't be sampled, for example, if the transformation defined
* by the given points is invalid or results in sampling outside the image boundaries
*/
public function sampleGrid(BitMatrix $image, int $dimension, PerspectiveTransform $transform):BitMatrix{
if($dimension <= 0){
throw new RuntimeException('invalid matrix size');
throw new QRCodeDetectorException('invalid matrix size');
}
$bits = new BitMatrix($dimension);
@@ -152,7 +152,7 @@ final class GridSampler{
}
}
}
catch(Exception $aioobe){//ArrayIndexOutOfBoundsException
catch(Throwable $aioobe){//ArrayIndexOutOfBoundsException
// This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
// transform gets "twisted" such that it maps a straight line of points to a set of points
// whose endpoints are in bounds, but others are not. There is probably some mathematical
@@ -160,7 +160,7 @@ final class GridSampler{
// This results in an ugly runtime exception despite our clever checks above -- can't have
// that. We could check each point's coordinates but that feels duplicative. We settle for
// catching and wrapping ArrayIndexOutOfBoundsException.
throw new RuntimeException('ArrayIndexOutOfBoundsException');
throw new QRCodeDetectorException('ArrayIndexOutOfBoundsException');
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
/**
* Class QRCodeDetectorException
*
* @created 01.12.2021
* @author smiley <smiley@chillerlan.net>
* @copyright 2021 smiley
* @license MIT
*/
namespace chillerlan\QRCode\Detector;
use chillerlan\QRCode\QRCodeException;
class QRCodeDetectorException extends QRCodeException{}