-/**
+/**
*
* IEC16022 bar code generation
* Adrian Kennard, Andrews & Arnold Ltd
* with help from Cliff Hones on the RS coding
- *
+ *
* (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
- * (c) 2006 Stefan Schmidt <stefan@datenfreihafen.org>
- *
+ * (c) 2006-2007 Stefan Schmidt <stefan@datenfreihafen.org>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
*
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "reedsol.h"
#include "iec16022ecc200.h"
-static struct ecc200matrix_s
-{
- int H,
- W;
- int FH,
- FW;
- int bytes;
- int datablock,
- rsblock;
-}
-ecc200matrix[] =
-{
- 10, 10, 10, 10, 3, 3, 5, //
- 12, 12, 12, 12, 5, 5, 7, //
- 8, 18, 8, 18, 5, 5, 7, //
- 14, 14, 14, 14, 8, 8, 10, //
- 8, 32, 8, 16, 10, 10, 11, //
- 16, 16, 16, 16, 12, 12, 12, //
- 12, 26, 12, 26, 16, 16, 14, //
- 18, 18, 18, 18, 18, 18, 14, //
- 20, 20, 20, 20, 22, 22, 18, //
- 12, 36, 12, 18, 22, 22, 18, //
- 22, 22, 22, 22, 30, 30, 20, //
- 16, 36, 16, 18, 32, 32, 24, //
- 24, 24, 24, 24, 36, 36, 24, //
- 26, 26, 26, 26, 44, 44, 28, //
- 16, 48, 16, 24, 49, 49, 28, //
- 32, 32, 16, 16, 62, 62, 36, //
- 36, 36, 18, 18, 86, 86, 42, //
- 40, 40, 20, 20, 114, 114, 48, //
- 44, 44, 22, 22, 144, 144, 56, //
- 48, 48, 24, 24, 174, 174, 68, //
- 52, 52, 26, 26, 204, 102, 42, //
- 64, 64, 16, 16, 280, 140, 56, //
- 72, 72, 18, 18, 368, 92, 36, //
- 80, 80, 20, 20, 456, 114, 48, //
- 88, 88, 22, 22, 576, 144, 56, //
- 96, 96, 24, 24, 696, 174, 68, //
- 104, 104, 26, 26, 816, 136, 56, //
- 120, 120, 20, 20, 1050, 175, 68, //
- 132, 132, 22, 22, 1304, 163, 62, //
- 144, 144, 24, 24, 1558, 156, 62, // 156*4+155*2
- 0 // terminate
+static struct ecc200matrix_s {
+ int H, W;
+ int FH, FW;
+ int bytes;
+ int datablock, rsblock;
+} ecc200matrix[] = {
+ 10, 10, 10, 10, 3, 3, 5, //
+ 12, 12, 12, 12, 5, 5, 7, //
+ 8, 18, 8, 18, 5, 5, 7, //
+ 14, 14, 14, 14, 8, 8, 10, //
+ 8, 32, 8, 16, 10, 10, 11, //
+ 16, 16, 16, 16, 12, 12, 12, //
+ 12, 26, 12, 26, 16, 16, 14, //
+ 18, 18, 18, 18, 18, 18, 14, //
+ 20, 20, 20, 20, 22, 22, 18, //
+ 12, 36, 12, 18, 22, 22, 18, //
+ 22, 22, 22, 22, 30, 30, 20, //
+ 16, 36, 16, 18, 32, 32, 24, //
+ 24, 24, 24, 24, 36, 36, 24, //
+ 26, 26, 26, 26, 44, 44, 28, //
+ 16, 48, 16, 24, 49, 49, 28, //
+ 32, 32, 16, 16, 62, 62, 36, //
+ 36, 36, 18, 18, 86, 86, 42, //
+ 40, 40, 20, 20, 114, 114, 48, //
+ 44, 44, 22, 22, 144, 144, 56, //
+ 48, 48, 24, 24, 174, 174, 68, //
+ 52, 52, 26, 26, 204, 102, 42, //
+ 64, 64, 16, 16, 280, 140, 56, //
+ 72, 72, 18, 18, 368, 92, 36, //
+ 80, 80, 20, 20, 456, 114, 48, //
+ 88, 88, 22, 22, 576, 144, 56, //
+ 96, 96, 24, 24, 696, 174, 68, //
+ 104, 104, 26, 26, 816, 136, 56, //
+ 120, 120, 20, 20, 1050, 175, 68, //
+ 132, 132, 22, 22, 1304, 163, 62, //
+ 144, 144, 24, 24, 1558, 156, 62, // 156*4+155*2
+ 0 // terminate
};
// simple checked response malloc
-static void * safemalloc (int n)
+static void *safemalloc(int n)
{
- void *p = malloc (n);
- if (!p)
- {
- fprintf (stderr, "Malloc(%d) failed\n", n);
- exit (1);
- }
- return p;
+ void *p = malloc(n);
+ if (!p) {
+ fprintf(stderr, "Malloc(%d) failed\n", n);
+ exit(1);
+ }
+ return p;
}
// Annex M placement alorithm low level
-static void ecc200placementbit (int *array, int NR, int NC, int r, int c, \
- int p, char b)
+static void ecc200placementbit(int *array, int NR, int NC, int r, int c,
+ int p, char b)
{
- if (r < 0)
- {
- r += NR;
- c += 4 - ((NR + 4) % 8);
- }
- if (c < 0)
- {
- c += NC;
- r += 4 - ((NC + 4) % 8);
- }
- array[r * NC + c] = (p << 3) + b;
+ if (r < 0) {
+ r += NR;
+ c += 4 - ((NR + 4) % 8);
+ }
+ if (c < 0) {
+ c += NC;
+ r += 4 - ((NC + 4) % 8);
+ }
+ array[r * NC + c] = (p << 3) + b;
}
-static void ecc200placementblock (int *array, int NR, int NC, int r, \
- int c, int p)
+static void ecc200placementblock(int *array, int NR, int NC, int r,
+ int c, int p)
{
- ecc200placementbit (array, NR, NC, r - 2, c - 2, p, 7);
- ecc200placementbit (array, NR, NC, r - 2, c - 1, p, 6);
- ecc200placementbit (array, NR, NC, r - 1, c - 2, p, 5);
- ecc200placementbit (array, NR, NC, r - 1, c - 1, p, 4);
- ecc200placementbit (array, NR, NC, r - 1, c - 0, p, 3);
- ecc200placementbit (array, NR, NC, r - 0, c - 2, p, 2);
- ecc200placementbit (array, NR, NC, r - 0, c - 1, p, 1);
- ecc200placementbit (array, NR, NC, r - 0, c - 0, p, 0);
+ ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7);
+ ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6);
+ ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5);
+ ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4);
+ ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3);
+ ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2);
+ ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1);
+ ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0);
}
-static void ecc200placementcornerA (int *array, int NR, int NC, int p)
+static void ecc200placementcornerA(int *array, int NR, int NC, int p)
{
- ecc200placementbit (array, NR, NC, NR - 1, 0, p, 7);
- ecc200placementbit (array, NR, NC, NR - 1, 1, p, 6);
- ecc200placementbit (array, NR, NC, NR - 1, 2, p, 5);
- ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
- ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
- ecc200placementbit (array, NR, NC, 1, NC - 1, p, 2);
- ecc200placementbit (array, NR, NC, 2, NC - 1, p, 1);
- ecc200placementbit (array, NR, NC, 3, NC - 1, p, 0);
+ ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
+ ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6);
+ ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5);
+ ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
+ ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
+ ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
}
-static void ecc200placementcornerB (int *array, int NR, int NC, int p)
+static void ecc200placementcornerB(int *array, int NR, int NC, int p)
{
- ecc200placementbit (array, NR, NC, NR - 3, 0, p, 7);
- ecc200placementbit (array, NR, NC, NR - 2, 0, p, 6);
- ecc200placementbit (array, NR, NC, NR - 1, 0, p, 5);
- ecc200placementbit (array, NR, NC, 0, NC - 4, p, 4);
- ecc200placementbit (array, NR, NC, 0, NC - 3, p, 3);
- ecc200placementbit (array, NR, NC, 0, NC - 2, p, 2);
- ecc200placementbit (array, NR, NC, 0, NC - 1, p, 1);
- ecc200placementbit (array, NR, NC, 1, NC - 1, p, 0);
+ ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
+ ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
+ ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
+ ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4);
+ ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3);
+ ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2);
+ ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1);
+ ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
}
-static void ecc200placementcornerC (int *array, int NR, int NC, int p)
+static void ecc200placementcornerC(int *array, int NR, int NC, int p)
{
- ecc200placementbit (array, NR, NC, NR - 3, 0, p, 7);
- ecc200placementbit (array, NR, NC, NR - 2, 0, p, 6);
- ecc200placementbit (array, NR, NC, NR - 1, 0, p, 5);
- ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
- ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
- ecc200placementbit (array, NR, NC, 1, NC - 1, p, 2);
- ecc200placementbit (array, NR, NC, 2, NC - 1, p, 1);
- ecc200placementbit (array, NR, NC, 3, NC - 1, p, 0);
+ ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
+ ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
+ ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
+ ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
+ ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
+ ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
}
-static void ecc200placementcornerD (int *array, int NR, int NC, int p)
+static void ecc200placementcornerD(int *array, int NR, int NC, int p)
{
- ecc200placementbit (array, NR, NC, NR - 1, 0, p, 7);
- ecc200placementbit (array, NR, NC, NR - 1, NC - 1, p, 6);
- ecc200placementbit (array, NR, NC, 0, NC - 3, p, 5);
- ecc200placementbit (array, NR, NC, 0, NC - 2, p, 4);
- ecc200placementbit (array, NR, NC, 0, NC - 1, p, 3);
- ecc200placementbit (array, NR, NC, 1, NC - 3, p, 2);
- ecc200placementbit (array, NR, NC, 1, NC - 2, p, 1);
- ecc200placementbit (array, NR, NC, 1, NC - 1, p, 0);
+ ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
+ ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
+ ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5);
+ ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
+ ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
+ ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2);
+ ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1);
+ ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
}
// Annex M placement alorithm main function
-static void ecc200placement (int *array, int NR, int NC)
+static void ecc200placement(int *array, int NR, int NC)
{
- int r,
- c,
- p;
- // invalidate
- for (r = 0; r < NR; r++)
- for (c = 0; c < NC; c++)
- array[r * NC + c] = 0;
- // start
- p = 1;
- r = 4;
- c = 0;
- do
- {
- // check corner
- if (r == NR && !c)
- ecc200placementcornerA (array, NR, NC, p++);
- if (r == NR - 2 && !c && NC % 4)
- ecc200placementcornerB (array, NR, NC, p++);
- if (r == NR - 2 && !c && (NC % 8) == 4)
- ecc200placementcornerC (array, NR, NC, p++);
- if (r == NR + 4 && c == 2 && !(NC % 8))
- ecc200placementcornerD (array, NR, NC, p++);
- // up/right
- do
- {
- if (r < NR && c >= 0 && !array[r * NC + c])
- ecc200placementblock (array, NR, NC, r, c, p++);
- r -= 2;
- c += 2;
- }
- while (r >= 0 && c < NC);
- r++;
- c += 3;
- // down/left
- do
- {
- if (r >= 0 && c < NC && !array[r * NC + c])
- ecc200placementblock (array, NR, NC, r, c, p++);
- r += 2;
- c -= 2;
- }
- while (r < NR && c >= 0);
- r += 3;
- c++;
- }
- while (r < NR || c < NC);
- // unfilled corner
- if (!array[NR * NC - 1])
- array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
+ int r, c, p;
+ // invalidate
+ for (r = 0; r < NR; r++)
+ for (c = 0; c < NC; c++)
+ array[r * NC + c] = 0;
+ // start
+ p = 1;
+ r = 4;
+ c = 0;
+ do {
+ // check corner
+ if (r == NR && !c)
+ ecc200placementcornerA(array, NR, NC, p++);
+ if (r == NR - 2 && !c && NC % 4)
+ ecc200placementcornerB(array, NR, NC, p++);
+ if (r == NR - 2 && !c && (NC % 8) == 4)
+ ecc200placementcornerC(array, NR, NC, p++);
+ if (r == NR + 4 && c == 2 && !(NC % 8))
+ ecc200placementcornerD(array, NR, NC, p++);
+ // up/right
+ do {
+ if (r < NR && c >= 0 && !array[r * NC + c])
+ ecc200placementblock(array, NR, NC, r, c, p++);
+ r -= 2;
+ c += 2;
+ }
+ while (r >= 0 && c < NC);
+ r++;
+ c += 3;
+ // down/left
+ do {
+ if (r >= 0 && c < NC && !array[r * NC + c])
+ ecc200placementblock(array, NR, NC, r, c, p++);
+ r += 2;
+ c -= 2;
+ }
+ while (r < NR && c >= 0);
+ r += 3;
+ c++;
+ }
+ while (r < NR || c < NC);
+ // unfilled corner
+ if (!array[NR * NC - 1])
+ array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
}
// calculate and append ecc code, and if necessary interleave
-static void ecc200 (unsigned char *binary, int bytes, int datablock, \
- int rsblock)
+static void ecc200(unsigned char *binary, int bytes, int datablock, int rsblock)
{
- int blocks = (bytes + 2) / datablock,
- b;
- rs_init_gf (0x12d);
- rs_init_code (rsblock, 1);
- for (b = 0; b < blocks; b++)
- {
- unsigned char buf[256],
- ecc[256];
- int n,
- p = 0;
- for (n = b; n < bytes; n += blocks)
- buf[p++] = binary[n];
- rs_encode (p, buf, ecc);
- p = rsblock - 1; // comes back reversed
- for (n = b; n < rsblock * blocks; n += blocks)
- binary[bytes + n] = ecc[p--];
- }
+ int blocks = (bytes + 2) / datablock, b;
+ rs_init_gf(0x12d);
+ rs_init_code(rsblock, 1);
+ for (b = 0; b < blocks; b++) {
+ unsigned char buf[256], ecc[256];
+ int n, p = 0;
+ for (n = b; n < bytes; n += blocks)
+ buf[p++] = binary[n];
+ rs_encode(p, buf, ecc);
+ p = rsblock - 1; // comes back reversed
+ for (n = b; n < rsblock * blocks; n += blocks)
+ binary[bytes + n] = ecc[p--];
+ }
}
/*
- * perform encoding for ecc200, source s len sl, to target t len tl, using
- * optional encoding control string e return 1 if OK, 0 if failed. Does all
+ * perform encoding for ecc200, source s len sl, to target t len tl, using
+ * optional encoding control string e return 1 if OK, 0 if failed. Does all
* necessary padding to tl
*/
-char ecc200encode (unsigned char *t, int tl, unsigned char *s, int sl, \
- char *encoding, int *lenp)
+char ecc200encode(unsigned char *t, int tl, unsigned char *s, int sl,
+ char *encoding, int *lenp)
{
- char enc = 'a'; // start in ASCII encoding mode
- int tp = 0,
- sp = 0;
- if (strlen (encoding) < sl)
- {
- fprintf (stderr, "Encoding string too short\n");
- return 0;
- }
- // do the encoding
- while (sp < sl && tp < tl)
- {
- char newenc = enc; // suggest new encoding
- if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2 && enc \
- == 'x')
- enc = 'a'; // auto revert to ASCII
- newenc = tolower (encoding[sp]);
- switch (newenc)
- { // encode character
- case 'c': // C40
- case 't': // Text
- case 'x': // X12
- {
- char out[6],
- p = 0;
- const char *e,
- *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]_",
- *s3 = 0;
- if (newenc == 'c')
- {
- e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
- }
- if (newenc == 't')
- {
- e = " 0123456789abcdefghijklmnopqrstuvwxyz";
- s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
- }
- if (newenc == 'x')
- e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>";
- do
- {
- unsigned char c = s[sp++];
- char *w;
- if (c & 0x80)
- {
- if (newenc == 'x')
- {
- fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c);
- return 0;
- }
- c &= 0x7f;
- out[p++] = 1;
- out[p++] = 30;
- }
- w = strchr (e, c);
- if (w)
- out[p++] = ((w - e) + 3) % 40;
- else
- {
- if (newenc == 'x')
- {
- fprintf (stderr, "Cannot encode char 0x%02X in X12\n", c);
- return 0;
- }
- if (c < 32)
- { // shift 1
- out[p++] = 0;
- out[p++] = c;
- } else
- {
- w = strchr (s2, c);
- if (w)
- { // shift 2
- out[p++] = 1;
- out[p++] = (w - s2);
- } else
- {
- w = strchr (s3, c);
- if (w)
- {
- out[p++] = 2;
- out[p++] = (w - s3);
- } else
- {
- fprintf (stderr, "Could not encode 0x%02X, should \
- not happen\n", c);
- return 0;
- }
- }
- }
- }
- if (p == 2 && tp + 2 == tl && sp == sl)
- out[p++] = 0; // shift 1 pad at end
- while (p >= 3)
- {
- int v = out[0] * 1600 + out[1] * 40 + out[2] + 1;
- if (enc != newenc)
- {
- if (enc == 'c' || enc == 't' || enc == 'x')
- t[tp++] = 254; // escape C40/text/X12
- else if (enc == 'x')
- t[tp++] = 0x7C; // escape EDIFACT
- if (newenc == 'c')
- t[tp++] = 230;
- if (newenc == 't')
- t[tp++] = 239;
- if (newenc == 'x')
- t[tp++] = 238;
- enc = newenc;
- }
- t[tp++] = (v >> 8);
- t[tp++] = (v & 0xFF);
- p -= 3;
- out[0] = out[3];
- out[1] = out[4];
- out[2] = out[5];
- }
- }
- while (p && sp < sl);
- }
- break;
- case 'e': // EDIFACT
- {
- unsigned char out[4],
- p = 0;
- if (enc != newenc)
- { // can only be from C40/Text/X12
- t[tp++] = 254;
- enc = 'a';
- }
- while (sp < sl && tolower (encoding[sp]) == 'e' && p < 4)
- out[p++] = s[sp++];
- if (p < 4)
- {
- out[p++] = 0x1F;
- enc = 'a';
- } // termination
- t[tp] = ((s[0] & 0x3F) << 2);
- t[tp++] |= ((s[1] & 0x30) >> 4);
- t[tp] = ((s[1] & 0x0F) << 4);
- if (p == 2)
- tp++;
- else
- {
- t[tp++] |= ((s[2] & 0x3C) >> 2);
- t[tp] = ((s[2] & 0x03) << 6);
- t[tp++] |= (s[3] & 0x3F);
- }
- }
- break;
- case 'a': // ASCII
- if (enc != newenc)
- {
- if (enc == 'c' || enc == 't' || enc == 'x')
- t[tp++] = 254; // escape C40/text/X12
- else
- t[tp++] = 0x7C; // escape EDIFACT
- }
- enc = 'a';
- if (sl - sp >= 2 && isdigit (s[sp]) && isdigit (s[sp + 1]))
- {
- t[tp++] = (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130;
- sp += 2;
- } else if (s[sp] > 127)
- {
- t[tp++] = 235;
- t[tp++] = s[sp++] - 127;
- } else
- t[tp++] = s[sp++] + 1;
- break;
- case 'b': // Binary
- {
- int l = 0; // how much to encode
- if (encoding)
- {
- int p;
- for (p = sp; p < sl && tolower (encoding[p]) == 'b'; p++)
- l++;
- }
- t[tp++] = 231; // base256
- if (l < 250)
- t[tp++] = l;
- else
- {
- t[tp++] = 249 + (l / 250);
- t[tp++] = (l % 250);
- }
- while (l-- && tp < tl)
- {
- t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H
- tp++;
- }
- enc = 'a'; // reverse to ASCII at end
- }
- break;
- default:
- fprintf (stderr, "Unknown encoding %c\n", newenc);
- return 0; // failed
- }
- }
- if (lenp)
- *lenp = tp;
- if (tp < tl && enc != 'a')
- {
- if (enc == 'c' || enc == 'x' || enc == 't')
- t[tp++] = 254; // escape X12/C40/Text
- else
- t[tp++] = 0x7C; // escape EDIFACT
- }
- if (tp < tl)
- t[tp++] = 129; // pad
- while (tp < tl)
- { // more padding
- int v = 129 + (((tp + 1) * 149) % 253) + 1; // see Annex H
- if (v > 254)
- v -= 254;
- t[tp++] = v;
- }
- if (tp > tl || sp < sl)
- return 0; // did not fit
- /*
- * for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); \
- * fprintf (stderr, "\n");
- */
- return 1; // OK
+ char enc = 'a'; // start in ASCII encoding mode
+ int tp = 0, sp = 0;
+ if (strlen(encoding) < sl) {
+ fprintf(stderr, "Encoding string too short\n");
+ return 0;
+ }
+ // do the encoding
+ while (sp < sl && tp < tl) {
+ char newenc = enc; // suggest new encoding
+ if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2
+ && enc == 'x')
+ enc = 'a'; // auto revert to ASCII
+ newenc = tolower(encoding[sp]);
+ switch (newenc) { // encode character
+ case 'c': // C40
+ case 't': // Text
+ case 'x': // X12
+ {
+ char out[6], p = 0;
+ const char *e,
+ *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]_",
+ *s3 = 0;
+ if (newenc == 'c') {
+ e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
+ }
+ if (newenc == 't') {
+ e = " 0123456789abcdefghijklmnopqrstuvwxyz";
+ s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
+ }
+ if (newenc == 'x')
+ e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>";
+ do {
+ unsigned char c = s[sp++];
+ char *w;
+ if (c & 0x80) {
+ if (newenc == 'x') {
+ fprintf(stderr,
+ "Cannot encode char 0x%02X in X12\n",
+ c);
+ return 0;
+ }
+ c &= 0x7f;
+ out[p++] = 1;
+ out[p++] = 30;
+ }
+ w = strchr(e, c);
+ if (w)
+ out[p++] = ((w - e) + 3) % 40;
+ else {
+ if (newenc == 'x') {
+ fprintf(stderr,
+ "Cannot encode char 0x%02X in X12\n",
+ c);
+ return 0;
+ }
+ if (c < 32) { // shift 1
+ out[p++] = 0;
+ out[p++] = c;
+ } else {
+ w = strchr(s2, c);
+ if (w) { // shift 2
+ out[p++] = 1;
+ out[p++] =
+ (w - s2);
+ } else {
+ w = strchr(s3,
+ c);
+ if (w) {
+ out[p++]
+ = 2;
+ out[p++]
+ =
+ (w -
+ s3);
+ } else {
+ fprintf
+ (stderr,
+ "Could not encode 0x%02X, should \
+ not happen\n", c);
+ return
+ 0;
+ }
+ }
+ }
+ }
+ if (p == 2 && tp + 2 == tl && sp == sl)
+ out[p++] = 0; // shift 1 pad at end
+ while (p >= 3) {
+ int v =
+ out[0] * 1600 +
+ out[1] * 40 + out[2] + 1;
+ if (enc != newenc) {
+ if (enc == 'c'
+ || enc == 't'
+ || enc == 'x')
+ t[tp++] = 254; // escape C40/text/X12
+ else if (enc == 'x')
+ t[tp++] = 0x7C; // escape EDIFACT
+ if (newenc == 'c')
+ t[tp++] = 230;
+ if (newenc == 't')
+ t[tp++] = 239;
+ if (newenc == 'x')
+ t[tp++] = 238;
+ enc = newenc;
+ }
+ t[tp++] = (v >> 8);
+ t[tp++] = (v & 0xFF);
+ p -= 3;
+ out[0] = out[3];
+ out[1] = out[4];
+ out[2] = out[5];
+ }
+ }
+ while (p && sp < sl);
+ }
+ break;
+ case 'e': // EDIFACT
+ {
+ unsigned char out[4], p = 0;
+ if (enc != newenc) { // can only be from C40/Text/X12
+ t[tp++] = 254;
+ enc = 'a';
+ }
+ while (sp < sl && tolower(encoding[sp]) == 'e'
+ && p < 4)
+ out[p++] = s[sp++];
+ if (p < 4) {
+ out[p++] = 0x1F;
+ enc = 'a';
+ } // termination
+ t[tp] = ((s[0] & 0x3F) << 2);
+ t[tp++] |= ((s[1] & 0x30) >> 4);
+ t[tp] = ((s[1] & 0x0F) << 4);
+ if (p == 2)
+ tp++;
+ else {
+ t[tp++] |= ((s[2] & 0x3C) >> 2);
+ t[tp] = ((s[2] & 0x03) << 6);
+ t[tp++] |= (s[3] & 0x3F);
+ }
+ }
+ break;
+ case 'a': // ASCII
+ if (enc != newenc) {
+ if (enc == 'c' || enc == 't' || enc == 'x')
+ t[tp++] = 254; // escape C40/text/X12
+ else
+ t[tp++] = 0x7C; // escape EDIFACT
+ }
+ enc = 'a';
+ if (sl - sp >= 2 && isdigit(s[sp])
+ && isdigit(s[sp + 1])) {
+ t[tp++] =
+ (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130;
+ sp += 2;
+ } else if (s[sp] > 127) {
+ t[tp++] = 235;
+ t[tp++] = s[sp++] - 127;
+ } else
+ t[tp++] = s[sp++] + 1;
+ break;
+ case 'b': // Binary
+ {
+ int l = 0; // how much to encode
+ if (encoding) {
+ int p;
+ for (p = sp;
+ p < sl
+ && tolower(encoding[p]) == 'b';
+ p++)
+ l++;
+ }
+ t[tp++] = 231; // base256
+ if (l < 250)
+ t[tp++] = l;
+ else {
+ t[tp++] = 249 + (l / 250);
+ t[tp++] = (l % 250);
+ }
+ while (l-- && tp < tl) {
+ t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H
+ tp++;
+ }
+ enc = 'a'; // reverse to ASCII at end
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown encoding %c\n", newenc);
+ return 0; // failed
+ }
+ }
+ if (lenp)
+ *lenp = tp;
+ if (tp < tl && enc != 'a') {
+ if (enc == 'c' || enc == 'x' || enc == 't')
+ t[tp++] = 254; // escape X12/C40/Text
+ else
+ t[tp++] = 0x7C; // escape EDIFACT
+ }
+ if (tp < tl)
+ t[tp++] = 129; // pad
+ while (tp < tl) { // more padding
+ int v = 129 + (((tp + 1) * 149) % 253) + 1; // see Annex H
+ if (v > 254)
+ v -= 254;
+ t[tp++] = v;
+ }
+ if (tp > tl || sp < sl)
+ return 0; // did not fit
+ /*
+ * for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); \
+ * fprintf (stderr, "\n");
+ */
+ return 1; // OK
}
// Auto encoding format functions
static char encchr[] = "ACTXEB";
-enum
-{
- E_ASCII,
- E_C40,
- E_TEXT,
- E_X12,
- E_EDIFACT,
- E_BINARY,
- E_MAX
+enum {
+ E_ASCII,
+ E_C40,
+ E_TEXT,
+ E_X12,
+ E_EDIFACT,
+ E_BINARY,
+ E_MAX
};
unsigned char switchcost[E_MAX][E_MAX] = {
- 0, 1, 1, 1, 1, 2, // From E_ASCII
- 1, 0, 2, 2, 2, 3, // From E_C40
- 1, 2, 0, 2, 2, 3, // From E_TEXT
- 1, 2, 2, 0, 2, 3, // From E_X12
- 1, 2, 2, 2, 0, 3, // From E_EDIFACT
- 0, 1, 1, 1, 1, 0, // From E_BINARY
+ 0, 1, 1, 1, 1, 2, // From E_ASCII
+ 1, 0, 2, 2, 2, 3, // From E_C40
+ 1, 2, 0, 2, 2, 3, // From E_TEXT
+ 1, 2, 2, 0, 2, 3, // From E_X12
+ 1, 2, 2, 2, 0, 3, // From E_EDIFACT
+ 0, 1, 1, 1, 1, 0, // From E_BINARY
};
/*
* returns encoding string
* if lenp not null, target len stored
* if error, null returned
- * if exact specified, then assumes shortcuts applicable for exact fit
+ * if exact specified, then assumes shortcuts applicable for exact fit
* in target
- * 1. No unlatch to return to ASCII for last encoded byte after C40 or
+ * 1. No unlatch to return to ASCII for last encoded byte after C40 or
* Text or X12
- * 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after
+ * 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after
* EDIFACT
- * 3. Final C40 or text encoding exactly in last 2 bytes can have a shift
+ * 3. Final C40 or text encoding exactly in last 2 bytes can have a shift
* 0 to pad to make a tripple
- * Only use the encoding from an exact request if the len matches the target,
+ * Only use the encoding from an exact request if the len matches the target,
* otherwise free the result and try again with exact=0
*/
-static char * encmake (int l, unsigned char *s, int *lenp, char exact)
+static char *encmake(int l, unsigned char *s, int *lenp, char exact)
{
- char *encoding = 0;
- int p = l;
- char e;
- struct
- {
- // number of bytes of source that can be encoded in a row at this point
- // using this encoding mode
- short s;
- // number of bytes of target generated encoding from this point to end if
- // already in this encoding mode
- short t;
- } enc[MAXBARCODE][E_MAX];
- memset (&enc, 0, sizeof (enc));
- if (!l)
- return ""; // no length
- if (l > MAXBARCODE)
- return 0; // not valid
- while (p--)
- {
- char b = 0,
- sub;
- int sl,
- tl,
- bl,
- t;
- // consider each encoding from this point
- // ASCII
- sl = tl = 1;
- if (isdigit (s[p]) && p + 1 < l && isdigit (s[p + 1]))
- sl = 2; // double digit
- else if (s[p] & 0x80)
- tl = 2; // high shifted
- bl = 0;
- if (p + sl < l)
- for (e = 0; e < E_MAX; e++)
- if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + \
- switchcost[E_ASCII][e]) < bl || !bl))
- {
- bl = t;
- b = e;
- }
- enc[p][E_ASCII].t = tl + bl;
- enc[p][E_ASCII].s = sl;
- if (bl && b == E_ASCII)
- enc[p][b].s += enc[p + sl][b].s;
- // C40
- sub = tl = sl = 0;
- do
- {
- unsigned char c = s[p + sl++];
- if (c & 0x80)
- { // shift + upper
- sub += 2;
- c &= 0x7F;
- }
- if (c != ' ' && !isdigit (c) && !isupper (c))
- sub++; // shift
- sub++;
- while (sub >= 3)
- {
- sub -= 3;
- tl += 2;
- }
- } while (sub && p + sl < l);
- if (exact && sub == 2 && p + sl == l)
- {
- // special case, can encode last block with shift 0 at end (Is this
- // valid when not end of target buffer?)
- sub = 0;
- tl += 2;
- }
- if (!sub)
- { // can encode C40
- bl = 0;
- if (p + sl < l)
- for (e = 0; e < E_MAX; e++)
- if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + \
- switchcost[E_C40][e]) < bl || !bl))
- {
- bl = t;
- b = e;
- }
- if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
- {
- // special case, switch to ASCII for last bytes
- bl = 1;
- b = E_ASCII;
- }
- enc[p][E_C40].t = tl + bl;
- enc[p][E_C40].s = sl;
- if (bl && b == E_C40)
- enc[p][b].s += enc[p + sl][b].s;
- }
- // Text
- sub = tl = sl = 0;
- do
- {
- unsigned char c = s[p + sl++];
- if (c & 0x80)
- { // shift + upper
- sub += 2;
- c &= 0x7F;
- }
- if (c != ' ' && !isdigit (c) && !islower (c))
- sub++; // shift
- sub++;
- while (sub >= 3)
- {
- sub -= 3;
- tl += 2;
- }
- } while (sub && p + sl < l);
- if (exact && sub == 2 && p + sl == l)
- {
- // special case, can encode last block with shift 0 at end (Is this
- // valid when not end of target buffer?)
- sub = 0;
- tl += 2;
- }
- if (!sub && sl)
- { // can encode Text
- bl = 0;
- if (p + sl < l)
- for (e = 0; e < E_MAX; e++)
- if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + \
- switchcost[E_TEXT][e]) < bl || !bl))
- {
- bl = t;
- b = e;
- }
- if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
- { // special case, switch to ASCII for last bytes
- bl = 1;
- b = E_ASCII;
- }
- enc[p][E_TEXT].t = tl + bl;
- enc[p][E_TEXT].s = sl;
- if (bl && b == E_TEXT)
- enc[p][b].s += enc[p + sl][b].s;
- }
- // X12
- sub = tl = sl = 0;
- do
- {
- unsigned char c = s[p + sl++];
- if (c != 13 && c != '*' && c != '>' && c != ' ' && !isdigit (c) && \
- !isupper (c))
- {
- sl = 0;
- break;
- }
- sub++;
- while (sub >= 3)
- {
- sub -= 3;
- tl += 2;
- }
- } while (sub && p + sl < l);
- if (!sub && sl)
- { // can encode X12
- bl = 0;
- if (p + sl < l)
- for (e = 0; e < E_MAX; e++)
- if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + \
- switchcost[E_X12][e]) < bl || !bl))
- {
- bl = t;
- b = e;
- }
- if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl)
- {
- // special case, switch to ASCII for last bytes
- bl = 1;
- b = E_ASCII;
- }
- enc[p][E_X12].t = tl + bl;
- enc[p][E_X12].s = sl;
- if (bl && b == E_X12)
- enc[p][b].s += enc[p + sl][b].s;
- }
- // EDIFACT
- sl = bl = 0;
- if (s[p + 0] >= 32 && s[p + 0] <= 94)
- { // can encode 1
- char bs = 0;
- if (p + 1 == l && (!bl || bl < 2))
- {
- bl = 2;
- bs = 1;
- } else
- for (e = 0; e < E_MAX; e++)
- if (e != E_EDIFACT && enc[p + 1][e].t && ((t = 2 + \
- enc[p + 1][e].t + switchcost[E_ASCII][e]) \
- < bl || !bl)) // E_ASCII as allowed for unlatch
- {
- bs = 1;
- bl = t;
- b = e;
- }
- if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94)
- { // can encode 2
- if (p + 2 == l && (!bl || bl < 2))
- {
- bl = 3;
- bs = 2;
- } else
- for (e = 0; e < E_MAX; e++)
- if (e != E_EDIFACT && enc[p + 2][e].t && ((t = 3 + \
- enc[p + 2][e].t + switchcost[E_ASCII][e]) \
- < bl || !bl)) // E_ASCII as allowed for unlatch
- {
- bs = 2;
- bl = t;
- b = e;
- }
- if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94)
- { // can encode 3
- if (p + 3 == l && (!bl || bl < 3))
- {
- bl = 3;
- bs = 3;
- } else
- for (e = 0; e < E_MAX; e++)
- if (e != E_EDIFACT && enc[p + 3][e].t && ((t = 3 + \
- enc[p + 3][e].t + switchcost[E_ASCII][e]) \
- < bl || !bl)) // E_ASCII as allowed for unlatch
- {
- bs = 3;
- bl = t;
- b = e;
- }
- if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94)
- { // can encode 4
- if (p + 4 == l && (!bl || bl < 3))
- {
- bl = 3;
- bs = 4;
- } else
- {
- for (e = 0; e < E_MAX; e++)
- if (enc[p + 4][e].t && ((t = 3 + enc[p + 4][e].t + \
- switchcost[E_EDIFACT][e]) < bl || !bl))
- {
- bs = 4;
- bl = t;
- b = e;
- }
- if (exact && enc[p + 4][E_ASCII].t && enc[p + \
- 4][E_ASCII].t <= 2 && (t = 3 + enc[p + \
- 4][E_ASCII].t) < bl)
- {
- // special case, switch to ASCII for last 1 ot two bytes
- bs = 4;
- bl = t;
- b = E_ASCII;
- }
- }
- }
- }
- }
- enc[p][E_EDIFACT].t = bl;
- enc[p][E_EDIFACT].s = bs;
- if (bl && b == E_EDIFACT)
- enc[p][b].s += enc[p + bs][b].s;
- }
- // Binary
- bl = 0;
- for (e = 0; e < E_MAX; e++)
- if (enc[p + 1][e].t
- && ((t = enc[p + 1][e].t + switchcost[E_BINARY][e] + ((e == \
- E_BINARY && enc[p + 1][e].t == 249) ? 1 : 0)) \
- < bl || !bl))
- {
- bl = t;
- b = e;
- }
- enc[p][E_BINARY].t = 1 + bl;
- enc[p][E_BINARY].s = 1;
- if (bl && b == E_BINARY)
- enc[p][b].s += enc[p + 1][b].s;
- /*
- * fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf \
- * (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); \
- * fprintf (stderr, "\n");
- */
- }
- encoding = safemalloc (l + 1);
- p = 0;
- {
- char cur = E_ASCII; // starts ASCII
- while (p < l)
- {
- int t,
- m = 0;
- char b = 0;
- for (e = 0; e < E_MAX; e++)
- if (enc[p][e].t && ((t = enc[p][e].t + switchcost[cur][e]) < m || \
- t == m && e == cur || !m))
- {
- b = e;
- m = t;
- }
- cur = b;
- m = enc[p][b].s;
- if (!p && lenp)
- *lenp = enc[p][b].t;
- while (p < l && m--)
- encoding[p++] = encchr[b];
- }
- }
- encoding[p] = 0;
- return encoding;
+ char *encoding = 0;
+ int p = l;
+ char e;
+ struct {
+ // number of bytes of source that can be encoded in a row at this point
+ // using this encoding mode
+ short s;
+ // number of bytes of target generated encoding from this point to end if
+ // already in this encoding mode
+ short t;
+ } enc[MAXBARCODE][E_MAX];
+ memset(&enc, 0, sizeof(enc));
+ if (!l)
+ return ""; // no length
+ if (l > MAXBARCODE)
+ return 0; // not valid
+ while (p--) {
+ char b = 0, sub;
+ int sl, tl, bl, t;
+ // consider each encoding from this point
+ // ASCII
+ sl = tl = 1;
+ if (isdigit(s[p]) && p + 1 < l && isdigit(s[p + 1]))
+ sl = 2; // double digit
+ else if (s[p] & 0x80)
+ tl = 2; // high shifted
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t && ((t = enc[p + sl][e].t +
+ switchcost[E_ASCII]
+ [e]) < bl || !bl)) {
+ bl = t;
+ b = e;
+ }
+ enc[p][E_ASCII].t = tl + bl;
+ enc[p][E_ASCII].s = sl;
+ if (bl && b == E_ASCII)
+ enc[p][b].s += enc[p + sl][b].s;
+ // C40
+ sub = tl = sl = 0;
+ do {
+ unsigned char c = s[p + sl++];
+ if (c & 0x80) { // shift + upper
+ sub += 2;
+ c &= 0x7F;
+ }
+ if (c != ' ' && !isdigit(c) && !isupper(c))
+ sub++; // shift
+ sub++;
+ while (sub >= 3) {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (exact && sub == 2 && p + sl == l) {
+ // special case, can encode last block with shift 0 at end (Is this
+ // valid when not end of target buffer?)
+ sub = 0;
+ tl += 2;
+ }
+ if (!sub) { // can encode C40
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t
+ &&
+ ((t =
+ enc[p + sl][e].t +
+ switchcost[E_C40][e]) < bl
+ || !bl)) {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
+ // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_C40].t = tl + bl;
+ enc[p][E_C40].s = sl;
+ if (bl && b == E_C40)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // Text
+ sub = tl = sl = 0;
+ do {
+ unsigned char c = s[p + sl++];
+ if (c & 0x80) { // shift + upper
+ sub += 2;
+ c &= 0x7F;
+ }
+ if (c != ' ' && !isdigit(c) && !islower(c))
+ sub++; // shift
+ sub++;
+ while (sub >= 3) {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (exact && sub == 2 && p + sl == l) {
+ // special case, can encode last block with shift 0 at end (Is this
+ // valid when not end of target buffer?)
+ sub = 0;
+ tl += 2;
+ }
+ if (!sub && sl) { // can encode Text
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t
+ &&
+ ((t =
+ enc[p + sl][e].t +
+ switchcost[E_TEXT][e]) < bl
+ || !bl)) {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) { // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_TEXT].t = tl + bl;
+ enc[p][E_TEXT].s = sl;
+ if (bl && b == E_TEXT)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // X12
+ sub = tl = sl = 0;
+ do {
+ unsigned char c = s[p + sl++];
+ if (c != 13 && c != '*' && c != '>' && c != ' '
+ && !isdigit(c) && !isupper(c)) {
+ sl = 0;
+ break;
+ }
+ sub++;
+ while (sub >= 3) {
+ sub -= 3;
+ tl += 2;
+ }
+ } while (sub && p + sl < l);
+ if (!sub && sl) { // can encode X12
+ bl = 0;
+ if (p + sl < l)
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + sl][e].t
+ &&
+ ((t =
+ enc[p + sl][e].t +
+ switchcost[E_X12][e]) < bl
+ || !bl)) {
+ bl = t;
+ b = e;
+ }
+ if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
+ // special case, switch to ASCII for last bytes
+ bl = 1;
+ b = E_ASCII;
+ }
+ enc[p][E_X12].t = tl + bl;
+ enc[p][E_X12].s = sl;
+ if (bl && b == E_X12)
+ enc[p][b].s += enc[p + sl][b].s;
+ }
+ // EDIFACT
+ sl = bl = 0;
+ if (s[p + 0] >= 32 && s[p + 0] <= 94) { // can encode 1
+ char bs = 0;
+ if (p + 1 == l && (!bl || bl < 2)) {
+ bl = 2;
+ bs = 1;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT && enc[p + 1][e].t
+ &&
+ ((t =
+ 2 + enc[p + 1][e].t +
+ switchcost[E_ASCII][e])
+ < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 1;
+ bl = t;
+ b = e;
+ }
+ if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94) { // can encode 2
+ if (p + 2 == l && (!bl || bl < 2)) {
+ bl = 3;
+ bs = 2;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT
+ && enc[p + 2][e].t
+ &&
+ ((t =
+ 3 + enc[p + 2][e].t +
+ switchcost[E_ASCII][e])
+ < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 2;
+ bl = t;
+ b = e;
+ }
+ if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94) { // can encode 3
+ if (p + 3 == l && (!bl || bl < 3)) {
+ bl = 3;
+ bs = 3;
+ } else
+ for (e = 0; e < E_MAX; e++)
+ if (e != E_EDIFACT
+ && enc[p + 3][e].t
+ &&
+ ((t =
+ 3 + enc[p +
+ 3][e].t +
+ switchcost
+ [E_ASCII][e])
+ < bl || !bl)) // E_ASCII as allowed for unlatch
+ {
+ bs = 3;
+ bl = t;
+ b = e;
+ }
+ if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94) { // can encode 4
+ if (p + 4 == l
+ && (!bl || bl < 3)) {
+ bl = 3;
+ bs = 4;
+ } else {
+ for (e = 0; e < E_MAX;
+ e++)
+ if (enc[p + 4]
+ [e].t
+ &&
+ ((t =
+ 3 +
+ enc[p +
+ 4][e].
+ t +
+ switchcost
+ [E_EDIFACT]
+ [e]) < bl
+ || !bl)) {
+ bs = 4;
+ bl = t;
+ b = e;
+ }
+ if (exact
+ && enc[p +
+ 4][E_ASCII].t
+ && enc[p +
+ 4][E_ASCII].
+ t <= 2
+ && (t =
+ 3 + enc[p +
+ 4]
+ [E_ASCII].t) <
+ bl) {
+ // special case, switch to ASCII for last 1 ot two bytes
+ bs = 4;
+ bl = t;
+ b = E_ASCII;
+ }
+ }
+ }
+ }
+ }
+ enc[p][E_EDIFACT].t = bl;
+ enc[p][E_EDIFACT].s = bs;
+ if (bl && b == E_EDIFACT)
+ enc[p][b].s += enc[p + bs][b].s;
+ }
+ // Binary
+ bl = 0;
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p + 1][e].t
+ &&
+ ((t =
+ enc[p + 1][e].t + switchcost[E_BINARY][e] +
+ ((e == E_BINARY
+ && enc[p + 1][e].t == 249) ? 1 : 0))
+ < bl || !bl)) {
+ bl = t;
+ b = e;
+ }
+ enc[p][E_BINARY].t = 1 + bl;
+ enc[p][E_BINARY].s = 1;
+ if (bl && b == E_BINARY)
+ enc[p][b].s += enc[p + 1][b].s;
+ /*
+ * fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf \
+ * (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); \
+ * fprintf (stderr, "\n");
+ */
+ }
+ encoding = safemalloc(l + 1);
+ p = 0;
+ {
+ char cur = E_ASCII; // starts ASCII
+ while (p < l) {
+ int t, m = 0;
+ char b = 0;
+ for (e = 0; e < E_MAX; e++)
+ if (enc[p][e].t
+ && ((t = enc[p][e].t + switchcost[cur][e]) <
+ m || t == m && e == cur || !m)) {
+ b = e;
+ m = t;
+ }
+ cur = b;
+ m = enc[p][b].s;
+ if (!p && lenp)
+ *lenp = enc[p][b].t;
+ while (p < l && m--)
+ encoding[p++] = encchr[b];
+ }
+ }
+ encoding[p] = 0;
+ return encoding;
}
+
/*
* Main encoding function
* Returns the grid (malloced) containing the matrix. L corner at 0,0.
* Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
* Takes barcodelen and barcode to be encoded
- * Note, if *encodingptr is null, then fills with auto picked (malloced)
+ * Note, if *encodingptr is null, then fills with auto picked (malloced)
* encoding
- * If lenp not null, then the length of encoded data before any final
+ * If lenp not null, then the length of encoded data before any final
* unlatch or pad is stored
* If maxp not null, then the max storage of this size code is stored
- * If eccp not null, then the number of ecc bytes used in this size is
+ * If eccp not null, then the number of ecc bytes used in this size is
* stored
* Returns 0 on error (writes to stderr with details).
*/
-unsigned char * iec16022ecc200 (int *Wptr, int *Hptr, char **encodingptr, \
- int barcodelen, unsigned char *barcode, \
- int *lenp, int *maxp, int *eccp)
+unsigned char *iec16022ecc200(int *Wptr, int *Hptr, char **encodingptr,
+ int barcodelen, unsigned char *barcode,
+ int *lenp, int *maxp, int *eccp)
{
- unsigned char binary[3000]; // encoded raw data and ecc to place in barcode
- int W = 0,
- H = 0;
- char *encoding = 0;
- unsigned char *grid = 0;
- struct ecc200matrix_s *matrix;
- memset (binary, 0, sizeof (binary));
- if (encodingptr)
- encoding = *encodingptr;
- if (Wptr)
- W = *Wptr;
- if (Hptr)
- H = *Hptr;
+ unsigned char binary[3000]; // encoded raw data and ecc to place in barcode
+ int W = 0, H = 0;
+ char *encoding = 0;
+ unsigned char *grid = 0;
+ struct ecc200matrix_s *matrix;
+ memset(binary, 0, sizeof(binary));
+ if (encodingptr)
+ encoding = *encodingptr;
+ if (Wptr)
+ W = *Wptr;
+ if (Hptr)
+ H = *Hptr;
+
+ // encoding
+ if (W) { // known size
+ for (matrix = ecc200matrix; matrix->W && (matrix->W != W ||
+ matrix->H != H);
+ matrix++) ;
+ if (!matrix->W) {
+ fprintf(stderr, "Invalid size %dx%d\n", W, H);
+ return 0;
+ }
+ if (!encoding) {
+ int len;
+ char *e = encmake(barcodelen, barcode, &len, 1);
+ if (e && len != matrix->bytes) { // try not an exact fit
+ free(e);
+ e = encmake(barcodelen, barcode, &len, 0);
+ if (len > matrix->bytes) {
+ fprintf(stderr,
+ "Cannot make barcode fit %dx%d\n",
+ W, H);
+ return 0;
+ }
+ }
+ encoding = e;
+ }
+ } else {
+ // find a suitable encoding
+ if (encoding == NULL)
+ encoding = encmake(barcodelen, barcode, NULL, 1);
- // encoding
- if (W)
- { // known size
- for (matrix = ecc200matrix; matrix->W && (matrix->W != W || \
- matrix->H != H); matrix++);
- if (!matrix->W)
- {
- fprintf (stderr, "Invalid size %dx%d\n", W, H);
- return 0;
- }
- if (!encoding)
- {
- int len;
- char *e = encmake (barcodelen, barcode, &len, 1);
- if (e && len != matrix->bytes)
- { // try not an exact fit
- free (e);
- e = encmake (barcodelen, barcode, &len, 0);
- if (len > matrix->bytes)
- {
- fprintf (stderr, "Cannot make barcode fit %dx%d\n", W, H);
- return 0;
- }
- }
- encoding = e;
- }
- } else
- { // find size
- if (encoding)
- { // find one that fits chosen encoding
- for (matrix = ecc200matrix; matrix->W; matrix++)
- if (ecc200encode (binary, matrix->bytes, barcode, barcodelen, \
- encoding, 0))
- break;
- } else
- {
- int len;
- char *e;
- e = encmake (barcodelen, barcode, &len, 1);
- for (matrix = ecc200matrix; matrix->W && matrix->bytes != len; \
- matrix++);
- if (e && !matrix->W)
- { // try for non exact fit
- free (e);
- e = encmake (barcodelen, barcode, &len, 0);
- for (matrix = ecc200matrix; matrix->W && matrix->bytes < len; \
- matrix++);
- }
- encoding = e;
- }
- if (!matrix->W)
- {
- fprintf (stderr, "Cannot find suitable size, barcode too long\n");
- return 0;
- }
- W = matrix->W;
- H = matrix->H;
- }
- if (!ecc200encode (binary, matrix->bytes, barcode, barcodelen, \
- encoding, lenp))
- {
- fprintf (stderr, "Barcode too long for %dx%d\n", W, H);
- return 0;
- }
- // ecc code
- ecc200 (binary, matrix->bytes, matrix->datablock, matrix->rsblock);
- { // placement
- int x,
- y,
- NC,
- NR,
- *places;
- NC = W - 2 * (W / matrix->FW);
- NR = H - 2 * (H / matrix->FH);
- places = safemalloc (NC * NR * sizeof (int));
- ecc200placement (places, NR, NC);
- grid = safemalloc (W * H);
- memset (grid, 0, W * H);
- for (y = 0; y < H; y += matrix->FH)
- {
- for (x = 0; x < W; x++)
- grid[y * W + x] = 1;
- for (x = 0; x < W; x += 2)
- grid[(y + matrix->FH - 1) * W + x] = 1;
- }
- for (x = 0; x < W; x += matrix->FW)
- {
- for (y = 0; y < H; y++)
- grid[y * W + x] = 1;
- for (y = 0; y < H; y += 2)
- grid[y * W + x + matrix->FW - 1] = 1;
- }
- for (y = 0; y < NR; y++)
- {
- for (x = 0; x < NC; x++)
- {
- int v = places[(NR - y - 1) * NC + x];
- //fprintf (stderr, "%4d", v);
- if (v == 1 || v > 7 && (binary[(v >> 3) - 1] & (1 << (v & 7))))
- grid[(1 + y + 2 * (y / (matrix->FH - 2))) * W + 1 + x + 2 * \
- (x / (matrix->FW - 2))] = 1;
- }
- //fprintf (stderr, "\n");
- }
- free (places);
- }
- if (Wptr)
- *Wptr = W;
- if (Hptr)
- *Hptr = H;
- if (encodingptr)
- *encodingptr = encoding;
- if (maxp)
- *maxp = matrix->bytes;
- if (eccp)
- *eccp = (matrix->bytes + 2) / matrix->datablock * matrix->rsblock;
- return grid;
+ if (encoding) { // find one that fits chosen encoding
+ for (matrix = ecc200matrix; matrix->W; matrix++)
+ if (ecc200encode
+ (binary, matrix->bytes, barcode, barcodelen,
+ encoding, 0))
+ break;
+ } else {
+ int len;
+ char *e;
+ e = encmake(barcodelen, barcode, &len, 1);
+ for (matrix = ecc200matrix;
+ matrix->W && matrix->bytes != len; matrix++) ;
+ if (e && !matrix->W) { // try for non exact fit
+ free(e);
+ e = encmake(barcodelen, barcode, &len, 0);
+ for (matrix = ecc200matrix;
+ matrix->W && matrix->bytes < len;
+ matrix++) ;
+ }
+ encoding = e;
+ }
+ if (!matrix->W) {
+ fprintf(stderr,
+ "Cannot find suitable size, barcode too long\n");
+ return 0;
+ }
+ W = matrix->W;
+ H = matrix->H;
+ }
+ if (!ecc200encode(binary, matrix->bytes, barcode, barcodelen,
+ encoding, lenp)) {
+ fprintf(stderr, "Barcode too long for %dx%d\n", W, H);
+ return 0;
+ }
+ // ecc code
+ ecc200(binary, matrix->bytes, matrix->datablock, matrix->rsblock);
+ { // placement
+ int x, y, NC, NR, *places;
+ NC = W - 2 * (W / matrix->FW);
+ NR = H - 2 * (H / matrix->FH);
+ places = safemalloc(NC * NR * sizeof(int));
+ ecc200placement(places, NR, NC);
+ grid = safemalloc(W * H);
+ memset(grid, 0, W * H);
+ for (y = 0; y < H; y += matrix->FH) {
+ for (x = 0; x < W; x++)
+ grid[y * W + x] = 1;
+ for (x = 0; x < W; x += 2)
+ grid[(y + matrix->FH - 1) * W + x] = 1;
+ }
+ for (x = 0; x < W; x += matrix->FW) {
+ for (y = 0; y < H; y++)
+ grid[y * W + x] = 1;
+ for (y = 0; y < H; y += 2)
+ grid[y * W + x + matrix->FW - 1] = 1;
+ }
+ for (y = 0; y < NR; y++) {
+ for (x = 0; x < NC; x++) {
+ int v = places[(NR - y - 1) * NC + x];
+ //fprintf (stderr, "%4d", v);
+ if (v == 1 || v > 7
+ && (binary[(v >> 3) - 1] & (1 << (v & 7))))
+ grid[(1 + y +
+ 2 * (y / (matrix->FH - 2))) * W +
+ 1 + x +
+ 2 * (x / (matrix->FW - 2))] = 1;
+ }
+ //fprintf (stderr, "\n");
+ }
+ free(places);
+ }
+ if (Wptr)
+ *Wptr = W;
+ if (Hptr)
+ *Hptr = H;
+ if (encodingptr)
+ *encodingptr = encoding;
+ if (maxp)
+ *maxp = matrix->bytes;
+ if (eccp)
+ *eccp =
+ (matrix->bytes + 2) / matrix->datablock * matrix->rsblock;
+ return grid;
}