Merge to XFA: Kill FXSYS_mem{cpy,cmp,set.move}{32,8}.
[pdfium.git] / xfa / src / fxbarcode / qrcode / BC_QRDecodedBitStreamParser.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 2007 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 "../BC_UtilCodingConvert.h"\r
25 #include "../common/BC_CommonBitSource.h"\r
26 #include "../common/BC_CommonECI.h"\r
27 #include "../common/BC_CommonCharacterSetECI.h"\r
28 #include "../common/BC_CommonDecoderResult.h"\r
29 #include "BC_QRCoderMode.h"\r
30 #include "BC_QRDecodedBitStreamParser.h"\r
31 const FX_CHAR* CBC_QRDecodedBitStreamParser::UTF_8 = "utf8";\r
32 const FX_CHAR CBC_QRDecodedBitStreamParser::ALPHANUMERIC_CHARS[45] = {\r
33     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',\r
34     'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',\r
35     'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\r
36     ' ', '$', '%', '*', '+', '-', '.', '/', ':'\r
37 };\r
38 CBC_QRDecodedBitStreamParser::CBC_QRDecodedBitStreamParser()\r
39 {\r
40 }\r
41 CBC_QRDecodedBitStreamParser::~CBC_QRDecodedBitStreamParser()\r
42 {\r
43 }\r
44 CBC_CommonDecoderResult* CBC_QRDecodedBitStreamParser::Decode(CFX_ByteArray *bytes, CBC_QRCoderVersion *version,\r
45         CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t byteModeDecode, int32_t &e)\r
46 {\r
47     CBC_CommonBitSource bits(bytes);\r
48     CFX_ByteString result;\r
49     CBC_CommonCharacterSetECI* currentCharacterSetECI = NULL;\r
50     FX_BOOL fc1Infact = FALSE;\r
51     CFX_Int32Array byteSegments;\r
52     CBC_QRCoderMode* mode = NULL;\r
53     do {\r
54         if(bits.Available() < 4) {\r
55             mode = CBC_QRCoderMode::sTERMINATOR;\r
56         } else {\r
57             int32_t iTemp1 = bits.ReadBits(4, e);\r
58             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
59             mode = CBC_QRCoderMode::ForBits(iTemp1, e);\r
60             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
61             if(mode == NULL) {\r
62                 e = BCExceptionUnSupportMode;\r
63                 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
64             }\r
65         }\r
66         if(!(mode == CBC_QRCoderMode::sTERMINATOR)) {\r
67             if(mode == CBC_QRCoderMode::sFNC1_FIRST_POSITION || mode == CBC_QRCoderMode::sFNC1_SECOND_POSITION) {\r
68                 fc1Infact = TRUE;\r
69             } else if(mode == CBC_QRCoderMode::sSTRUCTURED_APPEND) {\r
70                 bits.ReadBits(16, e);\r
71                 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
72             } else if(mode == CBC_QRCoderMode::sECI) {\r
73                 int32_t value = ParseECIValue(&bits, e);\r
74                 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
75                 currentCharacterSetECI = CBC_CommonCharacterSetECI::GetCharacterSetECIByValue(value);\r
76             } else {\r
77                 if(mode == CBC_QRCoderMode::sGBK) {\r
78                     bits.ReadBits(4, e);\r
79                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
80                 }\r
81                 int32_t numBits = mode->GetCharacterCountBits(version, e);\r
82                 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
83                 int32_t count = bits.ReadBits(numBits, e);\r
84                 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
85                 if(mode == CBC_QRCoderMode::sNUMERIC) {\r
86                     DecodeNumericSegment(&bits, result, count, e);\r
87                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
88                 } else if(mode == CBC_QRCoderMode::sALPHANUMERIC) {\r
89                     DecodeAlphanumericSegment(&bits, result, count, fc1Infact, e);\r
90                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
91                 } else if(mode == CBC_QRCoderMode::sBYTE) {\r
92                     DecodeByteSegment(&bits, result, count, currentCharacterSetECI, &byteSegments, byteModeDecode, e);\r
93                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
94                 } else if(mode == CBC_QRCoderMode::sGBK) {\r
95                     DecodeGBKSegment(&bits, result, count, e);\r
96                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
97                 } else if(mode == CBC_QRCoderMode::sKANJI) {\r
98                     DecodeKanjiSegment(&bits, result, count, e);\r
99                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
100                 } else {\r
101                     e = BCExceptionUnSupportMode;\r
102                     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
103                 }\r
104             }\r
105         }\r
106     } while (!(mode == CBC_QRCoderMode::sTERMINATOR));\r
107     CBC_CommonDecoderResult *tempCd = FX_NEW CBC_CommonDecoderResult();\r
108     tempCd->Init(*bytes, result, byteSegments, ecLevel, e);\r
109     BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
110     return tempCd;\r
111 }\r
112 void CBC_QRDecodedBitStreamParser::DecodeGBKSegment(CBC_CommonBitSource* bits, CFX_ByteString &result, int32_t count, int32_t &e)\r
113 {\r
114     CFX_ByteString buffer;\r
115     int32_t offset = 0;\r
116     while (count > 0) {\r
117         int32_t twoBytes = bits->ReadBits(13, e);\r
118         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
119         int32_t assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);\r
120         if (assembledTwoBytes <= 0x0095d) {\r
121             assembledTwoBytes += 0x0a1a1;\r
122         } else {\r
123             assembledTwoBytes += 0x0a6a1;\r
124         }\r
125         buffer += (uint8_t) (assembledTwoBytes >> 8);\r
126         buffer += (uint8_t) assembledTwoBytes;\r
127         count--;\r
128     }\r
129     CBC_UtilCodingConvert::LocaleToUtf8(buffer, result);\r
130 }\r
131 void CBC_QRDecodedBitStreamParser::DecodeKanjiSegment(CBC_CommonBitSource* bits, CFX_ByteString &result, int32_t count, int32_t &e)\r
132 {\r
133     CFX_ByteString buffer;\r
134     while (count > 0) {\r
135         int32_t twoBytes = bits->ReadBits(13, e);\r
136         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
137         int32_t assembledTwoBytes = ((twoBytes / 0x0c0) << 8) | (twoBytes % 0x0c0);\r
138         if (assembledTwoBytes <= 0x01f00) {\r
139             assembledTwoBytes += 0x08140;\r
140         } else {\r
141             assembledTwoBytes += 0x0c140;\r
142         }\r
143         buffer += (uint8_t) (assembledTwoBytes >> 8);\r
144         buffer += (uint8_t) assembledTwoBytes;\r
145         count--;\r
146     }\r
147     CBC_UtilCodingConvert::LocaleToUtf8(buffer, result);\r
148 }\r
149 void CBC_QRDecodedBitStreamParser::DecodeByteSegment(CBC_CommonBitSource* bits, CFX_ByteString &result, int32_t count,\r
150         CBC_CommonCharacterSetECI *currentCharacterSetECI,\r
151         CFX_Int32Array *byteSegments, int32_t byteModeDecode, int32_t &e)\r
152 {\r
153     if(count < 0) {\r
154         e = BCExceptionNotFound;\r
155         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
156     }\r
157     if((count << 3) > bits->Available()) {\r
158         e = BCExceptionRead;\r
159         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
160     }\r
161     uint8_t *readBytes = FX_Alloc(uint8_t, count);\r
162     FXSYS_memset(readBytes, 0x00, count);\r
163     for(int32_t i = 0; i < count; i++) {\r
164         readBytes[i] = (uint8_t) bits->ReadBits(8, e);\r
165         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
166     }\r
167     CFX_ByteString bs(readBytes, count);\r
168     result += bs;\r
169     FX_Free(readBytes);\r
170 }\r
171 void CBC_QRDecodedBitStreamParser::DecodeAlphanumericSegment(CBC_CommonBitSource* bits,\r
172         CFX_ByteString &result, int32_t count, FX_BOOL fac1InEffect, int32_t &e)\r
173 {\r
174     int32_t start = result.GetLength();\r
175     while(count > 1) {\r
176         int32_t nextTwoCharsBits = bits->ReadBits(11, e);\r
177         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
178         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[nextTwoCharsBits / 45]);\r
179         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]);\r
180         count -= 2;\r
181     }\r
182     if(count == 1) {\r
183         int32_t itemp = bits->ReadBits(6, e);\r
184         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
185         BC_FX_ByteString_Append(result,  1, ALPHANUMERIC_CHARS[itemp]);\r
186     }\r
187     if(fac1InEffect) {\r
188         for(int32_t i = start; i < result.GetLength(); i++) {\r
189             if(result[i] == '%') {\r
190                 if((i < result.GetLength() - 1) && result[i + 1] == '%') {\r
191                     result.Delete(i + 1, 1);\r
192                 } else {\r
193                     result.SetAt(i, (FX_CHAR)0x1d);\r
194                 }\r
195             }\r
196         }\r
197     }\r
198 }\r
199 void CBC_QRDecodedBitStreamParser::DecodeNumericSegment(CBC_CommonBitSource* bits, CFX_ByteString &result, int32_t count, int32_t &e)\r
200 {\r
201     while(count >= 3) {\r
202         int32_t threeDigitsBits = bits->ReadBits(10, e);\r
203         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
204         if(threeDigitsBits >= 1000) {\r
205             e = BCExceptionRead;\r
206             BC_EXCEPTION_CHECK_ReturnVoid(e);\r
207         }\r
208         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[threeDigitsBits / 100]);\r
209         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]);\r
210         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[threeDigitsBits % 10]);\r
211         count -= 3;\r
212     }\r
213     if(count == 2) {\r
214         int32_t twoDigitBits = bits->ReadBits(7, e);\r
215         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
216         if(twoDigitBits >= 100) {\r
217             e = BCExceptionRead;\r
218             BC_EXCEPTION_CHECK_ReturnVoid(e);\r
219         }\r
220         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[twoDigitBits / 10]);\r
221         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[twoDigitBits % 10]);\r
222     } else if(count == 1) {\r
223         int32_t digitBits = bits->ReadBits(4, e);\r
224         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
225         if(digitBits >= 10) {\r
226             e = BCExceptionRead;\r
227             BC_EXCEPTION_CHECK_ReturnVoid(e);\r
228         }\r
229         BC_FX_ByteString_Append(result, 1, ALPHANUMERIC_CHARS[digitBits]);\r
230     }\r
231 }\r
232 const CFX_ByteString CBC_QRDecodedBitStreamParser::GuessEncoding(CFX_ByteArray *bytes)\r
233 {\r
234     return *UTF_8;\r
235 }\r
236 int32_t CBC_QRDecodedBitStreamParser::ParseECIValue(CBC_CommonBitSource* bits, int32_t &e)\r
237 {\r
238     int32_t firstByte = bits->ReadBits(8, e);\r
239     BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
240     if((firstByte & 0x80) == 0) {\r
241         return firstByte & 0x7f;\r
242     } else if((firstByte & 0xc0) == 0x80) {\r
243         int32_t secondByte = bits->ReadBits(8, e);\r
244         BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
245         return ((firstByte & 0x3f) << 8) | secondByte;\r
246     } else if((firstByte & 0xe0) == 0xc0) {\r
247         int32_t secondThirdByte = bits->ReadBits(16, e);\r
248         BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
249         return ((firstByte & 0x1f) << 16) | secondThirdByte;\r
250     }\r
251     e = BCExceptionBadECI;\r
252     BC_EXCEPTION_CHECK_ReturnValue(e, 0);\r
253     return 0;\r
254 }\r