1 /**
2 * libdmtx - Data Matrix Encoding/Decoding Library
3 * Copyright 2008, 2009 Mike Laughton. All rights reserved.
4 * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved.
5 * Copyright 2016 Tim Zaman. All rights reserved.
6 *
7 * See LICENSE file in the main project directory for full
8 * terms of use and distribution.
9 *
10 * Contact:
11 * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
12 * Mike Laughton <mike@dragonflylogic.com>
13 *
14 * \file dmtxdecodescheme.c
15 */
16
17 /**
18 * \brief Translate encoded data stream into final output
19 * \param msg
20 * \param sizeIdx
21 * \param outputStart
22 * \return void
23 */
24 extern void
DecodeDataStream(DmtxMessage * msg,int sizeIdx,unsigned char * outputStart)25 DecodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart)
26 {
27 //fprintf(stdout, "libdmtx::DecodeDataStream()\n");
28 //int oned = sqrt(msg->arraySize);
29 //for (int i=0; i<msg->arraySize; i++){
30 // fprintf(stdout, " %c.", msg->array[i]);
31 // if (i%oned==oned-1){
32 // fprintf(stdout, "\n");
33 // }
34 //}
35
36 DmtxBoolean macro = DmtxFalse;
37 DmtxScheme encScheme;
38 unsigned char *ptr, *dataEnd;
39
40 msg->output = (outputStart == NULL) ? msg->output : outputStart;
41 msg->outputIdx = 0;
42
43 ptr = msg->code;
44 dataEnd = ptr + dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx);
45
46 /* Print macro header if first codeword triggers it */
47 if(*ptr == DmtxValue05Macro || *ptr == DmtxValue06Macro) {
48 PushOutputMacroHeader(msg, *ptr);
49 macro = DmtxTrue;
50 }
51
52 while(ptr < dataEnd) {
53
54 encScheme = GetEncodationScheme(*ptr);
55 if(encScheme != DmtxSchemeAscii)
56 ptr++;
57
58 switch(encScheme) {
59 case DmtxSchemeAscii:
60 ptr = DecodeSchemeAscii(msg, ptr, dataEnd);
61 break;
62 case DmtxSchemeC40:
63 case DmtxSchemeText:
64 ptr = DecodeSchemeC40Text(msg, ptr, dataEnd, encScheme);
65 break;
66 case DmtxSchemeX12:
67 ptr = DecodeSchemeX12(msg, ptr, dataEnd);
68 break;
69 case DmtxSchemeEdifact:
70 ptr = DecodeSchemeEdifact(msg, ptr, dataEnd);
71 break;
72 case DmtxSchemeBase256:
73 ptr = DecodeSchemeBase256(msg, ptr, dataEnd);
74 break;
75 default:
76 /* error */
77 break;
78 }
79 }
80
81 /* Print macro trailer if required */
82 if(macro == DmtxTrue)
83 PushOutputMacroTrailer(msg);
84 }
85
86 /**
87 * \brief Determine next encodation scheme
88 * \param encScheme
89 * \param cw
90 * \return Pointer to next undecoded codeword
91 */
92 static int
GetEncodationScheme(unsigned char cw)93 GetEncodationScheme(unsigned char cw)
94 {
95 DmtxScheme encScheme;
96
97 switch(cw) {
98 case DmtxValueC40Latch:
99 encScheme = DmtxSchemeC40;
100 break;
101 case DmtxValueTextLatch:
102 encScheme = DmtxSchemeText;
103 break;
104 case DmtxValueX12Latch:
105 encScheme = DmtxSchemeX12;
106 break;
107 case DmtxValueEdifactLatch:
108 encScheme = DmtxSchemeEdifact;
109 break;
110 case DmtxValueBase256Latch:
111 encScheme = DmtxSchemeBase256;
112 break;
113 default:
114 encScheme = DmtxSchemeAscii;
115 break;
116 }
117
118 return encScheme;
119 }
120
121 /**
122 *
123 *
124 */
125 static void
PushOutputWord(DmtxMessage * msg,int value)126 PushOutputWord(DmtxMessage *msg, int value)
127 {
128 assert(value >= 0 && value < 256);
129
130 msg->output[msg->outputIdx++] = (unsigned char)value;
131 }
132
133 /**
134 *
135 *
136 */
137 static void
PushOutputC40TextWord(DmtxMessage * msg,C40TextState * state,int value)138 PushOutputC40TextWord(DmtxMessage *msg, C40TextState *state, int value)
139 {
140 assert(value >= 0 && value < 256);
141
142 msg->output[msg->outputIdx] = (unsigned char)value;
143
144 if(state->upperShift == DmtxTrue) {
145 assert(value < 128);
146 msg->output[msg->outputIdx] += 128;
147 }
148
149 msg->outputIdx++;
150
151 state->shift = DmtxC40TextBasicSet;
152 state->upperShift = DmtxFalse;
153 }
154
155 /**
156 *
157 *
158 */
159 static void
PushOutputMacroHeader(DmtxMessage * msg,int macroType)160 PushOutputMacroHeader(DmtxMessage *msg, int macroType)
161 {
162 PushOutputWord(msg, '[');
163 PushOutputWord(msg, ')');
164 PushOutputWord(msg, '>');
165 PushOutputWord(msg, 30); /* ASCII RS */
166 PushOutputWord(msg, '0');
167
168 assert(macroType == DmtxValue05Macro || macroType == DmtxValue06Macro);
169 if(macroType == DmtxValue05Macro)
170 PushOutputWord(msg, '5');
171 else
172 PushOutputWord(msg, '6');
173
174 PushOutputWord(msg, 29); /* ASCII GS */
175 }
176
177 /**
178 *
179 *
180 */
181 static void
PushOutputMacroTrailer(DmtxMessage * msg)182 PushOutputMacroTrailer(DmtxMessage *msg)
183 {
184 PushOutputWord(msg, 30); /* ASCII RS */
185 PushOutputWord(msg, 4); /* ASCII EOT */
186 }
187
188 /**
189 * \brief Decode stream assuming standard ASCII encodation
190 * \param msg
191 * \param ptr
192 * \param dataEnd
193 * \return Pointer to next undecoded codeword
194 */
195 static unsigned char *
DecodeSchemeAscii(DmtxMessage * msg,unsigned char * ptr,unsigned char * dataEnd)196 DecodeSchemeAscii(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
197 {
198 int upperShift;
199 int codeword, digits;
200
201 upperShift = DmtxFalse;
202
203 while(ptr < dataEnd) {
204
205 codeword = (int)(*ptr);
206
207 if(GetEncodationScheme(*ptr) != DmtxSchemeAscii)
208 return ptr;
209 else
210 ptr++;
211
212 if(upperShift == DmtxTrue) {
213 PushOutputWord(msg, codeword + 127);
214 upperShift = DmtxFalse;
215 }
216 else if(codeword == DmtxValueAsciiUpperShift) {
217 upperShift = DmtxTrue;
218 }
219 else if(codeword == DmtxValueAsciiPad) {
220 assert(dataEnd >= ptr);
221 assert(dataEnd - ptr <= INT_MAX);
222 msg->padCount = (int)(dataEnd - ptr);
223 return dataEnd;
224 }
225 else if(codeword == 0 || codeword >= 242) {
226 return ptr;
227 }
228 else if(codeword <= 128) {
229 PushOutputWord(msg, codeword - 1);
230 }
231 else if(codeword <= 229) {
232 digits = codeword - 130;
233 PushOutputWord(msg, digits/10 + '0');
234 PushOutputWord(msg, digits - (digits/10)*10 + '0');
235 }
236 else if(codeword == DmtxValueFNC1) {
237 if(msg->fnc1 != DmtxUndefined) {
238 PushOutputWord(msg, msg->fnc1);
239 }
240 }
241 }
242
243 return ptr;
244 }
245
246 /**
247 * \brief Decode stream assuming C40 or Text encodation
248 * \param msg
249 * \param ptr
250 * \param dataEnd
251 * \param encScheme
252 * \return Pointer to next undecoded codeword
253 */
254 static unsigned char *
DecodeSchemeC40Text(DmtxMessage * msg,unsigned char * ptr,unsigned char * dataEnd,DmtxScheme encScheme)255 DecodeSchemeC40Text(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd, DmtxScheme encScheme)
256 {
257 int i;
258 int packed;
259 int c40Values[3];
260 C40TextState state;
261
262 state.shift = DmtxC40TextBasicSet;
263 state.upperShift = DmtxFalse;
264
265 assert(encScheme == DmtxSchemeC40 || encScheme == DmtxSchemeText);
266
267 /* Unlatch is implied if only one codeword remains */
268 if(dataEnd - ptr < 2)
269 return ptr;
270
271 while(ptr < dataEnd) {
272
273 /* FIXME Also check that ptr+1 is safe to access */
274 packed = (*ptr << 8) | *(ptr+1);
275 c40Values[0] = ((packed - 1)/1600);
276 c40Values[1] = ((packed - 1)/40) % 40;
277 c40Values[2] = (packed - 1) % 40;
278 ptr += 2;
279
280 for(i = 0; i < 3; i++) {
281 if(state.shift == DmtxC40TextBasicSet) { /* Basic set */
282 if(c40Values[i] <= 2) {
283 state.shift = c40Values[i] + 1;
284 }
285 else if(c40Values[i] == 3) {
286 PushOutputC40TextWord(msg, &state, ' ');
287 }
288 else if(c40Values[i] <= 13) {
289 PushOutputC40TextWord(msg, &state, c40Values[i] - 13 + '9'); /* 0-9 */
290 }
291 else if(c40Values[i] <= 39) {
292 if(encScheme == DmtxSchemeC40) {
293 PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'Z'); /* A-Z */
294 }
295 else if(encScheme == DmtxSchemeText) {
296 PushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'z'); /* a-z */
297 }
298 }
299 }
300 else if(state.shift == DmtxC40TextShift1) { /* Shift 1 set */
301 PushOutputC40TextWord(msg, &state, c40Values[i]); /* ASCII 0 - 31 */
302 }
303 else if(state.shift == DmtxC40TextShift2) { /* Shift 2 set */
304 if(c40Values[i] <= 14) {
305 PushOutputC40TextWord(msg, &state, c40Values[i] + 33); /* ASCII 33 - 47 */
306 }
307 else if(c40Values[i] <= 21) {
308 PushOutputC40TextWord(msg, &state, c40Values[i] + 43); /* ASCII 58 - 64 */
309 }
310 else if(c40Values[i] <= 26) {
311 PushOutputC40TextWord(msg, &state, c40Values[i] + 69); /* ASCII 91 - 95 */
312 }
313 else if(c40Values[i] == 27) {
314 if(msg->fnc1 != DmtxUndefined) {
315 PushOutputC40TextWord(msg, &state, msg->fnc1);
316 }
317 }
318 else if(c40Values[i] == 30) {
319 state.upperShift = DmtxTrue;
320 state.shift = DmtxC40TextBasicSet;
321 }
322 }
323 else if(state.shift == DmtxC40TextShift3) { /* Shift 3 set */
324 if(encScheme == DmtxSchemeC40) {
325 PushOutputC40TextWord(msg, &state, c40Values[i] + 96);
326 }
327 else if(encScheme == DmtxSchemeText) {
328 if(c40Values[i] == 0)
329 PushOutputC40TextWord(msg, &state, c40Values[i] + 96);
330 else if(c40Values[i] <= 26)
331 PushOutputC40TextWord(msg, &state, c40Values[i] - 26 + 'Z'); /* A-Z */
332 else
333 PushOutputC40TextWord(msg, &state, c40Values[i] - 31 + 127); /* { | } ~ DEL */
334 }
335 }
336 }
337
338 /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */
339 if(*ptr == DmtxValueCTXUnlatch)
340 return ptr + 1;
341
342 /* Unlatch is implied if only one codeword remains */
343 if(dataEnd - ptr < 2)
344 return ptr;
345 }
346
347 return ptr;
348 }
349
350 /**
351 * \brief Decode stream assuming X12 encodation
352 * \param msg
353 * \param ptr
354 * \param dataEnd
355 * \return Pointer to next undecoded codeword
356 */
357 static unsigned char *
DecodeSchemeX12(DmtxMessage * msg,unsigned char * ptr,unsigned char * dataEnd)358 DecodeSchemeX12(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
359 {
360 int i;
361 int packed;
362 int x12Values[3];
363
364 /* Unlatch is implied if only one codeword remains */
365 if(dataEnd - ptr < 2)
366 return ptr;
367
368 while(ptr < dataEnd) {
369
370 /* FIXME Also check that ptr+1 is safe to access */
371 packed = (*ptr << 8) | *(ptr+1);
372 x12Values[0] = ((packed - 1)/1600);
373 x12Values[1] = ((packed - 1)/40) % 40;
374 x12Values[2] = (packed - 1) % 40;
375 ptr += 2;
376
377 for(i = 0; i < 3; i++) {
378 if(x12Values[i] == 0)
379 PushOutputWord(msg, 13);
380 else if(x12Values[i] == 1)
381 PushOutputWord(msg, 42);
382 else if(x12Values[i] == 2)
383 PushOutputWord(msg, 62);
384 else if(x12Values[i] == 3)
385 PushOutputWord(msg, 32);
386 else if(x12Values[i] <= 13)
387 PushOutputWord(msg, x12Values[i] + 44);
388 else if(x12Values[i] <= 90)
389 PushOutputWord(msg, x12Values[i] + 51);
390 }
391
392 /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */
393 if(*ptr == DmtxValueCTXUnlatch)
394 return ptr + 1;
395
396 /* Unlatch is implied if only one codeword remains */
397 if(dataEnd - ptr < 2)
398 return ptr;
399 }
400
401 return ptr;
402 }
403
404 /**
405 * \brief Decode stream assuming EDIFACT encodation
406 * \param msg
407 * \param ptr
408 * \param dataEnd
409 * \return Pointer to next undecoded codeword
410 */
411 static unsigned char *
DecodeSchemeEdifact(DmtxMessage * msg,unsigned char * ptr,unsigned char * dataEnd)412 DecodeSchemeEdifact(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
413 {
414 int i;
415 unsigned char unpacked[4];
416
417 /* Unlatch is implied if fewer than 3 codewords remain */
418 if(dataEnd - ptr < 3)
419 return ptr;
420
421 while(ptr < dataEnd) {
422
423 /* FIXME Also check that ptr+2 is safe to access -- shouldn't be a
424 problem because I'm guessing you can guarantee there will always
425 be at least 3 error codewords */
426 unpacked[0] = (*ptr & 0xfc) >> 2;
427 unpacked[1] = (*ptr & 0x03) << 4 | (*(ptr+1) & 0xf0) >> 4;
428 unpacked[2] = (*(ptr+1) & 0x0f) << 2 | (*(ptr+2) & 0xc0) >> 6;
429 unpacked[3] = *(ptr+2) & 0x3f;
430
431 for(i = 0; i < 4; i++) {
432
433 /* Advance input ptr (4th value comes from already-read 3rd byte) */
434 if(i < 3)
435 ptr++;
436
437 /* Test for unlatch condition */
438 if(unpacked[i] == DmtxValueEdifactUnlatch) {
439 assert(msg->output[msg->outputIdx] == 0); /* XXX dirty why? */
440 return ptr;
441 }
442
443 PushOutputWord(msg, unpacked[i] ^ (((unpacked[i] & 0x20) ^ 0x20) << 1));
444 }
445
446 /* Unlatch is implied if fewer than 3 codewords remain */
447 if(dataEnd - ptr < 3)
448 return ptr;
449 }
450
451 return ptr;
452
453 /* XXX the following version should be safer, but requires testing before replacing the old version
454 int bits = 0;
455 int bitCount = 0;
456 int value;
457
458 while(ptr < dataEnd) {
459
460 if(bitCount < 6) {
461 bits = (bits << 8) | *(ptr++);
462 bitCount += 8;
463 }
464
465 value = bits >> (bitCount - 6);
466 bits -= (value << (bitCount - 6));
467 bitCount -= 6;
468
469 if(value == 0x1f) {
470 assert(bits == 0); // should be padded with zero-value bits
471 return ptr;
472 }
473 PushOutputWord(msg, value ^ (((value & 0x20) ^ 0x20) << 1));
474
475 // Unlatch implied if just completed triplet and 1 or 2 words are left
476 if(bitCount == 0 && dataEnd - ptr - 1 > 0 && dataEnd - ptr - 1 < 3)
477 return ptr;
478 }
479
480 assert(bits == 0); // should be padded with zero-value bits
481 assert(bitCount == 0); // should be padded with zero-value bits
482 return ptr;
483 */
484 }
485
486 /**
487 * \brief Decode stream assuming Base 256 encodation
488 * \param msg
489 * \param ptr
490 * \param dataEnd
491 * \return Pointer to next undecoded codeword
492 */
493 static unsigned char *
DecodeSchemeBase256(DmtxMessage * msg,unsigned char * ptr,unsigned char * dataEnd)494 DecodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
495 {
496 int d0, d1;
497 int idx;
498 unsigned char *ptrEnd;
499
500 /* Find positional index used for unrandomizing */
501 assert(ptr + 1 >= msg->code);
502 assert(ptr + 1 - msg->code <= INT_MAX);
503 idx = (int)(ptr + 1 - msg->code);
504
505 d0 = UnRandomize255State(*(ptr++), idx++);
506 if(d0 == 0) {
507 ptrEnd = dataEnd;
508 }
509 else if(d0 <= 249) {
510 ptrEnd = ptr + d0;
511 }
512 else {
513 d1 = UnRandomize255State(*(ptr++), idx++);
514 ptrEnd = ptr + (d0 - 249) * 250 + d1;
515 }
516
517 if(ptrEnd > dataEnd)
518 exit(40); /* XXX needs cleaner error handling */
519
520 while(ptr < ptrEnd)
521 PushOutputWord(msg, UnRandomize255State(*(ptr++), idx++));
522
523 return ptr;
524 }
525