Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / datamatrix / BC_DataMatrixDecodedBitStreamParser.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 // Original code is licensed as follows:\r
7 /*\r
8  * Copyright 2008 ZXing authors\r
9  *\r
10  * Licensed under the Apache License, Version 2.0 (the "License");\r
11  * you may not use this file except in compliance with the License.\r
12  * You may obtain a copy of the License at\r
13  *\r
14  *      http://www.apache.org/licenses/LICENSE-2.0\r
15  *\r
16  * Unless required by applicable law or agreed to in writing, software\r
17  * distributed under the License is distributed on an "AS IS" BASIS,\r
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
19  * See the License for the specific language governing permissions and\r
20  * limitations under the License.\r
21  */\r
22 \r
23 #include "../barcode.h"\r
24 #include "../common/BC_CommonDecoderResult.h"\r
25 #include "../common/BC_CommonBitSource.h"\r
26 #include "BC_DataMatrixDecodedBitStreamParser.h"\r
27 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::C40_BASIC_SET_CHARS[] = {\r
28     '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\r
29     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\r
30     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'\r
31 };\r
32 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::C40_SHIFT2_SET_CHARS[] = {\r
33     '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*',  '+', ',', '-', '.',\r
34     '/', ':', ';', '<', '=', '>', '?',  '@', '[', '\\', ']', '^', '_'\r
35 };\r
36 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::TEXT_BASIC_SET_CHARS[] = {\r
37     '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\r
38     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',\r
39     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'\r
40 };\r
41 const FX_CHAR CBC_DataMatrixDecodedBitStreamParser::TEXT_SHIFT3_SET_CHARS[] = {\r
42     '\'', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\r
43     'O',  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (FX_CHAR) 127\r
44 };\r
45 const int32_t CBC_DataMatrixDecodedBitStreamParser::PAD_ENCODE = 0;\r
46 const int32_t CBC_DataMatrixDecodedBitStreamParser::ASCII_ENCODE = 1;\r
47 const int32_t CBC_DataMatrixDecodedBitStreamParser::C40_ENCODE = 2;\r
48 const int32_t CBC_DataMatrixDecodedBitStreamParser::TEXT_ENCODE = 3;\r
49 const int32_t CBC_DataMatrixDecodedBitStreamParser::ANSIX12_ENCODE = 4;\r
50 const int32_t CBC_DataMatrixDecodedBitStreamParser::EDIFACT_ENCODE = 5;\r
51 const int32_t CBC_DataMatrixDecodedBitStreamParser::BASE256_ENCODE = 6;\r
52 CBC_DataMatrixDecodedBitStreamParser::CBC_DataMatrixDecodedBitStreamParser()\r
53 {\r
54 }\r
55 CBC_DataMatrixDecodedBitStreamParser::~CBC_DataMatrixDecodedBitStreamParser()\r
56 {\r
57 }\r
58 CBC_CommonDecoderResult *CBC_DataMatrixDecodedBitStreamParser::Decode(CFX_ByteArray &bytes, int32_t &e)\r
59 {\r
60     CBC_CommonBitSource bits(&bytes);\r
61     CFX_ByteString result;\r
62     CFX_ByteString resultTrailer;\r
63     CFX_Int32Array byteSegments;\r
64     int32_t mode = ASCII_ENCODE;\r
65     do {\r
66         if (mode == 1) {\r
67             mode = DecodeAsciiSegment(&bits, result, resultTrailer, e);\r
68             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
69         } else {\r
70             switch (mode) {\r
71                 case 2:\r
72                     DecodeC40Segment(&bits, result, e);\r
73                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
74                     break;\r
75                 case 3:\r
76                     DecodeTextSegment(&bits, result, e);\r
77                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
78                     break;\r
79                 case 4:\r
80                     DecodeAnsiX12Segment(&bits, result, e);\r
81                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
82                     break;\r
83                 case 5:\r
84                     DecodeEdifactSegment(&bits, result, e);\r
85                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
86                     break;\r
87                 case 6:\r
88                     DecodeBase256Segment(&bits, result, byteSegments, e);\r
89                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
90                     break;\r
91                 default:\r
92                     NULL;\r
93                     e = BCExceptionFormatException;\r
94                     return NULL;\r
95             }\r
96             mode = ASCII_ENCODE;\r
97         }\r
98     } while (mode != PAD_ENCODE && bits.Available() > 0);\r
99     if (resultTrailer.GetLength() > 0) {\r
100         result += resultTrailer;\r
101     }\r
102     CBC_CommonDecoderResult *tempCp =  FX_NEW CBC_CommonDecoderResult();\r
103     tempCp->Init(bytes, result, (byteSegments.GetSize() <= 0) ? CFX_Int32Array() : byteSegments, NULL, e);\r
104     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
105     return tempCp;\r
106 }\r
107 int32_t CBC_DataMatrixDecodedBitStreamParser::DecodeAsciiSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, CFX_ByteString &resultTrailer, int32_t &e)\r
108 {\r
109     FX_CHAR buffer[128];\r
110     FX_BOOL upperShift = FALSE;\r
111     do {\r
112         int32_t oneByte = bits->ReadBits(8, e);\r
113         BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
114         if (oneByte == 0) {\r
115             e = BCExceptionFormatException;\r
116             return 0;\r
117         } else if (oneByte <= 128) {\r
118             oneByte = upperShift ? oneByte + 128 : oneByte;\r
119             upperShift = FALSE;\r
120             result += ((FX_CHAR) (oneByte - 1));\r
121             return ASCII_ENCODE;\r
122         } else if (oneByte == 129) {\r
123             return PAD_ENCODE;\r
124         } else if (oneByte <= 229) {\r
125             int32_t value = oneByte - 130;\r
126 #if defined(_FX_WINAPI_PARTITION_APP_)\r
127             memset(buffer, 0, sizeof(FX_CHAR) * 128);\r
128             _itoa_s(value, buffer, 128, 10);\r
129 #else\r
130             FXSYS_itoa(value, buffer, 10);\r
131 #endif\r
132             if (value < 10) {\r
133                 result += '0';\r
134                 buffer[1] = '\0';\r
135             } else {\r
136                 buffer[2] = '\0';\r
137             }\r
138             result += buffer;\r
139         } else if (oneByte == 230) {\r
140             return C40_ENCODE;\r
141         } else if (oneByte == 231) {\r
142             return BASE256_ENCODE;\r
143         } else if (oneByte == 232 || oneByte == 233 || oneByte == 234) {\r
144         } else if (oneByte == 235) {\r
145             upperShift = TRUE;\r
146         } else if (oneByte == 236) {\r
147             result += "[)>";\r
148             result += 0x1E;\r
149             result += "05";\r
150             result += 0x1D;\r
151             resultTrailer.Insert(0, 0x1E);\r
152             resultTrailer.Insert(0 + 1, 0x04);\r
153         } else if (oneByte == 237) {\r
154             result += "[)>";\r
155             result += 0x1E;\r
156             result += "06";\r
157             result += 0x1D;\r
158             resultTrailer.Insert(0, 0x1E);\r
159             resultTrailer.Insert(0 + 1, 0x04);\r
160         } else if (oneByte == 238) {\r
161             return ANSIX12_ENCODE;\r
162         } else if (oneByte == 239) {\r
163             return TEXT_ENCODE;\r
164         } else if (oneByte == 240) {\r
165             return EDIFACT_ENCODE;\r
166         } else if (oneByte == 241) {\r
167         } else if (oneByte >= 242) {\r
168             if (oneByte == 254 && bits->Available() == 0) {\r
169             } else {\r
170                 e = BCExceptionFormatException;\r
171                 return 0;\r
172             }\r
173         }\r
174     } while (bits->Available() > 0);\r
175     return ASCII_ENCODE;\r
176 }\r
177 void CBC_DataMatrixDecodedBitStreamParser::DecodeC40Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, int32_t &e)\r
178 {\r
179     FX_BOOL upperShift = FALSE;\r
180     CFX_Int32Array cValues;\r
181     cValues.SetSize(3);\r
182     do {\r
183         if (bits->Available() == 8) {\r
184             return;\r
185         }\r
186         int32_t firstByte = bits->ReadBits(8, e);\r
187         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
188         if (firstByte == 254) {\r
189             return;\r
190         }\r
191         int32_t tempp = bits->ReadBits(8, e);\r
192         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
193         ParseTwoBytes(firstByte, tempp, cValues);\r
194         int32_t shift = 0;\r
195         int32_t i;\r
196         for (i = 0; i < 3; i++) {\r
197             int32_t cValue = cValues[i];\r
198             switch (shift) {\r
199                 case 0:\r
200                     if (cValue < 3) {\r
201                         shift = cValue + 1;\r
202                     } else if (cValue < 27) {\r
203                         FX_CHAR c40char = C40_BASIC_SET_CHARS[cValue];\r
204                         if (upperShift) {\r
205                             result += (FX_CHAR) (c40char + 128);\r
206                             upperShift = FALSE;\r
207                         } else {\r
208                             result += c40char;\r
209                         }\r
210                     } else {\r
211                         e = BCExceptionFormatException;\r
212                         return ;\r
213                     }\r
214                     break;\r
215                 case 1:\r
216                     if (upperShift) {\r
217                         result += (FX_CHAR) (cValue + 128);\r
218                         upperShift = FALSE;\r
219                     } else {\r
220                         result += cValue;\r
221                     }\r
222                     shift = 0;\r
223                     break;\r
224                 case 2:\r
225                     if (cValue < 27) {\r
226                         FX_CHAR c40char = C40_SHIFT2_SET_CHARS[cValue];\r
227                         if (upperShift) {\r
228                             result += (FX_CHAR) (c40char + 128);\r
229                             upperShift = FALSE;\r
230                         } else {\r
231                             result += c40char;\r
232                         }\r
233                     } else if (cValue == 27) {\r
234                         e = BCExceptionFormatException;\r
235                         return;\r
236                     } else if (cValue == 30) {\r
237                         upperShift = TRUE;\r
238                     } else {\r
239                         e = BCExceptionFormatException;\r
240                         return;\r
241                     }\r
242                     shift = 0;\r
243                     break;\r
244                 case 3:\r
245                     if (upperShift) {\r
246                         result += (FX_CHAR) (cValue + 224);\r
247                         upperShift = FALSE;\r
248                     } else {\r
249                         result += (FX_CHAR) (cValue + 96);\r
250                     }\r
251                     shift = 0;\r
252                     break;\r
253                 default:\r
254                     break;\r
255                     e = BCExceptionFormatException;\r
256                     return;\r
257             }\r
258         }\r
259     } while (bits->Available() > 0);\r
260 }\r
261 void CBC_DataMatrixDecodedBitStreamParser::DecodeTextSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, int32_t &e)\r
262 {\r
263     FX_BOOL upperShift = FALSE;\r
264     CFX_Int32Array cValues;\r
265     cValues.SetSize(3);\r
266     int32_t shift = 0;\r
267     do {\r
268         if (bits->Available() == 8) {\r
269             return;\r
270         }\r
271         int32_t firstByte = bits->ReadBits(8, e);\r
272         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
273         if (firstByte == 254) {\r
274             return;\r
275         }\r
276         int32_t inTp = bits->ReadBits(8, e);\r
277         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
278         ParseTwoBytes(firstByte, inTp, cValues);\r
279         for (int32_t i = 0; i < 3; i++) {\r
280             int32_t cValue = cValues[i];\r
281             switch (shift) {\r
282                 case 0:\r
283                     if (cValue < 3) {\r
284                         shift = cValue + 1;\r
285                     } else if (cValue < 40) {\r
286                         FX_CHAR textChar = TEXT_BASIC_SET_CHARS[cValue];\r
287                         if (upperShift) {\r
288                             result += (FX_CHAR) (textChar + 128);\r
289                             upperShift = FALSE;\r
290                         } else {\r
291                             result += textChar;\r
292                         }\r
293                     } else {\r
294                         e = BCExceptionFormatException;\r
295                         return;\r
296                     }\r
297                     break;\r
298                 case 1:\r
299                     if (upperShift) {\r
300                         result += (FX_CHAR) (cValue + 128);\r
301                         upperShift = FALSE;\r
302                     } else {\r
303                         result += cValue;\r
304                     }\r
305                     shift = 0;\r
306                     break;\r
307                 case 2:\r
308                     if (cValue < 27) {\r
309                         FX_CHAR c40char = C40_SHIFT2_SET_CHARS[cValue];\r
310                         if (upperShift) {\r
311                             result += (FX_CHAR) (c40char + 128);\r
312                             upperShift = FALSE;\r
313                         } else {\r
314                             result += c40char;\r
315                         }\r
316                     } else if (cValue == 27) {\r
317                         e = BCExceptionFormatException;\r
318                         return;\r
319                     } else if (cValue == 30) {\r
320                         upperShift = TRUE;\r
321                     } else {\r
322                         e = BCExceptionFormatException;\r
323                         return;\r
324                     }\r
325                     shift = 0;\r
326                     break;\r
327                 case 3:\r
328                     if (cValue < 19) {\r
329                         FX_CHAR textChar = TEXT_SHIFT3_SET_CHARS[cValue];\r
330                         if (upperShift) {\r
331                             result += (FX_CHAR) (textChar + 128);\r
332                             upperShift = FALSE;\r
333                         } else {\r
334                             result += textChar;\r
335                         }\r
336                         shift = 0;\r
337                     } else {\r
338                         e = BCExceptionFormatException;\r
339                         return;\r
340                     }\r
341                     break;\r
342                 default:\r
343                     break;\r
344                     e = BCExceptionFormatException;\r
345                     return;\r
346             }\r
347         }\r
348     } while (bits->Available() > 0);\r
349 }\r
350 void CBC_DataMatrixDecodedBitStreamParser::DecodeAnsiX12Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, int32_t &e)\r
351 {\r
352     CFX_Int32Array cValues;\r
353     cValues.SetSize(3);\r
354     do {\r
355         if (bits->Available() == 8) {\r
356             return;\r
357         }\r
358         int32_t firstByte = bits->ReadBits(8, e);\r
359         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
360         if (firstByte == 254) {\r
361             return;\r
362         }\r
363         int32_t iTemp1 = bits->ReadBits(8, e);\r
364         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
365         ParseTwoBytes(firstByte, iTemp1, cValues);\r
366         int32_t i;\r
367         for (i = 0; i < 3; i++) {\r
368             int32_t cValue = cValues[i];\r
369             if (cValue == 0) {\r
370                 BC_FX_ByteString_Append(result, 1, '\r');\r
371             } else if (cValue == 1) {\r
372                 BC_FX_ByteString_Append(result, 1, '*');\r
373             } else if (cValue == 2) {\r
374                 BC_FX_ByteString_Append(result, 1, '>');\r
375             } else if (cValue == 3) {\r
376                 BC_FX_ByteString_Append(result, 1, ' ');\r
377             } else if (cValue < 14) {\r
378                 BC_FX_ByteString_Append(result, 1, (FX_CHAR) (cValue + 44));\r
379             } else if (cValue < 40) {\r
380                 BC_FX_ByteString_Append(result, 1, (FX_CHAR) (cValue + 51));\r
381             } else {\r
382                 e = BCExceptionFormatException;\r
383                 return;\r
384             }\r
385         }\r
386     } while (bits->Available() > 0);\r
387 }\r
388 void CBC_DataMatrixDecodedBitStreamParser::ParseTwoBytes(int32_t firstByte, int32_t secondByte, CFX_Int32Array &result)\r
389 {\r
390     int32_t fullBitValue = (firstByte << 8) + secondByte - 1;\r
391     int32_t temp = fullBitValue / 1600;\r
392     result[0] = temp;\r
393     fullBitValue -= temp * 1600;\r
394     temp = fullBitValue / 40;\r
395     result[1] = temp;\r
396     result[2] = fullBitValue - temp * 40;\r
397 }\r
398 void CBC_DataMatrixDecodedBitStreamParser::DecodeEdifactSegment(CBC_CommonBitSource *bits, CFX_ByteString &result, int32_t &e)\r
399 {\r
400     FX_CHAR buffer[128];\r
401     FX_BOOL unlatch = FALSE;\r
402     do {\r
403         if (bits->Available() <= 16) {\r
404             return;\r
405         }\r
406         int32_t i;\r
407         for (i = 0; i < 4; i++) {\r
408             int32_t edifactValue = bits->ReadBits(6, e);\r
409             BC_EXCEPTION_CHECK_ReturnVoid(e);\r
410             if (edifactValue == 0x1F) {\r
411                 unlatch = TRUE;\r
412             }\r
413             if (!unlatch) {\r
414                 if ((edifactValue & 32) == 0) {\r
415                     edifactValue |= 64;\r
416                 }\r
417 #if defined(_FX_WINAPI_PARTITION_APP_)\r
418                 memset(buffer, 0, sizeof(FX_CHAR) * 128);\r
419                 _itoa_s(edifactValue, buffer, 128, 10);\r
420                 result += buffer;\r
421 #else\r
422                 result += FXSYS_itoa(edifactValue, buffer, 10);\r
423 #endif\r
424             }\r
425         }\r
426     } while (!unlatch && bits->Available() > 0);\r
427 }\r
428 void CBC_DataMatrixDecodedBitStreamParser::DecodeBase256Segment(CBC_CommonBitSource *bits, CFX_ByteString &result, CFX_Int32Array &byteSegments, int32_t &e)\r
429 {\r
430     int32_t codewordPosition = 1 + bits->getByteOffset();\r
431     int32_t iTmp =  bits->ReadBits(8, e);\r
432     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
433     int32_t d1 = Unrandomize255State(iTmp, codewordPosition++);\r
434     int32_t count;\r
435     if (d1 == 0) {\r
436         count = bits->Available() / 8;\r
437     } else if (d1 < 250) {\r
438         count = d1;\r
439     } else {\r
440         int32_t iTmp3 = bits->ReadBits(8, e);\r
441         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
442         count = 250 * (d1 - 249) + Unrandomize255State(iTmp3, codewordPosition++);\r
443     }\r
444     if (count < 0) {\r
445         e = BCExceptionFormatException;\r
446         return;\r
447     }\r
448     CFX_ByteArray *bytes = FX_NEW CFX_ByteArray();\r
449     bytes->SetSize(count);\r
450     int32_t i;\r
451     for (i = 0; i < count; i++) {\r
452         if (bits->Available() < 8) {\r
453             e  = BCExceptionFormatException;\r
454             delete bytes;\r
455             return;\r
456         }\r
457         int32_t iTemp5 = bits->ReadBits(8, e);\r
458         if (e != BCExceptionNO) {\r
459             delete bytes;\r
460             return;\r
461         }\r
462         bytes->SetAt(i, Unrandomize255State(iTemp5, codewordPosition++));\r
463     }\r
464     BC_FX_ByteString_Append(result, *bytes);\r
465     delete bytes;\r
466 }\r
467 uint8_t CBC_DataMatrixDecodedBitStreamParser::Unrandomize255State(int32_t randomizedBase256Codeword, int32_t base256CodewordPosition)\r
468 {\r
469     int32_t pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\r
470     int32_t tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\r
471     return (uint8_t) (tempVariable >= 0 ? tempVariable : tempVariable + 256);\r
472 }\r