qrencode  4.1.1
About: libqrencode is a fast and compact library and command-line utility for encoding data in a QR Code symbol.
  Fossies Dox: qrencode-4.1.1.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

split.c
Go to the documentation of this file.
1/*
2 * qrencode - QR Code encoder
3 *
4 * Input data splitter.
5 * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
6 *
7 * The following data / specifications are taken from
8 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
9 * or
10 * "Automatic identification and data capture techniques --
11 * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28#if HAVE_CONFIG_H
29# include "config.h"
30#endif
31#include <stdlib.h>
32#include <string.h>
33#include <errno.h>
34#include "qrencode.h"
35#include "qrinput.h"
36#include "qrspec.h"
37#include "split.h"
38
39#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
40#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
41
42#if !HAVE_STRDUP
43#undef strdup
44char *strdup(const char *s)
45{
46 size_t len = strlen(s) + 1;
47 void *newstring = malloc(len);
48 if(newstring == NULL) return NULL;
49 return (char *)memcpy(newstring, s, len);
50}
51#endif
52
54{
55 unsigned char c, d;
56 unsigned int word;
57
58 c = (unsigned char)string[0];
59
60 if(c == '\0') return QR_MODE_NUL;
61 if(isdigit(c)) {
62 return QR_MODE_NUM;
63 } else if(isalnum(c)) {
64 return QR_MODE_AN;
65 } else if(hint == QR_MODE_KANJI) {
66 d = (unsigned char)string[1];
67 if(d != '\0') {
68 word = ((unsigned int)c << 8) | d;
69 if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
70 return QR_MODE_KANJI;
71 }
72 }
73 }
74
75 return QR_MODE_8;
76}
77
78static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
79static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
80
81static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
82{
83 const char *p;
84 int ret;
85 int run;
86 int dif;
87 int ln;
88 QRencodeMode mode;
89
91
92 p = string;
93 while(isdigit(*p)) {
94 p++;
95 }
96 run = (int)(p - string);
97 mode = Split_identifyMode(p, hint);
98 if(mode == QR_MODE_8) {
99 dif = QRinput_estimateBitsModeNum(run) + 4 + ln
100 + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
101 - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
102 if(dif > 0) {
103 return Split_eat8(string, input, hint);
104 }
105 }
106 if(mode == QR_MODE_AN) {
107 dif = QRinput_estimateBitsModeNum(run) + 4 + ln
108 + QRinput_estimateBitsModeAn(1) /* + 4 + la */
109 - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
110 if(dif > 0) {
111 return Split_eatAn(string, input, hint);
112 }
113 }
114
115 ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
116 if(ret < 0) return -1;
117
118 return run;
119}
120
121static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
122{
123 const char *p, *q;
124 int ret;
125 int run;
126 int dif;
127 int la, ln;
128
131
132 p = string;
133 while(isalnum(*p)) {
134 if(isdigit(*p)) {
135 q = p;
136 while(isdigit(*q)) {
137 q++;
138 }
139 dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */
140 + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
141 + (isalnum(*q)?(4 + ln):0)
142 - QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */;
143 if(dif < 0) {
144 break;
145 }
146 p = q;
147 } else {
148 p++;
149 }
150 }
151
152 run = (int)(p - string);
153
154 if(*p && !isalnum(*p)) {
155 dif = QRinput_estimateBitsModeAn(run) + 4 + la
156 + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
157 - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
158 if(dif > 0) {
159 return Split_eat8(string, input, hint);
160 }
161 }
162
163 ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
164 if(ret < 0) return -1;
165
166 return run;
167}
168
169static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
170{
171 const char *p;
172 int ret;
173 int run;
174
175 p = string;
177 p += 2;
178 }
179 run = (int)(p - string);
180 ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
181 if(ret < 0) return -1;
182
183 return run;
184}
185
186static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
187{
188 const char *p, *q;
189 QRencodeMode mode;
190 int ret;
191 int run;
192 int dif;
193 int la, ln, l8;
194 int swcost;
195
199
200 p = string + 1;
201 while(*p != '\0') {
202 mode = Split_identifyMode(p, hint);
203 if(mode == QR_MODE_KANJI) {
204 break;
205 }
206 if(mode == QR_MODE_NUM) {
207 q = p;
208 while(isdigit(*q)) {
209 q++;
210 }
212 swcost = 4 + l8;
213 } else {
214 swcost = 0;
215 }
216 dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
217 + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
218 + swcost
219 - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
220 if(dif < 0) {
221 break;
222 }
223 p = q;
224 } else if(mode == QR_MODE_AN) {
225 q = p;
226 while(isalnum(*q)) {
227 q++;
228 }
230 swcost = 4 + l8;
231 } else {
232 swcost = 0;
233 }
234 dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
235 + QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la
236 + swcost
237 - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
238 if(dif < 0) {
239 break;
240 }
241 p = q;
242 } else {
243 p++;
244 }
245 }
246
247 run = (int)(p - string);
248 ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
249 if(ret < 0) return -1;
250
251 return run;
252}
253
254static int Split_splitString(const char *string, QRinput *input,
256{
257 int length;
258 QRencodeMode mode;
259
260 while(*string != '\0') {
261 mode = Split_identifyMode(string, hint);
262 if(mode == QR_MODE_NUM) {
263 length = Split_eatNum(string, input, hint);
264 } else if(mode == QR_MODE_AN) {
265 length = Split_eatAn(string, input, hint);
266 } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
267 length = Split_eatKanji(string, input, hint);
268 } else {
269 length = Split_eat8(string, input, hint);
270 }
271 if(length == 0) break;
272 if(length < 0) return -1;
273 string += length;
274 }
275
276 return 0;
277}
278
279static char *dupAndToUpper(const char *str, QRencodeMode hint)
280{
281 char *newstr, *p;
282 QRencodeMode mode;
283
284 newstr = strdup(str);
285 if(newstr == NULL) return NULL;
286
287 p = newstr;
288 while(*p != '\0') {
289 mode = Split_identifyMode(p, hint);
290 if(mode == QR_MODE_KANJI) {
291 p += 2;
292 } else {
293 if (*p >= 'a' && *p <= 'z') {
294 *p = (char)((int)*p - 32);
295 }
296 p++;
297 }
298 }
299
300 return newstr;
301}
302
303int Split_splitStringToQRinput(const char *string, QRinput *input,
305{
306 char *newstr;
307 int ret;
308
309 if(string == NULL || *string == '\0') {
310 errno = EINVAL;
311 return -1;
312 }
313 if(!casesensitive) {
314 newstr = dupAndToUpper(string, hint);
315 if(newstr == NULL) return -1;
316 ret = Split_splitString(newstr, input, hint);
317 free(newstr);
318 } else {
319 ret = Split_splitString(string, input, hint);
320 }
321
322 return ret;
323}
static QRencodeMode hint
Definition: qrenc.c:51
static int casesensitive
Definition: qrenc.c:38
int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data)
Append data to an input object.
Definition: qrinput.c:223
QRencodeMode
Encoding mode.
Definition: qrencode.h:109
@ QR_MODE_KANJI
Kanji (shift-jis) mode.
Definition: qrencode.h:114
@ QR_MODE_AN
Alphabet-numeric mode.
Definition: qrencode.h:112
@ QR_MODE_8
8-bit data mode
Definition: qrencode.h:113
@ QR_MODE_NUL
Terminator (NUL character). Internal use only.
Definition: qrencode.h:110
@ QR_MODE_NUM
Numeric mode.
Definition: qrencode.h:111
int QRinput_estimateBitsModeNum(int size)
Estimate the length of the encoded bit stream of numeric data.
Definition: qrinput.c:381
int QRinput_estimateBitsMode8(int size)
8 bit data
Definition: qrinput.c:566
int QRinput_estimateBitsModeAn(int size)
Estimate the length of the encoded bit stream of alphabet-numeric data.
Definition: qrinput.c:493
int QRspec_lengthIndicator(QRencodeMode mode, int version)
Length indicator.
Definition: qrspec.c:142
static int Split_splitString(const char *string, QRinput *input, QRencodeMode hint)
Definition: split.c:254
static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
Definition: split.c:169
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
Definition: split.c:186
static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint)
Definition: split.c:81
char * strdup(const char *s)
Definition: split.c:44
static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
Definition: split.c:53
static char * dupAndToUpper(const char *str, QRencodeMode hint)
Definition: split.c:279
int Split_splitStringToQRinput(const char *string, QRinput *input, QRencodeMode hint, int casesensitive)
Split the input string (null terminated) into QRinput.
Definition: split.c:303
#define isdigit(__c__)
Definition: split.c:39
#define isalnum(__c__)
Definition: split.c:40
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
Definition: split.c:121
Input Data.
Definition: qrinput.h:46
int version
Definition: qrinput.h:47