qrsplit.php (11381B)
1 <?php 2 /* 3 * PHP QR Code encoder 4 * 5 * Input splitting classes 6 * 7 * Based on libqrencode C library distributed under LGPL 2.1 8 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 9 * 10 * PHP QR Code is distributed under LGPL 3 11 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 12 * 13 * The following data / specifications are taken from 14 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 15 * or 16 * "Automatic identification and data capture techniques -- 17 * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 18 * 19 * This library is free software; you can redistribute it and/or 20 * modify it under the terms of the GNU Lesser General Public 21 * License as published by the Free Software Foundation; either 22 * version 3 of the License, or any later version. 23 * 24 * This library is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 * Lesser General Public License for more details. 28 * 29 * You should have received a copy of the GNU Lesser General Public 30 * License along with this library; if not, write to the Free Software 31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 */ 33 class QRsplit { 34 35 public $dataStr = ''; 36 public $input; 37 public $modeHint; 38 39 //---------------------------------------------------------------------- 40 public function __construct($dataStr, $input, $modeHint) 41 { 42 $this->dataStr = $dataStr; 43 $this->input = $input; 44 $this->modeHint = $modeHint; 45 } 46 47 //---------------------------------------------------------------------- 48 public static function isdigitat($str, $pos) 49 { 50 if ($pos >= strlen($str)) 51 return false; 52 53 return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); 54 } 55 56 //---------------------------------------------------------------------- 57 public static function isalnumat($str, $pos) 58 { 59 if ($pos >= strlen($str)) 60 return false; 61 62 return (QRinput::lookAnTable(ord($str[$pos])) >= 0); 63 } 64 65 //---------------------------------------------------------------------- 66 public function identifyMode($pos) 67 { 68 if ($pos >= strlen($this->dataStr)) 69 return QR_MODE_NUL; 70 71 $c = $this->dataStr[$pos]; 72 73 if(self::isdigitat($this->dataStr, $pos)) { 74 return QR_MODE_NUM; 75 } else if(self::isalnumat($this->dataStr, $pos)) { 76 return QR_MODE_AN; 77 } else if($this->modeHint == QR_MODE_KANJI) { 78 79 if ($pos+1 < strlen($this->dataStr)) 80 { 81 $d = $this->dataStr[$pos+1]; 82 $word = (ord($c) << 8) | ord($d); 83 if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { 84 return QR_MODE_KANJI; 85 } 86 } 87 } 88 89 return QR_MODE_8; 90 } 91 92 //---------------------------------------------------------------------- 93 public function eatNum() 94 { 95 $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); 96 97 $p = 0; 98 while(self::isdigitat($this->dataStr, $p)) { 99 $p++; 100 } 101 102 $run = $p; 103 $mode = $this->identifyMode($p); 104 105 if($mode == QR_MODE_8) { 106 $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln 107 + QRinput::estimateBitsMode8(1) // + 4 + l8 108 - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 109 if($dif > 0) { 110 return $this->eat8(); 111 } 112 } 113 if($mode == QR_MODE_AN) { 114 $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln 115 + QRinput::estimateBitsModeAn(1) // + 4 + la 116 - QRinput::estimateBitsModeAn($run + 1);// - 4 - la 117 if($dif > 0) { 118 return $this->eatAn(); 119 } 120 } 121 122 $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); 123 if($ret < 0) 124 return -1; 125 126 return $run; 127 } 128 129 //---------------------------------------------------------------------- 130 public function eatAn() 131 { 132 $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); 133 $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); 134 135 $p = 0; 136 137 while(self::isalnumat($this->dataStr, $p)) { 138 if(self::isdigitat($this->dataStr, $p)) { 139 $q = $p; 140 while(self::isdigitat($this->dataStr, $q)) { 141 $q++; 142 } 143 144 $dif = QRinput::estimateBitsModeAn($p) // + 4 + la 145 + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln 146 - QRinput::estimateBitsModeAn($q); // - 4 - la 147 148 if($dif < 0) { 149 break; 150 } else { 151 $p = $q; 152 } 153 } else { 154 $p++; 155 } 156 } 157 158 $run = $p; 159 160 if(!self::isalnumat($this->dataStr, $p)) { 161 $dif = QRinput::estimateBitsModeAn($run) + 4 + $la 162 + QRinput::estimateBitsMode8(1) // + 4 + l8 163 - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 164 if($dif > 0) { 165 return $this->eat8(); 166 } 167 } 168 169 $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); 170 if($ret < 0) 171 return -1; 172 173 return $run; 174 } 175 176 //---------------------------------------------------------------------- 177 public function eatKanji() 178 { 179 $p = 0; 180 181 while($this->identifyMode($p) == QR_MODE_KANJI) { 182 $p += 2; 183 } 184 185 $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); 186 if($ret < 0) 187 return -1; 188 189 return $run; 190 } 191 192 //---------------------------------------------------------------------- 193 public function eat8() 194 { 195 $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); 196 $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); 197 198 $p = 1; 199 $dataStrLen = strlen($this->dataStr); 200 201 while($p < $dataStrLen) { 202 203 $mode = $this->identifyMode($p); 204 if($mode == QR_MODE_KANJI) { 205 break; 206 } 207 if($mode == QR_MODE_NUM) { 208 $q = $p; 209 while(self::isdigitat($this->dataStr, $q)) { 210 $q++; 211 } 212 $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 213 + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln 214 - QRinput::estimateBitsMode8($q); // - 4 - l8 215 if($dif < 0) { 216 break; 217 } else { 218 $p = $q; 219 } 220 } else if($mode == QR_MODE_AN) { 221 $q = $p; 222 while(self::isalnumat($this->dataStr, $q)) { 223 $q++; 224 } 225 $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 226 + QRinput::estimateBitsModeAn($q - $p) + 4 + $la 227 - QRinput::estimateBitsMode8($q); // - 4 - l8 228 if($dif < 0) { 229 break; 230 } else { 231 $p = $q; 232 } 233 } else { 234 $p++; 235 } 236 } 237 238 $run = $p; 239 $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); 240 241 if($ret < 0) 242 return -1; 243 244 return $run; 245 } 246 247 //---------------------------------------------------------------------- 248 public function splitString() 249 { 250 while (strlen($this->dataStr) > 0) 251 { 252 if($this->dataStr == '') 253 return 0; 254 255 $mode = $this->identifyMode(0); 256 257 switch ($mode) { 258 case QR_MODE_NUM: $length = $this->eatNum(); break; 259 case QR_MODE_AN: $length = $this->eatAn(); break; 260 case QR_MODE_KANJI: 261 if ($hint == QR_MODE_KANJI) 262 $length = $this->eatKanji(); 263 else $length = $this->eat8(); 264 break; 265 default: $length = $this->eat8(); break; 266 267 } 268 269 if($length == 0) return 0; 270 if($length < 0) return -1; 271 272 $this->dataStr = substr($this->dataStr, $length); 273 } 274 } 275 276 //---------------------------------------------------------------------- 277 public function toUpper() 278 { 279 $stringLen = strlen($this->dataStr); 280 $p = 0; 281 282 while ($p<$stringLen) { 283 $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); 284 if($mode == QR_MODE_KANJI) { 285 $p += 2; 286 } else { 287 if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { 288 $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); 289 } 290 $p++; 291 } 292 } 293 294 return $this->dataStr; 295 } 296 297 //---------------------------------------------------------------------- 298 public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) 299 { 300 if(is_null($string) || $string == '\0' || $string == '') { 301 throw new Exception('empty string!!!'); 302 } 303 304 $split = new QRsplit($string, $input, $modeHint); 305 306 if(!$casesensitive) 307 $split->toUpper(); 308 309 return $split->splitString(); 310 } 311 }