Util.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. /**
  3. * Class Util
  4. *
  5. * @filesource Util.php
  6. * @created 25.11.2015
  7. * @package chillerlan\QRCode
  8. * @author Smiley <smiley@chillerlan.net>
  9. * @copyright 2015 Smiley
  10. * @license MIT
  11. */
  12. namespace chillerlan\QRCode;
  13. /**
  14. *
  15. */
  16. class Util{
  17. /**
  18. * @param int $typeNumber
  19. * @param int $errorCorrectLevel
  20. *
  21. * @return array
  22. * @throws \chillerlan\QRCode\QRCodeException
  23. */
  24. public static function getRSBlocks($typeNumber, $errorCorrectLevel){
  25. // PHP5 compat
  26. $RSBLOCK = QRConst::RSBLOCK;
  27. $BLOCK_TABLE = QRConst::BLOCK_TABLE;
  28. if(!isset($RSBLOCK[$errorCorrectLevel])){
  29. throw new QRCodeException('$typeNumber: '.$typeNumber.' / $errorCorrectLevel: '.$errorCorrectLevel.PHP_EOL.print_r($RSBLOCK, true));
  30. }
  31. $rsBlock = $BLOCK_TABLE[($typeNumber - 1) * 4 + $RSBLOCK[$errorCorrectLevel]];
  32. $list = [];
  33. $length = count($rsBlock) / 3;
  34. for($i = 0; $i < $length; $i++){
  35. for($j = 0; $j < $rsBlock[$i * 3 + 0]; $j++){
  36. $list[] = [$rsBlock[$i * 3 + 1], $rsBlock[$i * 3 + 2]];
  37. }
  38. }
  39. return $list;
  40. }
  41. /**
  42. * @param int $typeNumber
  43. * @param int $mode
  44. * @param int $ecLevel
  45. *
  46. * @return int
  47. * @throws \chillerlan\QRCode\QRCodeException
  48. */
  49. public static function getMaxLength($typeNumber, $mode, $ecLevel){
  50. $RSBLOCK = QRConst::RSBLOCK;
  51. $MAX_LENGTH = QRConst::MAX_LENGTH;
  52. $MODE = QRConst::MODE;
  53. if(!isset($RSBLOCK[$ecLevel])){
  54. throw new QRCodeException('$_err: '.$ecLevel);
  55. }
  56. if(!isset($MODE[$mode])){
  57. throw new QRCodeException('$_mode: '.$mode);
  58. }
  59. return $MAX_LENGTH[$typeNumber - 1][$RSBLOCK[$ecLevel]][$MODE[$mode]];
  60. }
  61. /**
  62. * @param string $s
  63. *
  64. * @return int
  65. */
  66. public static function getMode($s){
  67. switch(true){
  68. case self::isAlphaNum($s): return self::isNumber($s) ? QRConst::MODE_NUMBER : QRConst::MODE_ALPHANUM;
  69. case self::isKanji($s) : return QRConst::MODE_KANJI;
  70. default:
  71. return QRConst::MODE_BYTE;
  72. }
  73. }
  74. /**
  75. * @param string $s
  76. *
  77. * @return bool
  78. */
  79. protected static function isNumber($s){
  80. $len = strlen($s);
  81. for($i = 0; $i < $len; $i++){
  82. $c = ord($s[$i]);
  83. if(!(ord('0') <= $c && $c <= ord('9'))){
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. /**
  90. * @param string $s
  91. *
  92. * @return bool
  93. */
  94. protected static function isAlphaNum($s){
  95. $len = strlen($s);
  96. for($i = 0; $i < $len; $i++){
  97. $c = ord($s[$i]);
  98. if(!(ord('0') <= $c && $c <= ord('9')) && !(ord('A') <= $c && $c <= ord('Z')) && strpos(' $%*+-./:', $s[$i]) === false){
  99. return false;
  100. }
  101. }
  102. return true;
  103. }
  104. /**
  105. * @param string $s
  106. *
  107. * @return bool
  108. */
  109. protected static function isKanji($s){
  110. $i = 0;
  111. $len = strlen($s);
  112. while($i + 1 < $len){
  113. $c = ((0xff&ord($s[$i])) << 8)|(0xff&ord($s[$i + 1]));
  114. if(!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF)){
  115. return false;
  116. }
  117. $i += 2;
  118. }
  119. if($i < $len){
  120. return false;
  121. }
  122. return true;
  123. }
  124. /**
  125. * @param int $data
  126. *
  127. * @return int
  128. */
  129. public static function getBCHTypeInfo($data){
  130. $d = $data << 10;
  131. while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15) >= 0){
  132. $d ^= (QRConst::G15 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G15)));
  133. }
  134. return (($data << 10)|$d)^QRConst::G15_MASK;
  135. }
  136. /**
  137. * @param int $data
  138. *
  139. * @return int
  140. */
  141. public static function getBCHTypeNumber($data){
  142. $d = $data << 12;
  143. while(self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18) >= 0){
  144. $d ^= (QRConst::G18 << (self::getBCHDigit($d) - self::getBCHDigit(QRConst::G18)));
  145. }
  146. return ($data << 12)|$d;
  147. }
  148. /**
  149. * @param int $data
  150. *
  151. * @return int
  152. */
  153. public static function getBCHDigit($data){
  154. $digit = 0;
  155. while($data !== 0){
  156. $digit++;
  157. $data >>= 1;
  158. }
  159. return $digit;
  160. }
  161. /**
  162. * @param string $c
  163. *
  164. * @return int
  165. * @throws \chillerlan\QRCode\QRCodeException
  166. */
  167. public static function getCharCode($c){
  168. $c = ord($c);
  169. switch(true){
  170. case ord('0') <= $c && $c <= ord('9'): return $c - ord('0');
  171. case ord('A') <= $c && $c <= ord('Z'): return $c - ord('A') + 10;
  172. default:
  173. foreach(QRConst::CHAR_MAP as $i => $char){
  174. if(ord($char) === $c){
  175. return $i;
  176. }
  177. }
  178. }
  179. throw new QRCodeException('illegal char: '.$c);
  180. }
  181. /**
  182. * @param string $string
  183. *
  184. * @return int
  185. * @throws \chillerlan\QRCode\QRCodeException
  186. */
  187. public static function parseInt($string){
  188. $num = 0;
  189. $len = strlen($string);
  190. for($i = 0; $i < $len; $i++){
  191. $c = ord($string[$i]);
  192. $ord0 = ord('0');
  193. if($ord0 <= $c && $c <= ord('9')){
  194. $c = $c - $ord0;
  195. }
  196. else{
  197. throw new QRCodeException('illegal char: '.$c);
  198. }
  199. $num = $num * 10 + $c;
  200. }
  201. return $num;
  202. }
  203. }