📄 iec16022ecc200.c
字号:
}
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
};
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
};
// Creates a encoding list (malloc)
// returns encoding string
// if lenp not null, target len stored
// if error, null returned
// 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 Text or X12
// 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 0 to pad to make a tripple
// 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)
{
char *encoding = 0;
int p = l;
char e;
struct
{
short s; // number of bytes of source that can be encoded in a row at this point using this encoding mode
short t; // number of bytes of target generated encoding from this point to end if already in this encoding mode
} 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -