qrsplit::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 5
rs 10
c 1
b 0
f 0
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 <[email protected]>
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
54
            return (ord($str[$pos]) >= ord('0')) && (ord($str[$pos]) <= ord('9'));
55
        }
56
57
        //----------------------------------------------------------------------
58
        public static function isalnumat($str, $pos)
59
        {
60
            if ($pos >= strlen($str)) {
61
                return false;
62
            }
63
64
            return QRinput::lookAnTable(ord($str[$pos])) >= 0;
65
        }
66
67
        //----------------------------------------------------------------------
68
        public function identifyMode($pos)
69
        {
70
            if ($pos >= strlen($this->dataStr)) {
71
                return QR_MODE_NUL;
72
            }
73
74
            $c = $this->dataStr[$pos];
75
76
            if (self::isdigitat($this->dataStr, $pos)) {
77
                return QR_MODE_NUM;
78
            } elseif (self::isalnumat($this->dataStr, $pos)) {
79
                return QR_MODE_AN;
80
            } elseif ($this->modeHint == QR_MODE_KANJI) {
81
                if ($pos + 1 < strlen($this->dataStr)) {
82
                    $d = $this->dataStr[$pos + 1];
83
                    $word = (ord($c) << 8) | ord($d);
84
                    if (($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
85
                        return QR_MODE_KANJI;
86
                    }
87
                }
88
            }
89
90
            return QR_MODE_8;
91
        }
92
93
        //----------------------------------------------------------------------
94
        public function eatNum()
95
        {
96
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
97
98
            $p = 0;
99
            while (self::isdigitat($this->dataStr, $p)) {
100
                $p++;
101
            }
102
103
            $run = $p;
104
            $mode = $this->identifyMode($p);
105
106
            if ($mode == QR_MODE_8) {
107
                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
108
                     + QRinput::estimateBitsMode8(1)         // + 4 + l8
109
                     - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
110
                if ($dif > 0) {
111
                    return $this->eat8();
112
                }
113
            }
114
            if ($mode == QR_MODE_AN) {
115
                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
116
                     + QRinput::estimateBitsModeAn(1)        // + 4 + la
117
                     - QRinput::estimateBitsModeAn($run + 1); // - 4 - la
118
                if ($dif > 0) {
119
                    return $this->eatAn();
120
                }
121
            }
122
123
            $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
124
            if ($ret < 0) {
125
                return -1;
126
            }
127
128
            return $run;
129
        }
130
131
        //----------------------------------------------------------------------
132
        public function eatAn()
133
        {
134
            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
135
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
136
137
            $p = 0;
138
139
            while (self::isalnumat($this->dataStr, $p)) {
140
                if (self::isdigitat($this->dataStr, $p)) {
141
                    $q = $p;
142
                    while (self::isdigitat($this->dataStr, $q)) {
143
                        $q++;
144
                    }
145
146
                    $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
147
                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
148
                         - QRinput::estimateBitsModeAn($q); // - 4 - la
149
150
                    if ($dif < 0) {
151
                        break;
152
                    } else {
153
                        $p = $q;
154
                    }
155
                } else {
156
                    $p++;
157
                }
158
            }
159
160
            $run = $p;
161
162
            if (!self::isalnumat($this->dataStr, $p)) {
163
                $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
164
                     + QRinput::estimateBitsMode8(1) // + 4 + l8
165
                      - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
166
                if ($dif > 0) {
167
                    return $this->eat8();
168
                }
169
            }
170
171
            $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
172
            if ($ret < 0) {
173
                return -1;
174
            }
175
176
            return $run;
177
        }
178
179
        //----------------------------------------------------------------------
180
        public function eatKanji()
181
        {
182
            $p = 0;
183
184
            while ($this->identifyMode($p) == QR_MODE_KANJI) {
185
                $p += 2;
186
            }
187
188
            $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
189
            if ($ret < 0) {
190
                return -1;
191
            }
192
193
            return $ret;
194
        }
195
196
        //----------------------------------------------------------------------
197
        public function eat8()
198
        {
199
            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
200
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
201
202
            $p = 1;
203
            $dataStrLen = strlen($this->dataStr);
204
205
            while ($p < $dataStrLen) {
206
                $mode = $this->identifyMode($p);
207
                if ($mode == QR_MODE_KANJI) {
208
                    break;
209
                }
210
                if ($mode == QR_MODE_NUM) {
211
                    $q = $p;
212
                    while (self::isdigitat($this->dataStr, $q)) {
213
                        $q++;
214
                    }
215
                    $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
216
                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
217
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
218
                    if ($dif < 0) {
219
                        break;
220
                    } else {
221
                        $p = $q;
222
                    }
223
                } elseif ($mode == QR_MODE_AN) {
224
                    $q = $p;
225
                    while (self::isalnumat($this->dataStr, $q)) {
226
                        $q++;
227
                    }
228
                    $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
229
                         + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
230
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
231
                    if ($dif < 0) {
232
                        break;
233
                    } else {
234
                        $p = $q;
235
                    }
236
                } else {
237
                    $p++;
238
                }
239
            }
240
241
            $run = $p;
242
            $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
243
244
            if ($ret < 0) {
245
                return -1;
246
            }
247
248
            return $run;
249
        }
250
251
        //----------------------------------------------------------------------
252
        public function splitString()
253
        {
254
            while (strlen($this->dataStr) > 0) {
255
                if ($this->dataStr == '') {
256
                    return 0;
257
                }
258
259
                $mode = $this->identifyMode(0);
260
261
                switch ($mode) {
262
                    case QR_MODE_NUM: $length = $this->eatNum(); break;
263
                    case QR_MODE_AN:  $length = $this->eatAn(); break;
264
                    case QR_MODE_KANJI:
265
                        if ($mode == QR_MODE_KANJI) {
266
                            $length = $this->eatKanji();
267
                        } else {
268
                            $length = $this->eat8();
269
                        }
270
                        break;
271
                    default: $length = $this->eat8(); break;
272
273
                }
274
275
                if ($length == 0) {
276
                    return 0;
277
                }
278
                if ($length < 0) {
279
                    return -1;
280
                }
281
282
                $this->dataStr = substr($this->dataStr, $length);
283
            }
284
        }
285
286
        //----------------------------------------------------------------------
287
        public function toUpper()
288
        {
289
            $stringLen = strlen($this->dataStr);
290
            $p = 0;
291
292
            while ($p < $stringLen) {
293
                $mode = $this->identifyMode(substr($this->dataStr, $p));
294
                if ($mode == QR_MODE_KANJI) {
295
                    $p += 2;
296
                } else {
297
                    if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
298
                        $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
299
                    }
300
                    $p++;
301
                }
302
            }
303
304
            return $this->dataStr;
305
        }
306
307
        //----------------------------------------------------------------------
308
        public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
309
        {
310
            if (is_null($string) || $string == '\0' || $string == '') {
311
                throw new Exception('empty string!!!');
312
            }
313
314
            $split = new self($string, $input, $modeHint);
315
316
            if (!$casesensitive) {
317
                $split->toUpper();
318
            }
319
320
            return $split->splitString();
321
        }
322
    }
323