1 /**
2 *
3 * IEC16022 bar code generation
4 * Adrian Kennard, Andrews & Arnold Ltd
5 * with help from Cliff Hones on the RS coding
6 *
7 * (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
8 * (c) 2006-2007 Stefan Schmidt <stefan@datenfreihafen.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <time.h>
31 #include <stdlib.h>
32 #include "reedsol.h"
33 #include "iec16022ecc200.h"
34
35 static const struct ecc200matrix_s {
36 unsigned char H, W;
37 unsigned char FH, FW;
38 unsigned short bytes;
39 unsigned char datablock, rsblock;
40 } ecc200matrix[] = {
41 { 10, 10, 10, 10, 3, 3, 5}, //
42 { 12, 12, 12, 12, 5, 5, 7}, //
43 { 8, 18, 8, 18, 5, 5, 7}, //
44 { 14, 14, 14, 14, 8, 8, 10}, //
45 { 8, 32, 8, 16, 10, 10, 11}, //
46 { 16, 16, 16, 16, 12, 12, 12}, //
47 { 12, 26, 12, 26, 16, 16, 14}, //
48 { 18, 18, 18, 18, 18, 18, 14}, //
49 { 20, 20, 20, 20, 22, 22, 18}, //
50 { 12, 36, 12, 18, 22, 22, 18}, //
51 { 22, 22, 22, 22, 30, 30, 20}, //
52 { 16, 36, 16, 18, 32, 32, 24}, //
53 { 24, 24, 24, 24, 36, 36, 24}, //
54 { 26, 26, 26, 26, 44, 44, 28}, //
55 { 16, 48, 16, 24, 49, 49, 28}, //
56 { 32, 32, 16, 16, 62, 62, 36}, //
57 { 36, 36, 18, 18, 86, 86, 42}, //
58 { 40, 40, 20, 20, 114, 114, 48}, //
59 { 44, 44, 22, 22, 144, 144, 56}, //
60 { 48, 48, 24, 24, 174, 174, 68}, //
61 { 52, 52, 26, 26, 204, 102, 42}, //
62 { 64, 64, 16, 16, 280, 140, 56}, //
63 { 72, 72, 18, 18, 368, 92, 36}, //
64 { 80, 80, 20, 20, 456, 114, 48}, //
65 { 88, 88, 22, 22, 576, 144, 56}, //
66 { 96, 96, 24, 24, 696, 174, 68}, //
67 {104, 104, 26, 26, 816, 136, 56}, //
68 {120, 120, 20, 20, 1050, 175, 68}, //
69 {132, 132, 22, 22, 1304, 163, 62}, //
70 {144, 144, 24, 24, 1558, 156, 62}, // 156*4+155*2
71 {0} // terminate
72 };
73
74 // simple checked response malloc
safemalloc(int n,int s)75 static void *safemalloc(int n, int s)
76 {
77 void *p = calloc(n, s);
78 if (!p) {
79 fprintf(stderr, "Malloc(%d) failed\n", n);
80 exit(1);
81 }
82 return p;
83 }
84
85 // Annex M placement alorithm low level
ecc200placementbit(int * array,int NR,int NC,int r,int c,int p,char b)86 static void ecc200placementbit(int *array, int NR, int NC, int r, int c,
87 int p, char b)
88 {
89 if (r < 0) {
90 r += NR;
91 c += 4 - ((NR + 4) % 8);
92 }
93 if (c < 0) {
94 c += NC;
95 r += 4 - ((NC + 4) % 8);
96 }
97 array[r * NC + c] = (p << 3) + b;
98 }
99
ecc200placementblock(int * array,int NR,int NC,int r,int c,int p)100 static void ecc200placementblock(int *array, int NR, int NC, int r,
101 int c, int p)
102 {
103 ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7);
104 ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6);
105 ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5);
106 ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4);
107 ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3);
108 ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2);
109 ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1);
110 ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0);
111 }
112
ecc200placementcornerA(int * array,int NR,int NC,int p)113 static void ecc200placementcornerA(int *array, int NR, int NC, int p)
114 {
115 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
116 ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6);
117 ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5);
118 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
119 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
120 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
121 ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
122 ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
123 }
124
ecc200placementcornerB(int * array,int NR,int NC,int p)125 static void ecc200placementcornerB(int *array, int NR, int NC, int p)
126 {
127 ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
128 ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
129 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
130 ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4);
131 ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3);
132 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2);
133 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1);
134 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
135 }
136
ecc200placementcornerC(int * array,int NR,int NC,int p)137 static void ecc200placementcornerC(int *array, int NR, int NC, int p)
138 {
139 ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
140 ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
141 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
142 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
143 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
144 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
145 ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
146 ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
147 }
148
ecc200placementcornerD(int * array,int NR,int NC,int p)149 static void ecc200placementcornerD(int *array, int NR, int NC, int p)
150 {
151 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
152 ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
153 ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5);
154 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
155 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
156 ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2);
157 ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1);
158 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
159 }
160
161 // Annex M placement alorithm main function
ecc200placement(int * array,int NR,int NC)162 static void ecc200placement(int *array, int NR, int NC)
163 {
164 // array must be cleared by caller
165 int r, c, p;
166 // start
167 p = 1;
168 r = 4;
169 c = 0;
170 do {
171 // check corner
172 if (r == NR && !c)
173 ecc200placementcornerA(array, NR, NC, p++);
174 if (r == NR - 2 && !c && NC % 4)
175 ecc200placementcornerB(array, NR, NC, p++);
176 if (r == NR - 2 && !c && (NC % 8) == 4)
177 ecc200placementcornerC(array, NR, NC, p++);
178 if (r == NR + 4 && c == 2 && !(NC % 8))
179 ecc200placementcornerD(array, NR, NC, p++);
180 // up/right
181 do {
182 if (r < NR && c >= 0 && !array[r * NC + c])
183 ecc200placementblock(array, NR, NC, r, c, p++);
184 r -= 2;
185 c += 2;
186 }
187 while (r >= 0 && c < NC);
188 r++;
189 c += 3;
190 // down/left
191 do {
192 if (r >= 0 && c < NC && !array[r * NC + c])
193 ecc200placementblock(array, NR, NC, r, c, p++);
194 r += 2;
195 c -= 2;
196 }
197 while (r < NR && c >= 0);
198 r += 3;
199 c++;
200 }
201 while (r < NR || c < NC);
202 // unfilled corner
203 if (!array[NR * NC - 1])
204 array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
205 }
206
207 // calculate and append ecc code, and if necessary interleave
ecc200(unsigned char * binary,int bytes,int datablock,int rsblock)208 static void ecc200(unsigned char *binary, int bytes, int datablock, int rsblock)
209 {
210 int blocks = (bytes + 2) / datablock, b;
211 rs_init_gf(0x12d);
212 rs_init_code(rsblock, 1);
213 for (b = 0; b < blocks; b++) {
214 unsigned char buf[256], ecc[256];
215 int n, p = 0;
216 for (n = b; n < bytes; n += blocks)
217 buf[p++] = binary[n];
218 rs_encode(p, buf, ecc);
219 p = rsblock - 1; // comes back reversed
220 for (n = b; n < rsblock * blocks; n += blocks)
221 binary[bytes + n] = ecc[p--];
222 }
223 }
224
225 /*
226 * perform encoding for ecc200, source s len sl, to target t len tl, using
227 * optional encoding control string e return 1 if OK, 0 if failed. Does all
228 * necessary padding to tl
229 */
230
ecc200encode(unsigned char * t,int tl,const unsigned char * s,int sl,const char * encoding,int * lenp,int flags)231 static char ecc200encode(unsigned char *t, int tl, const unsigned char *s, int sl,
232 const char *encoding, int *lenp, int flags)
233 {
234 char enc = 'a'; // start in ASCII encoding mode
235 int tp = 0, sp = 0;
236 if (flags & IEC16022_FLAG_GS1) {
237 t[tp++] = 232;
238 if (sl >= 3 && s[0] == ']' && s[1] == 'd' && s[2] == '2') {
239 sp = 3;
240 }
241 }
242 if (strlen(encoding) < sl - sp) {
243 fprintf(stderr, "Encoding string too short\n");
244 return 0;
245 }
246 // do the encoding
247 while (sp < sl && tp < tl) {
248 char newenc = enc; // suggest new encoding
249 if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2
250 && enc == 'x')
251 enc = 'a'; // auto revert to ASCII
252 newenc = tolower(encoding[sp]);
253 switch (newenc) { // encode character
254 case 'c': // C40
255 case 't': // Text
256 case 'x': // X12
257 {
258 char out[6];
259 int p = 0;
260 const char *e,
261 *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_",
262 *s3 = 0;
263 if (newenc == 'c') {
264 e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
265 s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
266 }
267 if (newenc == 't') {
268 e = " 0123456789abcdefghijklmnopqrstuvwxyz";
269 s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
270 }
271 if (newenc == 'x')
272 e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>";
273 do {
274 unsigned char c = s[sp++];
275 char *w;
276 if (c & 0x80) {
277 if (newenc == 'x') {
278 fprintf(stderr,
279 "Cannot encode char 0x%02X in X12\n",
280 c);
281 return 0;
282 }
283 c &= 0x7f;
284 out[p++] = 1;
285 out[p++] = 30;
286 }
287 w = strchr(e, c);
288 if (w)
289 out[p++] = ((w - e) + 3) % 40;
290 else {
291 if (newenc == 'x') {
292 fprintf(stderr,
293 "Cannot encode char 0x%02X in X12\n",
294 c);
295 return 0;
296 }
297 if (c < 32) { // shift 1
298 out[p++] = 0;
299 out[p++] = c;
300 } else {
301 w = strchr(s2, c);
302 if (w) { // shift 2
303 out[p++] = 1;
304 out[p++] =
305 (w - s2);
306 } else {
307 w = strchr(s3,
308 c);
309 if (w) {
310 out[p++]
311 = 2;
312 out[p++]
313 =
314 (w -
315 s3);
316 } else {
317 fprintf
318 (stderr,
319 "Could not encode 0x%02X, should \
320 not happen\n", c);
321 return
322 0;
323 }
324 }
325 }
326 }
327 while (p >= 3 || (p && sp == sl)) {
328 int v;
329 while (p < 3) out[p++] = 0; // pad at end
330 if (tp + 2 >= tl) return 0; // not enough space
331 v = out[0] * 1600 +
332 out[1] * 40 + out[2] + 1;
333 if (enc != newenc) {
334 if (enc == 'c'
335 || enc == 't'
336 || enc == 'x')
337 t[tp++] = 254; // escape C40/text/X12
338 else if (enc == 'x')
339 t[tp++] = 0x7C; // escape EDIFACT
340 if (newenc == 'c')
341 t[tp++] = 230;
342 if (newenc == 't')
343 t[tp++] = 239;
344 if (newenc == 'x')
345 t[tp++] = 238;
346 enc = newenc;
347 }
348 t[tp++] = (v >> 8);
349 t[tp++] = (v & 0xFF);
350 p -= 3;
351 out[0] = out[3];
352 out[1] = out[4];
353 out[2] = out[5];
354 }
355 }
356 while (p && sp < sl);
357 }
358 break;
359 case 'e': // EDIFACT
360 {
361 unsigned char out[4], p = 0;
362 if (enc != 'a' && enc != newenc) { // can only be from C40/Text/X12
363 t[tp++] = 254;
364 enc = 'a';
365 }
366 if (enc == 'a')
367 {
368 t[tp++] = 240;
369 enc = 'e';
370 }
371 while (sp < sl && tolower(encoding[sp]) == 'e'
372 && p < 4) {
373 if (s[sp] < 32 || s[sp] > 94) {
374 fprintf(stderr, "Cannot encode 0x%02X in EDIFACT\n", s[sp]);
375 return 0;
376 }
377 out[p++] = s[sp++];
378 }
379 if (p < 4) {
380 out[p++] = 0x1F;
381 enc = 'a';
382 } // termination
383 t[tp] = ((out[0] & 0x3F) << 2);
384 t[tp++] |= ((out[1] & 0x30) >> 4);
385 t[tp] = ((out[1] & 0x0F) << 4);
386 if (p == 2)
387 tp++;
388 else {
389 t[tp++] |= ((out[2] & 0x3C) >> 2);
390 t[tp] = ((out[2] & 0x03) << 6);
391 t[tp++] |= (out[3] & 0x3F);
392 }
393 }
394 break;
395 case 'a': // ASCII
396 if (enc != newenc) {
397 if (enc == 'c' || enc == 't' || enc == 'x')
398 t[tp++] = 254; // escape C40/text/X12
399 else
400 t[tp++] = 0x7C; // escape EDIFACT
401 }
402 enc = 'a';
403 if (sl - sp >= 2 && isdigit(s[sp])
404 && isdigit(s[sp + 1])) {
405 t[tp++] =
406 (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130;
407 sp += 2;
408 } else if (s[sp] > 127) {
409 t[tp++] = 235;
410 t[tp++] = s[sp++] - 127;
411 } else
412 t[tp++] = s[sp++] + 1;
413 break;
414 case 'b': // Binary
415 {
416 int l = 0; // how much to encode
417 int p;
418 for (p = sp;
419 p < sl
420 && tolower(encoding[p]) == 'b';
421 p++)
422 l++;
423 t[tp++] = 231; // base256
424 if (l < 250)
425 t[tp++] = l;
426 else {
427 t[tp++] = 249 + (l / 250);
428 t[tp++] = (l % 250);
429 }
430 while (l-- && tp < tl) {
431 t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H
432 tp++;
433 }
434 if (l) return 0; // not enough space
435 enc = 'a'; // reverse to ASCII at end
436 }
437 break;
438 default:
439 fprintf(stderr, "Unknown encoding %c\n", newenc);
440 return 0; // failed
441 }
442 }
443 if (lenp)
444 *lenp = tp;
445 if (tp < tl && enc != 'a') {
446 if (enc == 'c' || enc == 'x' || enc == 't')
447 t[tp++] = 254; // escape X12/C40/Text
448 else
449 t[tp++] = 0x7C; // escape EDIFACT
450 }
451 if (tp < tl)
452 t[tp++] = 129; // pad
453 while (tp < tl) { // more padding
454 int v = 129 + (((tp + 1) * 149) % 253) + 1; // see Annex H
455 if (v > 254)
456 v -= 254;
457 t[tp++] = v;
458 }
459 if (tp > tl || sp < sl)
460 return 0; // did not fit
461 /*
462 * for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); \
463 * fprintf (stderr, "\n");
464 */
465 return 1; // OK
466 }
467
468 // Auto encoding format functions
469 static const char encchr[] = "ACTXEB";
470
471 enum {
472 E_ASCII,
473 E_C40,
474 E_TEXT,
475 E_X12,
476 E_EDIFACT,
477 E_BINARY,
478 E_MAX
479 };
480
481 static const unsigned char switchcost[E_MAX][E_MAX] = {
482 {0, 1, 1, 1, 1, 2}, // From E_ASCII
483 {1, 0, 2, 2, 2, 3}, // From E_C40
484 {1, 2, 0, 2, 2, 3}, // From E_TEXT
485 {1, 2, 2, 0, 2, 3}, // From E_X12
486 {1, 2, 2, 2, 0, 3}, // From E_EDIFACT
487 {0, 1, 1, 1, 1, 0}, // From E_BINARY
488 };
489
490 /*
491 * Creates a encoding list (malloc)
492 * returns encoding string
493 * if lenp not null, target len stored
494 * if error, null returned
495 * if exact specified, then assumes shortcuts applicable for exact fit
496 * in target
497 * 1. No unlatch to return to ASCII for last encoded byte after C40 or
498 * Text or X12
499 * 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after
500 * EDIFACT
501 * 3. Final C40 or text encoding exactly in last 2 bytes can have a shift
502 * 0 to pad to make a tripple
503 * Only use the encoding from an exact request if the len matches the target,
504 * otherwise free the result and try again with exact=0
505 */
506
encmake(int l,const unsigned char * s,int * lenp,char exact)507 static char *encmake(int l, const unsigned char *s, int *lenp, char exact)
508 {
509 char *encoding = 0;
510 int p = l;
511 int e;
512 struct {
513 // number of bytes of source that can be encoded in a row at this point
514 // using this encoding mode
515 short s;
516 // number of bytes of target generated encoding from this point to end if
517 // already in this encoding mode
518 short t;
519 } enc[MAXBARCODE][E_MAX];
520 memset(&enc, 0, sizeof(enc));
521 if (lenp)
522 *lenp = 0;
523 if (!l) {
524 encoding = safemalloc(1, 1);
525 *encoding = 0;
526 return encoding; // no length
527 }
528 if (l > MAXBARCODE)
529 return 0; // not valid
530 while (p--) {
531 int b = 0, sub;
532 int sl, tl, bl, t;
533 // consider each encoding from this point
534 // ASCII
535 sl = tl = 1;
536 if (isdigit(s[p]) && p + 1 < l && isdigit(s[p + 1]))
537 sl = 2; // double digit
538 else if (s[p] & 0x80)
539 tl = 2; // high shifted
540 bl = 0;
541 if (p + sl < l)
542 for (e = 0; e < E_MAX; e++)
543 if (enc[p + sl][e].t && ((t = enc[p + sl][e].t +
544 switchcost[E_ASCII]
545 [e]) < bl || !bl)) {
546 bl = t;
547 b = e;
548 }
549 enc[p][E_ASCII].t = tl + bl;
550 enc[p][E_ASCII].s = sl;
551 if (bl && b == E_ASCII)
552 enc[p][b].s += enc[p + sl][b].s;
553 // C40
554 sub = tl = sl = 0;
555 do {
556 unsigned char c = s[p + sl++];
557 if (c & 0x80) { // shift + upper
558 sub += 2;
559 c &= 0x7F;
560 }
561 if (c != ' ' && !isdigit(c) && !isupper(c))
562 sub++; // shift
563 sub++;
564 while (sub >= 3) {
565 sub -= 3;
566 tl += 2;
567 }
568 } while (sub && p + sl < l);
569 if (exact && sub == 2 && p + sl == l) {
570 // special case, can encode last block with shift 0 at end (Is this
571 // valid when not end of target buffer?)
572 sub = 0;
573 tl += 2;
574 }
575 if (!sub) { // can encode C40
576 bl = 0;
577 if (p + sl < l) {
578 for (e = 0; e < E_MAX; e++)
579 if (enc[p + sl][e].t
580 &&
581 ((t =
582 enc[p + sl][e].t +
583 switchcost[E_C40][e]) < bl
584 || !bl)) {
585 bl = t;
586 b = e;
587 }
588 if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
589 // special case, switch to ASCII for last bytes
590 bl = 1;
591 b = E_ASCII;
592 }
593 }
594 enc[p][E_C40].t = tl + bl;
595 enc[p][E_C40].s = sl;
596 if (bl && b == E_C40)
597 enc[p][b].s += enc[p + sl][b].s;
598 }
599 // Text
600 sub = tl = sl = 0;
601 do {
602 unsigned char c = s[p + sl++];
603 if (c & 0x80) { // shift + upper
604 sub += 2;
605 c &= 0x7F;
606 }
607 if (c != ' ' && !isdigit(c) && !islower(c))
608 sub++; // shift
609 sub++;
610 while (sub >= 3) {
611 sub -= 3;
612 tl += 2;
613 }
614 } while (sub && p + sl < l);
615 if (exact && sub == 2 && p + sl == l) {
616 // special case, can encode last block with shift 0 at end (Is this
617 // valid when not end of target buffer?)
618 sub = 0;
619 tl += 2;
620 }
621 if (!sub && sl) { // can encode Text
622 bl = 0;
623 if (p + sl < l) {
624 for (e = 0; e < E_MAX; e++)
625 if (enc[p + sl][e].t
626 &&
627 ((t =
628 enc[p + sl][e].t +
629 switchcost[E_TEXT][e]) < bl
630 || !bl)) {
631 bl = t;
632 b = e;
633 }
634 if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) { // special case, switch to ASCII for last bytes
635 bl = 1;
636 b = E_ASCII;
637 }
638 }
639 enc[p][E_TEXT].t = tl + bl;
640 enc[p][E_TEXT].s = sl;
641 if (bl && b == E_TEXT)
642 enc[p][b].s += enc[p + sl][b].s;
643 }
644 // X12
645 sub = tl = sl = 0;
646 do {
647 unsigned char c = s[p + sl++];
648 if (c != 13 && c != '*' && c != '>' && c != ' '
649 && !isdigit(c) && !isupper(c)) {
650 sl = 0;
651 break;
652 }
653 sub++;
654 while (sub >= 3) {
655 sub -= 3;
656 tl += 2;
657 }
658 } while (sub && p + sl < l);
659 if (!sub && sl) { // can encode X12
660 bl = 0;
661 if (p + sl < l) {
662 for (e = 0; e < E_MAX; e++)
663 if (enc[p + sl][e].t
664 &&
665 ((t =
666 enc[p + sl][e].t +
667 switchcost[E_X12][e]) < bl
668 || !bl)) {
669 bl = t;
670 b = e;
671 }
672 if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
673 // special case, switch to ASCII for last bytes
674 bl = 1;
675 b = E_ASCII;
676 }
677 }
678 enc[p][E_X12].t = tl + bl;
679 enc[p][E_X12].s = sl;
680 if (bl && b == E_X12)
681 enc[p][b].s += enc[p + sl][b].s;
682 }
683 // EDIFACT
684 sl = bl = 0;
685 if (s[p + 0] >= 32 && s[p + 0] <= 94) { // can encode 1
686 char bs = 0;
687 if (p + 1 == l) {
688 bl = 2;
689 bs = 1;
690 } else
691 for (e = 0; e < E_MAX; e++)
692 if (e != E_EDIFACT && enc[p + 1][e].t
693 &&
694 ((t =
695 2 + enc[p + 1][e].t +
696 switchcost[E_ASCII][e])
697 < bl || !bl)) // E_ASCII as allowed for unlatch
698 {
699 bs = 1;
700 bl = t;
701 b = e;
702 }
703 if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94) { // can encode 2
704 if (p + 2 == l) {
705 if (!bl || bl > 2) {
706 bl = 3;
707 bs = 2;
708 }
709 } else
710 for (e = 0; e < E_MAX; e++)
711 if (e != E_EDIFACT
712 && enc[p + 2][e].t
713 &&
714 ((t =
715 3 + enc[p + 2][e].t +
716 switchcost[E_ASCII][e])
717 < bl || !bl)) // E_ASCII as allowed for unlatch
718 {
719 bs = 2;
720 bl = t;
721 b = e;
722 }
723 if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94) { // can encode 3
724 if (p + 3 == l) {
725 if (!bl || bl > 3) {
726 bl = 3;
727 bs = 3;
728 }
729 } else
730 for (e = 0; e < E_MAX; e++)
731 if (e != E_EDIFACT
732 && enc[p + 3][e].t
733 &&
734 ((t =
735 3 + enc[p +
736 3][e].t +
737 switchcost
738 [E_ASCII][e])
739 < bl || !bl)) // E_ASCII as allowed for unlatch
740 {
741 bs = 3;
742 bl = t;
743 b = e;
744 }
745 if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94) { // can encode 4
746 if (p + 4 == l) {
747 if (!bl || bl > 3) {
748 bl = 3;
749 bs = 4;
750 }
751 } else {
752 for (e = 0; e < E_MAX;
753 e++)
754 if (enc[p + 4]
755 [e].t
756 &&
757 ((t =
758 3 +
759 enc[p +
760 4][e].
761 t +
762 switchcost
763 [E_EDIFACT]
764 [e]) < bl
765 || !bl)) {
766 bs = 4;
767 bl = t;
768 b = e;
769 }
770 if (exact
771 && enc[p +
772 4][E_ASCII].t
773 && enc[p +
774 4][E_ASCII].
775 t <= 2
776 && (t =
777 3 + enc[p +
778 4]
779 [E_ASCII].t) <
780 bl) {
781 // special case, switch to ASCII for last 1 ot two bytes
782 bs = 4;
783 bl = t;
784 b = E_ASCII;
785 }
786 }
787 }
788 }
789 }
790 enc[p][E_EDIFACT].t = bl;
791 enc[p][E_EDIFACT].s = bs;
792 if (bl && b == E_EDIFACT)
793 enc[p][b].s += enc[p + bs][b].s;
794 }
795 // Binary
796 bl = 0;
797 for (e = 0; e < E_MAX; e++)
798 if (enc[p + 1][e].t
799 &&
800 ((t =
801 enc[p + 1][e].t + switchcost[E_BINARY][e] +
802 ((e == E_BINARY
803 && enc[p + 1][e].t == 249) ? 1 : 0))
804 < bl || !bl)) {
805 bl = t;
806 b = e;
807 }
808 enc[p][E_BINARY].t = 1 + bl;
809 enc[p][E_BINARY].s = 1;
810 if (bl && b == E_BINARY)
811 enc[p][b].s += enc[p + 1][b].s;
812 /*
813 * fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf \
814 * (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); \
815 * fprintf (stderr, "\n");
816 */
817 }
818 encoding = safemalloc(1, l + 1);
819 p = 0;
820 {
821 int cur = E_ASCII; // starts ASCII
822 while (p < l) {
823 int t, m = 0;
824 int b = 0;
825 for (e = 0; e < E_MAX; e++)
826 if (enc[p][e].t
827 && ((t = enc[p][e].t + switchcost[cur][e]) <
828 m || t == m && e == cur || !m)) {
829 b = e;
830 m = t;
831 }
832 cur = b;
833 m = enc[p][b].s;
834 if (!p && lenp)
835 *lenp = enc[p][b].t;
836 while (p < l && m--)
837 encoding[p++] = encchr[b];
838 }
839 }
840 encoding[p] = 0;
841 return encoding;
842 }
843
iec16022ecc200(int * Wptr,int * Hptr,char ** encodingptr,int barcodelen,const unsigned char * barcode,int * lenp,int * maxp,int * eccp)844 unsigned char *iec16022ecc200(int *Wptr, int *Hptr, char **encodingptr,
845 int barcodelen, const unsigned char *barcode,
846 int *lenp, int *maxp, int *eccp)
847 {
848 return iec16022ecc200f(Wptr, Hptr, encodingptr, barcodelen, barcode, lenp, maxp, eccp, 0);
849 }
850
851 /*
852 * Main encoding function
853 * Returns the grid (malloced) containing the matrix. L corner at 0,0.
854 * Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
855 * Takes barcodelen and barcode to be encoded
856 * Note, if *encodingptr is null, then fills with auto picked (malloced)
857 * encoding
858 * If lenp not null, then the length of encoded data before any final
859 * unlatch or pad is stored
860 * If maxp not null, then the max storage of this size code is stored
861 * If eccp not null, then the number of ecc bytes used in this size is
862 * stored
863 * Returns 0 on error (writes to stderr with details).
864 */
865
iec16022ecc200f(int * Wptr,int * Hptr,char ** encodingptr,int barcodelen,const unsigned char * barcode,int * lenp,int * maxp,int * eccp,int flags)866 unsigned char *iec16022ecc200f(int *Wptr, int *Hptr, char **encodingptr,
867 int barcodelen, const unsigned char *barcode,
868 int *lenp, int *maxp, int *eccp, int flags)
869 {
870 unsigned char binary[3000]; // encoded raw data and ecc to place in barcode
871 int W = 0, H = 0;
872 char *encoding = 0;
873 unsigned char *grid = 0;
874 const struct ecc200matrix_s *matrix;
875 memset(binary, 0, sizeof(binary));
876 if (encodingptr)
877 encoding = *encodingptr;
878 if (Wptr)
879 W = *Wptr;
880 if (Hptr)
881 H = *Hptr;
882
883 // encoding
884 if (W) { // known size
885 for (matrix = ecc200matrix; matrix->W && (matrix->W != W ||
886 matrix->H != H);
887 matrix++) ;
888 if (!matrix->W) {
889 fprintf(stderr, "Invalid size %dx%d\n", W, H);
890 return 0;
891 }
892 if (!encoding) {
893 int len;
894 char *e = encmake(barcodelen, barcode, &len, 1);
895 if (e && len != matrix->bytes) { // try not an exact fit
896 free(e);
897 e = encmake(barcodelen, barcode, &len, 0);
898 if (len > matrix->bytes) {
899 fprintf(stderr,
900 "Cannot make barcode fit %dx%d\n",
901 W, H);
902 return 0;
903 }
904 }
905 encoding = e;
906 }
907 } else {
908 // find a suitable encoding
909 if (encoding == NULL)
910 encoding = encmake(barcodelen, barcode, NULL, 1);
911
912 if (encoding) { // find one that fits chosen encoding
913 for (matrix = ecc200matrix; matrix->W; matrix++)
914 if (ecc200encode
915 (binary, matrix->bytes, barcode, barcodelen,
916 encoding, 0, flags))
917 break;
918 } else {
919 int len;
920 char *e;
921 e = encmake(barcodelen, barcode, &len, 1);
922 for (matrix = ecc200matrix;
923 matrix->W && matrix->bytes != len; matrix++) ;
924 if (e && !matrix->W) { // try for non exact fit
925 free(e);
926 e = encmake(barcodelen, barcode, &len, 0);
927 for (matrix = ecc200matrix;
928 matrix->W && matrix->bytes < len;
929 matrix++) ;
930 }
931 encoding = e;
932 }
933 if (!matrix->W) {
934 fprintf(stderr,
935 "Cannot find suitable size, barcode too long\n");
936 if (!encodingptr || encoding != *encodingptr)
937 free(encoding);
938 return 0;
939 }
940 W = matrix->W;
941 H = matrix->H;
942 }
943 if (!encoding) {
944 fprintf(stderr,
945 "Barcode too long, could not find encoding\n");
946 return 0;
947 }
948 if (!ecc200encode(binary, matrix->bytes, barcode, barcodelen,
949 encoding, lenp, flags)) {
950 fprintf(stderr, "Barcode too long for %dx%d\n", W, H);
951 if (!encodingptr || encoding != *encodingptr)
952 free(encoding);
953 return 0;
954 }
955 // ecc code
956 ecc200(binary, matrix->bytes, matrix->datablock, matrix->rsblock);
957 { // placement
958 int border_offset_y;
959 int x, y, NC, NR, *places;
960 NC = W - 2 * (W / matrix->FW);
961 NR = H - 2 * (H / matrix->FH);
962 places = safemalloc(NC, NR * sizeof(int));
963 ecc200placement(places, NR, NC);
964 grid = safemalloc(H, W + 16); // extra padding to simplify some operations
965 for (y = 0; y < H; y += matrix->FH) {
966 memset(grid + y * W, 1, W);
967 for (x = 0; x < W; x += 2)
968 grid[(y + matrix->FH - 1) * W + x] = 1;
969 }
970 for (x = 0; x < W; x += matrix->FW) {
971 for (y = 0; y < H; y++)
972 grid[y * W + x] = 1;
973 for (y = 0; y < H; y += 2)
974 grid[y * W + x + matrix->FW - 1] = 1;
975 }
976 border_offset_y = -1;
977 for (y = 0; y < NR; y++) {
978 int border_offset_x = -1;
979 // jump over the 2 border pixels
980 if (y % (matrix->FH - 2) == 0) border_offset_y += 2;
981 for (x = 0; x < NC; x++) {
982 int v = places[(NR - y - 1) * NC + x];
983 // jump over the 2 border pixels
984 if (x % (matrix->FW - 2) == 0) border_offset_x += 2;
985 //fprintf (stderr, "%4d", v);
986 if (v == 1 || v > 7
987 && (binary[(v >> 3) - 1] & (1 << (v & 7))))
988 grid[(y + border_offset_y) * W +
989 x + border_offset_x] = 1;
990 }
991 //fprintf (stderr, "\n");
992 }
993 free(places);
994 }
995 if (Wptr)
996 *Wptr = W;
997 if (Hptr)
998 *Hptr = H;
999 if (encodingptr)
1000 *encodingptr = encoding;
1001 if (maxp)
1002 *maxp = matrix->bytes;
1003 if (eccp)
1004 *eccp =
1005 (matrix->bytes + 2) / matrix->datablock * matrix->rsblock;
1006 return grid;
1007 }
1008