1212namespace chillerlan \QRCode \Data ;
1313
1414use chillerlan \QRCode \Common \{BitBuffer , Mode };
15- use function ceil , intdiv , str_split ;
15+ use function ceil , intdiv , preg_match , strpos ;
1616
1717/**
1818 * Alphanumeric mode: 0 to 9, A to Z, space, $ % * + - . / :
@@ -25,30 +25,9 @@ final class AlphaNum extends QRDataModeAbstract{
2525 /**
2626 * ISO/IEC 18004:2000 Table 5
2727 *
28- * @var int[]
28+ * @var string
2929 */
30- private const CHAR_TO_ORD = [
31- // phpcs:ignore
32- '0 ' => 0 , '1 ' => 1 , '2 ' => 2 , '3 ' => 3 , '4 ' => 4 , '5 ' => 5 , '6 ' => 6 , '7 ' => 7 ,
33- // phpcs:ignore
34- '8 ' => 8 , '9 ' => 9 , 'A ' => 10 , 'B ' => 11 , 'C ' => 12 , 'D ' => 13 , 'E ' => 14 , 'F ' => 15 ,
35- 'G ' => 16 , 'H ' => 17 , 'I ' => 18 , 'J ' => 19 , 'K ' => 20 , 'L ' => 21 , 'M ' => 22 , 'N ' => 23 ,
36- 'O ' => 24 , 'P ' => 25 , 'Q ' => 26 , 'R ' => 27 , 'S ' => 28 , 'T ' => 29 , 'U ' => 30 , 'V ' => 31 ,
37- 'W ' => 32 , 'X ' => 33 , 'Y ' => 34 , 'Z ' => 35 , ' ' => 36 , '$ ' => 37 , '% ' => 38 , '* ' => 39 ,
38- '+ ' => 40 , '- ' => 41 , '. ' => 42 , '/ ' => 43 , ': ' => 44 ,
39- ];
40-
41- /**
42- * @var string[]
43- */
44- private const ORD_TO_CHAR = [
45- '0 ' , '1 ' , '2 ' , '3 ' , '4 ' , '5 ' , '6 ' , '7 ' ,
46- '8 ' , '9 ' , 'A ' , 'B ' , 'C ' , 'D ' , 'E ' , 'F ' ,
47- 'G ' , 'H ' , 'I ' , 'J ' , 'K ' , 'L ' , 'M ' , 'N ' ,
48- 'O ' , 'P ' , 'Q ' , 'R ' , 'S ' , 'T ' , 'U ' , 'V ' ,
49- 'W ' , 'X ' , 'Y ' , 'Z ' , ' ' , '$ ' , '% ' , '* ' ,
50- '+ ' , '- ' , '. ' , '/ ' , ': ' ,
51- ];
30+ private const CHAR_MAP = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./: ' ;
5231
5332 public const DATAMODE = Mode::ALPHANUM ;
5433
@@ -57,18 +36,7 @@ public function getLengthInBits():int{
5736 }
5837
5938 public static function validateString (string $ string ):bool {
60-
61- if ($ string === '' ){
62- return false ;
63- }
64-
65- foreach (str_split ($ string ) as $ chr ){
66- if (!isset (self ::CHAR_TO_ORD [$ chr ])){
67- return false ;
68- }
69- }
70-
71- return true ;
39+ return (bool )preg_match ('#^[ ' .self ::CHAR_MAP .']+$# ' , $ string );
7240 }
7341
7442 public function write (BitBuffer $ bitBuffer , int $ versionNumber ):static {
@@ -82,14 +50,14 @@ public function write(BitBuffer $bitBuffer, int $versionNumber):static{
8250 // encode 2 characters in 11 bits
8351 for ($ i = 0 ; ($ i + 1 ) < $ len ; $ i += 2 ){
8452 $ bitBuffer ->put (
85- (self :: CHAR_TO_ORD [ $ this ->data [$ i ]] * 45 + self :: CHAR_TO_ORD [ $ this ->data [($ i + 1 )]] ),
53+ ($ this ->ord ( $ this -> data [$ i ]) * 45 + $ this ->ord ( $ this -> data [($ i + 1 )]) ),
8654 11 ,
8755 );
8856 }
8957
9058 // encode a remaining character in 6 bits
9159 if ($ i < $ len ){
92- $ bitBuffer ->put (self :: CHAR_TO_ORD [ $ this ->data [$ i ]] , 6 );
60+ $ bitBuffer ->put ($ this ->ord ( $ this -> data [$ i ]) , 6 );
9361 }
9462
9563 return $ this ;
@@ -111,8 +79,8 @@ public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):s
11179 }
11280
11381 $ nextTwoCharsBits = $ bitBuffer ->read (11 );
114- $ result .= self ::ORD_TO_CHAR [ intdiv ($ nextTwoCharsBits , 45 )] ;
115- $ result .= self ::ORD_TO_CHAR [ ($ nextTwoCharsBits % 45 )] ;
82+ $ result .= self ::chr ( intdiv ($ nextTwoCharsBits , 45 )) ;
83+ $ result .= self ::chr ($ nextTwoCharsBits % 45 );
11684 $ length -= 2 ;
11785 }
11886
@@ -122,10 +90,35 @@ public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):s
12290 throw new QRCodeDataException ('not enough bits available ' ); // @codeCoverageIgnore
12391 }
12492
125- $ result .= self ::ORD_TO_CHAR [ $ bitBuffer ->read (6 )] ;
93+ $ result .= self ::chr ( $ bitBuffer ->read (6 )) ;
12694 }
12795
12896 return $ result ;
12997 }
13098
99+ /**
100+ * @throws \chillerlan\QRCode\Data\QRCodeDataException
101+ */
102+ private function ord (string $ chr ):int {
103+ $ ord = strpos (self ::CHAR_MAP , $ chr );
104+
105+ if ($ ord === false ){
106+ throw new QRCodeDataException ('invalid character ' ); // @codeCoverageIgnore
107+ }
108+
109+ return $ ord ;
110+ }
111+
112+ /**
113+ * @throws \chillerlan\QRCode\Data\QRCodeDataException
114+ */
115+ private static function chr (int $ ord ):string {
116+
117+ if ($ ord < 0 || $ ord > 44 ){
118+ throw new QRCodeDataException ('invalid character code ' ); // @codeCoverageIgnore
119+ }
120+
121+ return self ::CHAR_MAP [$ ord ];
122+ }
123+
131124}
0 commit comments