/src/libreoffice/sal/textenc/tcvtmb.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <rtl/textcvt.h> |
23 | | |
24 | | #include "handleundefinedunicodetotextchar.hxx" |
25 | | #include "tenchelp.hxx" |
26 | | #include "unichars.hxx" |
27 | | |
28 | | /* DBCS to Unicode conversion routine use a lead table for the first byte, */ |
29 | | /* where we determine the trail table or for single byte chars the unicode */ |
30 | | /* value. We have for all lead byte a separate table, because we can */ |
31 | | /* then share many tables for different charset encodings. */ |
32 | | |
33 | | sal_Size ImplDBCSToUnicode( const void* pData, SAL_UNUSED_PARAMETER void*, |
34 | | const char* pSrcBuf, sal_Size nSrcBytes, |
35 | | sal_Unicode* pDestBuf, sal_Size nDestChars, |
36 | | sal_uInt32 nFlags, sal_uInt32* pInfo, |
37 | | sal_Size* pSrcCvtBytes ) |
38 | 520k | { |
39 | 520k | unsigned char cTrail; |
40 | 520k | sal_Unicode cConv; |
41 | 520k | const ImplDBCSToUniLeadTab* pLeadEntry; |
42 | 520k | const ImplDBCSConvertData* pConvertData = static_cast<const ImplDBCSConvertData*>(pData); |
43 | 520k | const ImplDBCSToUniLeadTab* pLeadTab = pConvertData->mpToUniLeadTab; |
44 | 520k | sal_Unicode* pEndDestBuf; |
45 | 520k | const char* pEndSrcBuf; |
46 | 520k | char const * startOfCurrentChar = pSrcBuf; |
47 | | |
48 | 520k | *pInfo = 0; |
49 | 520k | pEndDestBuf = pDestBuf+nDestChars; |
50 | 520k | pEndSrcBuf = pSrcBuf+nSrcBytes; |
51 | 18.7M | while ( pSrcBuf < pEndSrcBuf ) |
52 | 18.2M | { |
53 | 18.2M | unsigned char cLead = static_cast<unsigned char>(*pSrcBuf); |
54 | | |
55 | | /* get entry for the lead byte */ |
56 | 18.2M | pLeadEntry = pLeadTab+cLead; |
57 | | |
58 | | /* SingleByte char? */ |
59 | 18.2M | if (pLeadEntry->mpToUniTrailTab == nullptr |
60 | 388k | || cLead < pConvertData->mnLeadStart |
61 | 388k | || cLead > pConvertData->mnLeadEnd) |
62 | 17.8M | { |
63 | 17.8M | cConv = pLeadEntry->mnUniChar; |
64 | 17.8M | if ( !cConv && (cLead != 0) ) |
65 | 77.5k | { |
66 | 77.5k | *pInfo |= RTL_TEXTTOUNICODE_INFO_UNDEFINED; |
67 | 77.5k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR ) |
68 | 18.8k | { |
69 | 18.8k | if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0) { |
70 | 3.83k | ++pSrcBuf; |
71 | 15.0k | } else { |
72 | 15.0k | pSrcBuf = startOfCurrentChar; |
73 | 15.0k | } |
74 | 18.8k | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR; |
75 | 18.8k | break; |
76 | 18.8k | } |
77 | 58.6k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE ) |
78 | 0 | { |
79 | 0 | pSrcBuf++; |
80 | 0 | startOfCurrentChar = pSrcBuf; |
81 | 0 | continue; |
82 | 0 | } |
83 | 58.6k | cConv = ImplGetUndefinedUnicodeChar(cLead, nFlags); |
84 | 58.6k | } |
85 | 17.8M | } |
86 | 388k | else |
87 | 388k | { |
88 | | /* Source buffer too small */ |
89 | 388k | if ( pSrcBuf +1 == pEndSrcBuf ) |
90 | 23.6k | { |
91 | 23.6k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0 ) |
92 | 19.4k | { |
93 | 19.4k | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL; |
94 | 19.4k | break; |
95 | 19.4k | } |
96 | 4.20k | cConv = 0; |
97 | 4.20k | } |
98 | 364k | else |
99 | 364k | { |
100 | 364k | pSrcBuf++; |
101 | 364k | cTrail = static_cast<unsigned char>(*pSrcBuf); |
102 | 364k | if ( (cTrail >= pLeadEntry->mnTrailStart) && (cTrail <= pLeadEntry->mnTrailEnd) ) |
103 | 185k | cConv = pLeadEntry->mpToUniTrailTab[cTrail-pLeadEntry->mnTrailStart]; |
104 | 179k | else |
105 | 179k | cConv = 0; |
106 | | |
107 | 364k | if ( !cConv ) |
108 | 188k | { |
109 | | /* EUDC Ranges */ |
110 | 188k | sal_uInt16 i; |
111 | 188k | const ImplDBCSEUDCData* pEUDCTab = pConvertData->mpEUDCTab; |
112 | 427k | for ( i = 0; i < pConvertData->mnEUDCCount; i++ ) |
113 | 298k | { |
114 | 298k | if ( (cLead >= pEUDCTab->mnLeadStart) && |
115 | 168k | (cLead <= pEUDCTab->mnLeadEnd) ) |
116 | 84.5k | { |
117 | 84.5k | if ( (cTrail >= pEUDCTab->mnTrail1Start) && |
118 | 67.4k | (cTrail <= pEUDCTab->mnTrail1End) ) |
119 | 9.38k | { |
120 | 9.38k | cConv = pEUDCTab->mnUniStart+ |
121 | 9.38k | ((cLead-pEUDCTab->mnLeadStart)*pEUDCTab->mnTrailRangeCount)+ |
122 | 9.38k | (cTrail-pEUDCTab->mnTrail1Start); |
123 | 9.38k | break; |
124 | 9.38k | } |
125 | 75.1k | sal_uInt16 nTrailCount = pEUDCTab->mnTrail1End-pEUDCTab->mnTrail1Start+1; |
126 | 75.1k | if ( (pEUDCTab->mnTrailCount >= 2) && |
127 | 70.6k | (cTrail >= pEUDCTab->mnTrail2Start) && |
128 | 53.3k | (cTrail <= pEUDCTab->mnTrail2End) ) |
129 | 50.0k | { |
130 | 50.0k | cConv = pEUDCTab->mnUniStart+ |
131 | 50.0k | ((cLead-pEUDCTab->mnLeadStart)*pEUDCTab->mnTrailRangeCount)+ |
132 | 50.0k | nTrailCount+ |
133 | 50.0k | (cTrail-pEUDCTab->mnTrail2Start); |
134 | 50.0k | break; |
135 | 50.0k | } |
136 | 25.1k | nTrailCount = pEUDCTab->mnTrail2End-pEUDCTab->mnTrail2Start+1; |
137 | 25.1k | if ( (pEUDCTab->mnTrailCount >= 3) && |
138 | 0 | (cTrail >= pEUDCTab->mnTrail3Start) && |
139 | 0 | (cTrail <= pEUDCTab->mnTrail3End) ) |
140 | 0 | { |
141 | 0 | cConv = pEUDCTab->mnUniStart+ |
142 | 0 | ((cLead-pEUDCTab->mnLeadStart)*pEUDCTab->mnTrailRangeCount)+ |
143 | 0 | nTrailCount+ |
144 | 0 | (cTrail-pEUDCTab->mnTrail3Start); |
145 | 0 | break; |
146 | 0 | } |
147 | 25.1k | } |
148 | | |
149 | 238k | pEUDCTab++; |
150 | 238k | } |
151 | | |
152 | 188k | if ( !cConv ) |
153 | 128k | { |
154 | | /* We compare the full range of the trail we defined, */ |
155 | | /* which can often be greater than the limit. We do this */ |
156 | | /* so that extensions that don't consider encodings */ |
157 | | /* correctly treat double-byte characters as a single */ |
158 | | /* character as much as possible. */ |
159 | | |
160 | 128k | if (cLead < pConvertData->mnLeadStart |
161 | 128k | || cLead > pConvertData->mnLeadEnd |
162 | 128k | || cTrail < pConvertData->mnTrailStart |
163 | 77.3k | || cTrail > pConvertData->mnTrailEnd) |
164 | 61.6k | { |
165 | 61.6k | *pInfo |= RTL_TEXTTOUNICODE_INFO_INVALID; |
166 | 61.6k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR ) |
167 | 4.92k | { |
168 | 4.92k | if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0) { |
169 | 3.94k | ++pSrcBuf; |
170 | 3.94k | } else { |
171 | 979 | pSrcBuf = startOfCurrentChar; |
172 | 979 | } |
173 | 4.92k | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR; |
174 | 4.92k | break; |
175 | 4.92k | } |
176 | 56.7k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE ) |
177 | 994 | { |
178 | 994 | pSrcBuf++; |
179 | 994 | startOfCurrentChar = pSrcBuf; |
180 | 994 | continue; |
181 | 994 | } |
182 | 55.7k | cConv = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER; |
183 | 55.7k | } |
184 | 128k | } |
185 | 188k | } |
186 | 364k | } |
187 | 362k | if ( !cConv ) |
188 | 71.3k | { |
189 | 71.3k | *pInfo |= RTL_TEXTTOUNICODE_INFO_MBUNDEFINED; |
190 | 71.3k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR ) |
191 | 8.08k | { |
192 | 8.08k | if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0) { |
193 | 5.43k | ++pSrcBuf; |
194 | 5.43k | } else { |
195 | 2.65k | pSrcBuf = startOfCurrentChar; |
196 | 2.65k | } |
197 | 8.08k | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR; |
198 | 8.08k | break; |
199 | 8.08k | } |
200 | 63.2k | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE ) |
201 | 0 | { |
202 | 0 | pSrcBuf++; |
203 | 0 | startOfCurrentChar = pSrcBuf; |
204 | 0 | continue; |
205 | 0 | } |
206 | 63.2k | cConv = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER; |
207 | 63.2k | } |
208 | 362k | } |
209 | | |
210 | 18.2M | if ( pDestBuf == pEndDestBuf ) |
211 | 0 | { |
212 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL; |
213 | 0 | break; |
214 | 0 | } |
215 | | |
216 | 18.2M | *pDestBuf = cConv; |
217 | 18.2M | pDestBuf++; |
218 | 18.2M | pSrcBuf++; |
219 | 18.2M | startOfCurrentChar = pSrcBuf; |
220 | 18.2M | } |
221 | | |
222 | 520k | *pSrcCvtBytes = nSrcBytes - (pEndSrcBuf-pSrcBuf); |
223 | 520k | return (nDestChars - (pEndDestBuf-pDestBuf)); |
224 | 520k | } |
225 | | |
226 | | sal_Size ImplUnicodeToDBCS( const void* pData, SAL_UNUSED_PARAMETER void*, |
227 | | const sal_Unicode* pSrcBuf, sal_Size nSrcChars, |
228 | | char* pDestBuf, sal_Size nDestBytes, |
229 | | sal_uInt32 nFlags, sal_uInt32* pInfo, |
230 | | sal_Size* pSrcCvtChars ) |
231 | 8.32k | { |
232 | 8.32k | sal_uInt16 cConv; |
233 | 8.32k | sal_Unicode c; |
234 | 8.32k | const ImplUniToDBCSHighTab* pHighEntry; |
235 | 8.32k | const ImplDBCSConvertData* pConvertData = static_cast<const ImplDBCSConvertData*>(pData); |
236 | 8.32k | const ImplUniToDBCSHighTab* pHighTab = pConvertData->mpToDBCSHighTab; |
237 | 8.32k | char* pEndDestBuf; |
238 | 8.32k | const sal_Unicode* pEndSrcBuf; |
239 | | |
240 | 8.32k | bool bCheckRange = |
241 | 8.32k | pConvertData->mnLeadStart != 0 || pConvertData->mnLeadEnd != 0xFF; |
242 | | /* this statement has the effect that this extra check is only done for |
243 | | EUC-KR, which uses the MS-949 tables, but does not support the full |
244 | | range of MS-949 */ |
245 | | |
246 | 8.32k | *pInfo = 0; |
247 | 8.32k | pEndDestBuf = pDestBuf+nDestBytes; |
248 | 8.32k | pEndSrcBuf = pSrcBuf+nSrcChars; |
249 | 16.6k | while ( pSrcBuf < pEndSrcBuf ) |
250 | 8.32k | { |
251 | 8.32k | c = *pSrcBuf; |
252 | 8.32k | unsigned char nHighChar = static_cast<unsigned char>((c >> 8) & 0xFF); |
253 | 8.32k | unsigned char nLowChar = static_cast<unsigned char>(c & 0xFF); |
254 | | |
255 | | /* get entry for the high byte */ |
256 | 8.32k | pHighEntry = pHighTab+nHighChar; |
257 | | |
258 | | /* is low byte in the table range */ |
259 | 8.32k | if ( (nLowChar >= pHighEntry->mnLowStart) && (nLowChar <= pHighEntry->mnLowEnd) ) |
260 | 5.36k | { |
261 | 5.36k | cConv = pHighEntry->mpToUniTrailTab[nLowChar-pHighEntry->mnLowStart]; |
262 | 5.36k | if (bCheckRange && cConv > 0x7F |
263 | 0 | && ((cConv >> 8) < pConvertData->mnLeadStart |
264 | 0 | || (cConv >> 8) > pConvertData->mnLeadEnd |
265 | 0 | || (cConv & 0xFF) < pConvertData->mnTrailStart |
266 | 0 | || (cConv & 0xFF) > pConvertData->mnTrailEnd)) |
267 | 0 | cConv = 0; |
268 | 5.36k | } |
269 | 2.96k | else |
270 | 2.96k | cConv = 0; |
271 | | |
272 | 8.32k | if (cConv == 0 && c != 0) |
273 | 3.17k | { |
274 | | /* Map to EUDC ranges: */ |
275 | 3.17k | ImplDBCSEUDCData const * pEUDCTab = pConvertData->mpEUDCTab; |
276 | 3.17k | sal_uInt32 i; |
277 | 9.69k | for (i = 0; i < pConvertData->mnEUDCCount; ++i) |
278 | 7.16k | { |
279 | 7.16k | if (c >= pEUDCTab->mnUniStart && c <= pEUDCTab->mnUniEnd) |
280 | 635 | { |
281 | 635 | sal_uInt32 nIndex = c - pEUDCTab->mnUniStart; |
282 | 635 | sal_uInt32 nLeadOff |
283 | 635 | = nIndex / pEUDCTab->mnTrailRangeCount; |
284 | 635 | sal_uInt32 nTrailOff |
285 | 635 | = nIndex % pEUDCTab->mnTrailRangeCount; |
286 | 635 | sal_uInt32 nSize; |
287 | 635 | cConv = static_cast<sal_uInt16>((pEUDCTab->mnLeadStart + nLeadOff) << 8); |
288 | 635 | nSize |
289 | 635 | = pEUDCTab->mnTrail1End - pEUDCTab->mnTrail1Start + 1; |
290 | 635 | if (nTrailOff < nSize) |
291 | 184 | { |
292 | 184 | cConv |= pEUDCTab->mnTrail1Start + nTrailOff; |
293 | 184 | break; |
294 | 184 | } |
295 | 451 | nTrailOff -= nSize; |
296 | 451 | nSize |
297 | 451 | = pEUDCTab->mnTrail2End - pEUDCTab->mnTrail2Start + 1; |
298 | 451 | if (nTrailOff < nSize) |
299 | 451 | { |
300 | 451 | cConv |= pEUDCTab->mnTrail2Start + nTrailOff; |
301 | 451 | break; |
302 | 451 | } |
303 | 0 | nTrailOff -= nSize; |
304 | 0 | cConv |= pEUDCTab->mnTrail3Start + nTrailOff; |
305 | 0 | break; |
306 | 451 | } |
307 | 6.52k | pEUDCTab++; |
308 | 6.52k | } |
309 | | |
310 | | /* FIXME |
311 | | * SB: Not sure why this is in here. Plus, it does not work as |
312 | | * intended when (c & 0xFF) == 0, because the next !cConv check |
313 | | * will then think c has not yet been converted... |
314 | | */ |
315 | 3.17k | if (c >= RTL_TEXTCVT_BYTE_PRIVATE_START |
316 | 2.92k | && c <= RTL_TEXTCVT_BYTE_PRIVATE_END) |
317 | 1.84k | { |
318 | 1.84k | if ( nFlags & RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 ) |
319 | 1.84k | cConv = static_cast< char >(static_cast< unsigned char >(c & 0xFF)); |
320 | 1.84k | } |
321 | 3.17k | } |
322 | | |
323 | 8.32k | if (cConv == 0 && c != 0) |
324 | 1.35k | { |
325 | 1.35k | if ( nFlags & RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE ) |
326 | 1.35k | { |
327 | | /* !!! */ |
328 | 1.35k | } |
329 | | |
330 | 1.35k | if ( nFlags & RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR ) |
331 | 0 | { |
332 | | /* !!! */ |
333 | 0 | } |
334 | | |
335 | | /* Handle undefined and surrogates characters */ |
336 | | /* (all surrogates characters are undefined) */ |
337 | 1.35k | if (sal::detail::textenc::handleUndefinedUnicodeToTextChar( |
338 | 1.35k | &pSrcBuf, pEndSrcBuf, &pDestBuf, pEndDestBuf, nFlags, |
339 | 1.35k | pInfo)) |
340 | 1.35k | continue; |
341 | 0 | break; |
342 | 1.35k | } |
343 | | |
344 | | /* SingleByte */ |
345 | 6.97k | if ( !(cConv & 0xFF00) ) |
346 | 4.52k | { |
347 | 4.52k | if ( pDestBuf == pEndDestBuf ) |
348 | 0 | { |
349 | 0 | *pInfo |= RTL_UNICODETOTEXT_INFO_ERROR | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL; |
350 | 0 | break; |
351 | 0 | } |
352 | | |
353 | 4.52k | *pDestBuf = static_cast< char >(static_cast< unsigned char >(cConv & 0xFF)); |
354 | 4.52k | pDestBuf++; |
355 | 4.52k | } |
356 | 2.44k | else |
357 | 2.44k | { |
358 | 2.44k | if ( pDestBuf+1 >= pEndDestBuf ) |
359 | 0 | { |
360 | 0 | *pInfo |= RTL_UNICODETOTEXT_INFO_ERROR | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL; |
361 | 0 | break; |
362 | 0 | } |
363 | | |
364 | 2.44k | *pDestBuf = static_cast< char >(static_cast< unsigned char >((cConv >> 8) & 0xFF)); |
365 | 2.44k | pDestBuf++; |
366 | 2.44k | *pDestBuf = static_cast< char >(static_cast< unsigned char >(cConv & 0xFF)); |
367 | 2.44k | pDestBuf++; |
368 | 2.44k | } |
369 | | |
370 | 6.97k | pSrcBuf++; |
371 | 6.97k | } |
372 | | |
373 | 8.32k | *pSrcCvtChars = nSrcChars - (pEndSrcBuf-pSrcBuf); |
374 | 8.32k | return (nDestBytes - (pEndDestBuf-pDestBuf)); |
375 | 8.32k | } |
376 | | |
377 | 0 | #define JIS_EUC_LEAD_OFF 0x80 |
378 | 0 | #define JIS_EUC_TRAIL_OFF 0x80 |
379 | | |
380 | | sal_Size ImplEUCJPToUnicode( const void* pData, |
381 | | SAL_UNUSED_PARAMETER void*, |
382 | | const char* pSrcBuf, sal_Size nSrcBytes, |
383 | | sal_Unicode* pDestBuf, sal_Size nDestChars, |
384 | | sal_uInt32 nFlags, sal_uInt32* pInfo, |
385 | | sal_Size* pSrcCvtBytes ) |
386 | 0 | { |
387 | 0 | unsigned char cLead = '\0'; |
388 | 0 | unsigned char cTrail = '\0'; |
389 | 0 | sal_Unicode cConv; |
390 | 0 | const ImplDBCSToUniLeadTab* pLeadEntry; |
391 | 0 | const ImplDBCSToUniLeadTab* pLeadTab; |
392 | 0 | const ImplEUCJPConvertData* pConvertData = static_cast<const ImplEUCJPConvertData*>(pData); |
393 | 0 | sal_Unicode* pEndDestBuf; |
394 | 0 | const char* pEndSrcBuf; |
395 | 0 | char const * startOfCurrentChar = pSrcBuf; |
396 | |
|
397 | 0 | *pInfo = 0; |
398 | 0 | pEndDestBuf = pDestBuf+nDestChars; |
399 | 0 | pEndSrcBuf = pSrcBuf+nSrcBytes; |
400 | 0 | while ( pSrcBuf < pEndSrcBuf ) |
401 | 0 | { |
402 | 0 | unsigned char c = static_cast<unsigned char>(*pSrcBuf); |
403 | | |
404 | | /* ASCII */ |
405 | 0 | if ( c <= 0x7F ) |
406 | 0 | cConv = c; |
407 | 0 | else |
408 | 0 | { |
409 | | /* SS2 - Half-width katakana */ |
410 | | /* 8E + A1-DF */ |
411 | 0 | if ( c == 0x8E ) |
412 | 0 | { |
413 | | /* Source buffer too small */ |
414 | 0 | if ( pSrcBuf + 1 == pEndSrcBuf ) |
415 | 0 | { |
416 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL; |
417 | 0 | break; |
418 | 0 | } |
419 | | |
420 | 0 | pSrcBuf++; |
421 | 0 | c = static_cast<unsigned char>(*pSrcBuf); |
422 | 0 | if ( (c >= 0xA1) && (c <= 0xDF) ) |
423 | 0 | cConv = 0xFF61+(c-0xA1); |
424 | 0 | else |
425 | 0 | { |
426 | 0 | cConv = 0; |
427 | 0 | cLead = 0x8E; |
428 | 0 | cTrail = c; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | else |
432 | 0 | { |
433 | | /* SS3 - JIS 0212-1990 */ |
434 | | /* 8F + A1-FE + A1-FE */ |
435 | 0 | if ( c == 0x8F ) |
436 | 0 | { |
437 | | /* Source buffer too small */ |
438 | 0 | if (pEndSrcBuf - pSrcBuf < 3) |
439 | 0 | { |
440 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL; |
441 | 0 | break; |
442 | 0 | } |
443 | | |
444 | 0 | pSrcBuf++; |
445 | 0 | cLead = static_cast<unsigned char>(*pSrcBuf); |
446 | 0 | pSrcBuf++; |
447 | 0 | cTrail = static_cast<unsigned char>(*pSrcBuf); |
448 | 0 | pLeadTab = pConvertData->mpJIS0212ToUniLeadTab; |
449 | 0 | } |
450 | | /* CodeSet 2 JIS 0208-1997 */ |
451 | | /* A1-FE + A1-FE */ |
452 | 0 | else |
453 | 0 | { |
454 | | /* Source buffer too small */ |
455 | 0 | if ( pSrcBuf + 1 == pEndSrcBuf ) |
456 | 0 | { |
457 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL; |
458 | 0 | break; |
459 | 0 | } |
460 | | |
461 | 0 | cLead = c; |
462 | 0 | pSrcBuf++; |
463 | 0 | cTrail = static_cast<unsigned char>(*pSrcBuf); |
464 | 0 | pLeadTab = pConvertData->mpJIS0208ToUniLeadTab; |
465 | 0 | } |
466 | | |
467 | | /* Undefined Range */ |
468 | 0 | if ( (cLead < JIS_EUC_LEAD_OFF) || (cTrail < JIS_EUC_TRAIL_OFF) ) |
469 | 0 | cConv = 0; |
470 | 0 | else |
471 | 0 | { |
472 | 0 | cLead -= JIS_EUC_LEAD_OFF; |
473 | 0 | cTrail -= JIS_EUC_TRAIL_OFF; |
474 | 0 | pLeadEntry = pLeadTab+cLead; |
475 | 0 | if ( (cTrail >= pLeadEntry->mnTrailStart) && (cTrail <= pLeadEntry->mnTrailEnd) ) |
476 | 0 | cConv = pLeadEntry->mpToUniTrailTab[cTrail-pLeadEntry->mnTrailStart]; |
477 | 0 | else |
478 | 0 | cConv = 0; |
479 | 0 | } |
480 | 0 | } |
481 | | |
482 | 0 | if ( !cConv ) |
483 | 0 | { |
484 | | /* We compare the full range of the trail we defined, */ |
485 | | /* which can often be greater than the limit. We do this */ |
486 | | /* so that extensions that don't consider encodings */ |
487 | | /* correctly treat double-byte characters as a single */ |
488 | | /* character as much as possible. */ |
489 | |
|
490 | 0 | if ( (cLead < JIS_EUC_LEAD_OFF) || (cTrail < JIS_EUC_TRAIL_OFF) ) |
491 | 0 | { |
492 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_INVALID; |
493 | 0 | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR ) |
494 | 0 | { |
495 | 0 | if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0) { |
496 | 0 | ++pSrcBuf; |
497 | 0 | } else { |
498 | 0 | pSrcBuf = startOfCurrentChar; |
499 | 0 | } |
500 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR; |
501 | 0 | break; |
502 | 0 | } |
503 | 0 | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_INVALID_MASK) == RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE ) |
504 | 0 | { |
505 | 0 | pSrcBuf++; |
506 | 0 | startOfCurrentChar = pSrcBuf; |
507 | 0 | continue; |
508 | 0 | } |
509 | 0 | cConv = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER; |
510 | 0 | } |
511 | 0 | else |
512 | 0 | { |
513 | 0 | if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0) { |
514 | 0 | ++pSrcBuf; |
515 | 0 | } else { |
516 | 0 | pSrcBuf = startOfCurrentChar; |
517 | 0 | } |
518 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_MBUNDEFINED; |
519 | 0 | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR ) |
520 | 0 | { |
521 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR; |
522 | 0 | break; |
523 | 0 | } |
524 | 0 | if ( (nFlags & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_MASK) == RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE ) |
525 | 0 | { |
526 | 0 | pSrcBuf++; |
527 | 0 | startOfCurrentChar = pSrcBuf; |
528 | 0 | continue; |
529 | 0 | } |
530 | 0 | cConv = RTL_TEXTENC_UNICODE_REPLACEMENT_CHARACTER; |
531 | 0 | } |
532 | 0 | } |
533 | 0 | } |
534 | | |
535 | 0 | if ( pDestBuf == pEndDestBuf ) |
536 | 0 | { |
537 | 0 | *pInfo |= RTL_TEXTTOUNICODE_INFO_ERROR | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL; |
538 | 0 | break; |
539 | 0 | } |
540 | | |
541 | 0 | *pDestBuf = cConv; |
542 | 0 | pDestBuf++; |
543 | 0 | pSrcBuf++; |
544 | 0 | startOfCurrentChar = pSrcBuf; |
545 | 0 | } |
546 | |
|
547 | 0 | *pSrcCvtBytes = nSrcBytes - (pEndSrcBuf-pSrcBuf); |
548 | 0 | return (nDestChars - (pEndDestBuf-pDestBuf)); |
549 | 0 | } |
550 | | |
551 | | sal_Size ImplUnicodeToEUCJP( const void* pData, |
552 | | SAL_UNUSED_PARAMETER void*, |
553 | | const sal_Unicode* pSrcBuf, sal_Size nSrcChars, |
554 | | char* pDestBuf, sal_Size nDestBytes, |
555 | | sal_uInt32 nFlags, sal_uInt32* pInfo, |
556 | | sal_Size* pSrcCvtChars ) |
557 | 0 | { |
558 | 0 | sal_uInt32 cConv; |
559 | 0 | sal_Unicode c; |
560 | 0 | unsigned char nHighChar; |
561 | 0 | unsigned char nLowChar; |
562 | 0 | const ImplUniToDBCSHighTab* pHighEntry; |
563 | 0 | const ImplUniToDBCSHighTab* pHighTab; |
564 | 0 | const ImplEUCJPConvertData* pConvertData = static_cast<const ImplEUCJPConvertData*>(pData); |
565 | 0 | char* pEndDestBuf; |
566 | 0 | const sal_Unicode* pEndSrcBuf; |
567 | |
|
568 | 0 | *pInfo = 0; |
569 | 0 | pEndDestBuf = pDestBuf+nDestBytes; |
570 | 0 | pEndSrcBuf = pSrcBuf+nSrcChars; |
571 | 0 | while ( pSrcBuf < pEndSrcBuf ) |
572 | 0 | { |
573 | 0 | c = *pSrcBuf; |
574 | | |
575 | | /* ASCII */ |
576 | 0 | if ( c <= 0x7F ) |
577 | 0 | cConv = c; |
578 | | /* Half-width katakana */ |
579 | 0 | else if ( (c >= 0xFF61) && (c <= 0xFF9F) ) |
580 | 0 | cConv = 0x8E00+0xA1+(c-0xFF61); |
581 | 0 | else |
582 | 0 | { |
583 | 0 | nHighChar = static_cast<unsigned char>((c >> 8) & 0xFF); |
584 | 0 | nLowChar = static_cast<unsigned char>(c & 0xFF); |
585 | | |
586 | | /* JIS 0208 */ |
587 | 0 | pHighTab = pConvertData->mpUniToJIS0208HighTab; |
588 | 0 | pHighEntry = pHighTab+nHighChar; |
589 | 0 | if ( (nLowChar >= pHighEntry->mnLowStart) && (nLowChar <= pHighEntry->mnLowEnd) ) |
590 | 0 | { |
591 | 0 | cConv = pHighEntry->mpToUniTrailTab[nLowChar-pHighEntry->mnLowStart]; |
592 | 0 | if (cConv != 0) |
593 | 0 | cConv |= 0x8080; |
594 | 0 | } |
595 | 0 | else |
596 | 0 | cConv = 0; |
597 | | |
598 | | /* JIS 0212 */ |
599 | 0 | if ( !cConv ) |
600 | 0 | { |
601 | 0 | pHighTab = pConvertData->mpUniToJIS0212HighTab; |
602 | 0 | pHighEntry = pHighTab+nHighChar; |
603 | 0 | if ( (nLowChar >= pHighEntry->mnLowStart) && (nLowChar <= pHighEntry->mnLowEnd) ) |
604 | 0 | { |
605 | 0 | cConv = pHighEntry->mpToUniTrailTab[nLowChar-pHighEntry->mnLowStart]; |
606 | 0 | if (cConv != 0) |
607 | 0 | cConv |= 0x8F8080; |
608 | 0 | } |
609 | |
|
610 | 0 | if ( !cConv ) |
611 | 0 | { |
612 | 0 | if ( nFlags & RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE ) |
613 | 0 | { |
614 | | /* !!! */ |
615 | 0 | } |
616 | |
|
617 | 0 | if ( nFlags & RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR ) |
618 | 0 | { |
619 | | /* !!! */ |
620 | 0 | } |
621 | | |
622 | | /* Handle undefined and surrogates characters */ |
623 | | /* (all surrogates characters are undefined) */ |
624 | 0 | if (sal::detail::textenc::handleUndefinedUnicodeToTextChar( |
625 | 0 | &pSrcBuf, pEndSrcBuf, &pDestBuf, pEndDestBuf, |
626 | 0 | nFlags, pInfo)) |
627 | 0 | continue; |
628 | 0 | break; |
629 | 0 | } |
630 | 0 | } |
631 | 0 | } |
632 | | |
633 | | /* SingleByte */ |
634 | 0 | if ( !(cConv & 0xFFFF00) ) |
635 | 0 | { |
636 | 0 | if ( pDestBuf == pEndDestBuf ) |
637 | 0 | { |
638 | 0 | *pInfo |= RTL_UNICODETOTEXT_INFO_ERROR | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL; |
639 | 0 | break; |
640 | 0 | } |
641 | | |
642 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >(cConv & 0xFF)); |
643 | 0 | pDestBuf++; |
644 | 0 | } |
645 | | /* DoubleByte */ |
646 | 0 | else if ( !(cConv & 0xFF0000) ) |
647 | 0 | { |
648 | 0 | if ( pDestBuf+1 >= pEndDestBuf ) |
649 | 0 | { |
650 | 0 | *pInfo |= RTL_UNICODETOTEXT_INFO_ERROR | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL; |
651 | 0 | break; |
652 | 0 | } |
653 | | |
654 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >((cConv >> 8) & 0xFF)); |
655 | 0 | pDestBuf++; |
656 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >(cConv & 0xFF)); |
657 | 0 | pDestBuf++; |
658 | 0 | } |
659 | 0 | else |
660 | 0 | { |
661 | 0 | if ( pDestBuf+2 >= pEndDestBuf ) |
662 | 0 | { |
663 | 0 | *pInfo |= RTL_UNICODETOTEXT_INFO_ERROR | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL; |
664 | 0 | break; |
665 | 0 | } |
666 | | |
667 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >((cConv >> 16) & 0xFF)); |
668 | 0 | pDestBuf++; |
669 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >((cConv >> 8) & 0xFF)); |
670 | 0 | pDestBuf++; |
671 | 0 | *pDestBuf = static_cast< char >(static_cast< unsigned char >(cConv & 0xFF)); |
672 | 0 | pDestBuf++; |
673 | 0 | } |
674 | | |
675 | 0 | pSrcBuf++; |
676 | 0 | } |
677 | |
|
678 | 0 | *pSrcCvtChars = nSrcChars - (pEndSrcBuf-pSrcBuf); |
679 | 0 | return (nDestBytes - (pEndDestBuf-pDestBuf)); |
680 | 0 | } |
681 | | |
682 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |