Line data Source code
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 <cassert>
23 :
24 : #include "rtl/textcvt.h"
25 : #include "sal/types.h"
26 :
27 : #include "context.hxx"
28 : #include "convertbig5hkscs.hxx"
29 : #include "converter.hxx"
30 : #include "tenchelp.hxx"
31 : #include "unichars.hxx"
32 :
33 : namespace {
34 :
35 : struct ImplBig5HkscsToUnicodeContext
36 : {
37 : sal_Int32 m_nRow; // 0--255; 0 means none
38 : };
39 :
40 : }
41 :
42 0 : void * ImplCreateBig5HkscsToUnicodeContext()
43 : {
44 : ImplBig5HkscsToUnicodeContext * pContext =
45 0 : new ImplBig5HkscsToUnicodeContext;
46 0 : pContext->m_nRow = 0;
47 0 : return pContext;
48 : }
49 :
50 0 : void ImplResetBig5HkscsToUnicodeContext(void * pContext)
51 : {
52 0 : if (pContext)
53 0 : static_cast< ImplBig5HkscsToUnicodeContext * >(pContext)->m_nRow = 0;
54 0 : }
55 :
56 0 : void ImplDestroyBig5HkscsToUnicodeContext(void * pContext)
57 : {
58 0 : delete static_cast< ImplBig5HkscsToUnicodeContext * >(pContext);
59 0 : }
60 :
61 0 : sal_Size ImplConvertBig5HkscsToUnicode(void const * pData,
62 : void * pContext,
63 : char const * pSrcBuf,
64 : sal_Size nSrcBytes,
65 : sal_Unicode * pDestBuf,
66 : sal_Size nDestChars,
67 : sal_uInt32 nFlags,
68 : sal_uInt32 * pInfo,
69 : sal_Size * pSrcCvtBytes)
70 : {
71 : sal_uInt16 const * pBig5Hkscs2001Data
72 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
73 0 : m_pBig5Hkscs2001ToUnicodeData;
74 : sal_Int32 const * pBig5Hkscs2001RowOffsets
75 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
76 0 : m_pBig5Hkscs2001ToUnicodeRowOffsets;
77 : ImplDBCSToUniLeadTab const * pBig5Data
78 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
79 0 : m_pBig5ToUnicodeData;
80 0 : sal_Int32 nRow = 0;
81 0 : sal_uInt32 nInfo = 0;
82 0 : sal_Size nConverted = 0;
83 0 : sal_Unicode * pDestBufPtr = pDestBuf;
84 0 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
85 :
86 0 : if (pContext)
87 0 : nRow = static_cast< ImplBig5HkscsToUnicodeContext * >(pContext)->m_nRow;
88 :
89 0 : for (; nConverted < nSrcBytes; ++nConverted)
90 : {
91 0 : bool bUndefined = true;
92 0 : sal_uInt32 nChar = *(unsigned char const *) pSrcBuf++;
93 0 : if (nRow == 0)
94 0 : if (nChar < 0x80)
95 0 : if (pDestBufPtr != pDestBufEnd)
96 0 : *pDestBufPtr++ = (sal_Unicode) nChar;
97 : else
98 0 : goto no_output;
99 0 : else if (nChar >= 0x81 && nChar <= 0xFE)
100 0 : nRow = nChar;
101 : else
102 : {
103 0 : bUndefined = false;
104 0 : goto bad_input;
105 : }
106 : else
107 0 : if ((nChar >= 0x40 && nChar <= 0x7E)
108 0 : || (nChar >= 0xA1 && nChar <= 0xFE))
109 : {
110 0 : sal_uInt32 nUnicode = 0xFFFF;
111 0 : sal_Int32 nOffset = pBig5Hkscs2001RowOffsets[nRow];
112 0 : sal_uInt32 nFirst=0;
113 0 : sal_uInt32 nLast=0;
114 0 : if (nOffset != -1)
115 : {
116 0 : sal_uInt32 nFirstLast = pBig5Hkscs2001Data[nOffset++];
117 0 : nFirst = nFirstLast & 0xFF;
118 0 : nLast = nFirstLast >> 8;
119 0 : if (nChar >= nFirst && nChar <= nLast)
120 : nUnicode
121 0 : = pBig5Hkscs2001Data[nOffset + (nChar - nFirst)];
122 : }
123 0 : if (nUnicode == 0xFFFF)
124 : {
125 0 : sal_uInt32 n = pBig5Data[nRow].mnTrailStart;
126 0 : if (nChar >= n && nChar <= pBig5Data[nRow].mnTrailEnd)
127 : {
128 0 : nUnicode = pBig5Data[nRow].mpToUniTrailTab[nChar - n];
129 0 : if (nUnicode == 0)
130 0 : nUnicode = 0xFFFF;
131 : assert(!ImplIsHighSurrogate(nUnicode));
132 : }
133 : }
134 0 : if (nUnicode == 0xFFFF)
135 : {
136 : ImplDBCSEUDCData const * p
137 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
138 0 : m_pEudcData;
139 : sal_uInt32 nCount
140 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
141 0 : m_nEudcCount;
142 : sal_uInt32 i;
143 0 : for (i = 0; i < nCount; ++i)
144 : {
145 0 : if (nRow >= p->mnLeadStart && nRow <= p->mnLeadEnd)
146 : {
147 0 : if (nChar < p->mnTrail1Start)
148 0 : break;
149 0 : if (nChar <= p->mnTrail1End)
150 : {
151 : nUnicode
152 : = p->mnUniStart
153 0 : + (nRow - p->mnLeadStart)
154 0 : * p->mnTrailRangeCount
155 0 : + (nChar - p->mnTrail1Start);
156 0 : break;
157 : }
158 0 : if (p->mnTrailCount < 2
159 0 : || nChar < p->mnTrail2Start)
160 : break;
161 0 : if (nChar <= p->mnTrail2End)
162 : {
163 : nUnicode
164 : = p->mnUniStart
165 0 : + (nRow - p->mnLeadStart)
166 0 : * p->mnTrailRangeCount
167 0 : + (nChar - p->mnTrail2Start)
168 0 : + (p->mnTrail1End - p->mnTrail1Start
169 0 : + 1);
170 0 : break;
171 : }
172 0 : if (p->mnTrailCount < 3
173 0 : || nChar < p->mnTrail3Start)
174 : break;
175 0 : if (nChar <= p->mnTrail3End)
176 : {
177 : nUnicode
178 : = p->mnUniStart
179 0 : + (nRow - p->mnLeadStart)
180 0 : * p->mnTrailRangeCount
181 0 : + (nChar - p->mnTrail3Start)
182 0 : + (p->mnTrail1End - p->mnTrail1Start
183 : + 1)
184 0 : + (p->mnTrail2End - p->mnTrail2Start
185 0 : + 1);
186 0 : break;
187 : }
188 0 : break;
189 : }
190 0 : ++p;
191 : }
192 : assert(!ImplIsHighSurrogate(nUnicode));
193 : }
194 0 : if (nUnicode == 0xFFFF)
195 0 : goto bad_input;
196 0 : if (ImplIsHighSurrogate(nUnicode))
197 0 : if (pDestBufEnd - pDestBufPtr >= 2)
198 : {
199 0 : nOffset += nLast - nFirst + 1;
200 0 : nFirst = pBig5Hkscs2001Data[nOffset++];
201 0 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
202 : *pDestBufPtr++
203 : = (sal_Unicode) pBig5Hkscs2001Data[
204 0 : nOffset + (nChar - nFirst)];
205 : }
206 : else
207 0 : goto no_output;
208 : else
209 0 : if (pDestBufPtr != pDestBufEnd)
210 0 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
211 : else
212 0 : goto no_output;
213 0 : nRow = 0;
214 : }
215 : else
216 : {
217 0 : bUndefined = false;
218 0 : goto bad_input;
219 : }
220 0 : continue;
221 :
222 : bad_input:
223 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
224 : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
225 0 : &nInfo))
226 : {
227 : case sal::detail::textenc::BAD_INPUT_STOP:
228 0 : nRow = 0;
229 0 : break;
230 :
231 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
232 0 : nRow = 0;
233 0 : continue;
234 :
235 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
236 0 : goto no_output;
237 : }
238 0 : break;
239 :
240 : no_output:
241 0 : --pSrcBuf;
242 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
243 0 : break;
244 : }
245 :
246 0 : if (nRow != 0
247 0 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
248 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
249 : == 0)
250 : {
251 0 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
252 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
253 : else
254 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
255 : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
256 0 : &nInfo))
257 : {
258 : case sal::detail::textenc::BAD_INPUT_STOP:
259 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
260 0 : nRow = 0;
261 0 : break;
262 :
263 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
264 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
265 0 : break;
266 : }
267 : }
268 :
269 0 : if (pContext)
270 0 : static_cast< ImplBig5HkscsToUnicodeContext * >(pContext)->m_nRow = nRow;
271 0 : if (pInfo)
272 0 : *pInfo = nInfo;
273 0 : if (pSrcCvtBytes)
274 0 : *pSrcCvtBytes = nConverted;
275 :
276 0 : return pDestBufPtr - pDestBuf;
277 : }
278 :
279 0 : sal_Size ImplConvertUnicodeToBig5Hkscs(void const * pData,
280 : void * pContext,
281 : sal_Unicode const * pSrcBuf,
282 : sal_Size nSrcChars,
283 : char * pDestBuf,
284 : sal_Size nDestBytes,
285 : sal_uInt32 nFlags,
286 : sal_uInt32 * pInfo,
287 : sal_Size * pSrcCvtChars)
288 : {
289 : sal_uInt16 const * pBig5Hkscs2001Data
290 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
291 0 : m_pUnicodeToBig5Hkscs2001Data;
292 : sal_Int32 const * pBig5Hkscs2001PageOffsets
293 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
294 0 : m_pUnicodeToBig5Hkscs2001PageOffsets;
295 : sal_Int32 const * pBig5Hkscs2001PlaneOffsets
296 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
297 0 : m_pUnicodeToBig5Hkscs2001PlaneOffsets;
298 : ImplUniToDBCSHighTab const * pBig5Data
299 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
300 0 : m_pUnicodeToBig5Data;
301 0 : sal_Unicode nHighSurrogate = 0;
302 0 : sal_uInt32 nInfo = 0;
303 0 : sal_Size nConverted = 0;
304 0 : char * pDestBufPtr = pDestBuf;
305 0 : char * pDestBufEnd = pDestBuf + nDestBytes;
306 :
307 0 : if (pContext)
308 : nHighSurrogate
309 0 : = ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate;
310 :
311 0 : for (; nConverted < nSrcChars; ++nConverted)
312 : {
313 0 : bool bUndefined = true;
314 0 : sal_uInt32 nChar = *pSrcBuf++;
315 0 : if (nHighSurrogate == 0)
316 : {
317 0 : if (ImplIsHighSurrogate(nChar))
318 : {
319 0 : nHighSurrogate = (sal_Unicode) nChar;
320 0 : continue;
321 : }
322 : }
323 0 : else if (ImplIsLowSurrogate(nChar))
324 0 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
325 : else
326 : {
327 0 : bUndefined = false;
328 0 : goto bad_input;
329 : }
330 :
331 0 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
332 : {
333 0 : bUndefined = false;
334 0 : goto bad_input;
335 : }
336 :
337 0 : if (nChar < 0x80)
338 0 : if (pDestBufPtr != pDestBufEnd)
339 0 : *pDestBufPtr++ = static_cast< char >(nChar);
340 : else
341 0 : goto no_output;
342 : else
343 : {
344 0 : sal_uInt32 nBytes = 0;
345 0 : sal_Int32 nOffset = pBig5Hkscs2001PlaneOffsets[nChar >> 16];
346 0 : if (nOffset != -1)
347 : {
348 : nOffset
349 0 : = pBig5Hkscs2001PageOffsets[nOffset + ((nChar & 0xFF00)
350 0 : >> 8)];
351 0 : if (nOffset != -1)
352 : {
353 0 : sal_uInt32 nFirstLast = pBig5Hkscs2001Data[nOffset++];
354 0 : sal_uInt32 nFirst = nFirstLast & 0xFF;
355 0 : sal_uInt32 nLast = nFirstLast >> 8;
356 0 : sal_uInt32 nIndex = nChar & 0xFF;
357 0 : if (nIndex >= nFirst && nIndex <= nLast)
358 : {
359 : nBytes
360 0 : = pBig5Hkscs2001Data[nOffset + (nIndex - nFirst)];
361 : }
362 : }
363 : }
364 0 : if (nBytes == 0)
365 : {
366 0 : sal_uInt32 nIndex1 = nChar >> 8;
367 0 : if (nIndex1 < 0x100)
368 : {
369 0 : sal_uInt32 nIndex2 = nChar & 0xFF;
370 0 : sal_uInt32 nFirst = pBig5Data[nIndex1].mnLowStart;
371 0 : if (nIndex2 >= nFirst
372 0 : && nIndex2 <= pBig5Data[nIndex1].mnLowEnd)
373 0 : nBytes = pBig5Data[nIndex1].
374 0 : mpToUniTrailTab[nIndex2 - nFirst];
375 : }
376 : }
377 0 : if (nBytes == 0)
378 : {
379 : ImplDBCSEUDCData const * p
380 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
381 0 : m_pEudcData;
382 : sal_uInt32 nCount
383 : = static_cast< ImplBig5HkscsConverterData const * >(pData)->
384 0 : m_nEudcCount;
385 : sal_uInt32 i;
386 0 : for (i = 0; i < nCount; ++i) {
387 0 : if (nChar >= p->mnUniStart && nChar <= p->mnUniEnd)
388 : {
389 0 : sal_uInt32 nIndex = nChar - p->mnUniStart;
390 0 : sal_uInt32 nLeadOff = nIndex / p->mnTrailRangeCount;
391 0 : sal_uInt32 nTrailOff = nIndex % p->mnTrailRangeCount;
392 : sal_uInt32 nSize;
393 0 : nBytes = (p->mnLeadStart + nLeadOff) << 8;
394 0 : nSize = p->mnTrail1End - p->mnTrail1Start + 1;
395 0 : if (nTrailOff < nSize)
396 : {
397 0 : nBytes |= p->mnTrail1Start + nTrailOff;
398 0 : break;
399 : }
400 0 : nTrailOff -= nSize;
401 0 : nSize = p->mnTrail2End - p->mnTrail2Start + 1;
402 0 : if (nTrailOff < nSize)
403 : {
404 0 : nBytes |= p->mnTrail2Start + nTrailOff;
405 0 : break;
406 : }
407 0 : nTrailOff -= nSize;
408 0 : nBytes |= p->mnTrail3Start + nTrailOff;
409 0 : break;
410 : }
411 0 : ++p;
412 : }
413 : }
414 0 : if (nBytes == 0)
415 0 : goto bad_input;
416 0 : if (pDestBufEnd - pDestBufPtr >= 2)
417 : {
418 0 : *pDestBufPtr++ = static_cast< char >(nBytes >> 8);
419 0 : *pDestBufPtr++ = static_cast< char >(nBytes & 0xFF);
420 : }
421 : else
422 0 : goto no_output;
423 : }
424 0 : nHighSurrogate = 0;
425 0 : continue;
426 :
427 : bad_input:
428 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
429 : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
430 0 : &nInfo, NULL, 0, NULL))
431 : {
432 : case sal::detail::textenc::BAD_INPUT_STOP:
433 0 : nHighSurrogate = 0;
434 0 : break;
435 :
436 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
437 0 : nHighSurrogate = 0;
438 0 : continue;
439 :
440 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
441 0 : goto no_output;
442 : }
443 0 : break;
444 :
445 : no_output:
446 0 : --pSrcBuf;
447 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
448 0 : break;
449 : }
450 :
451 0 : if (nHighSurrogate != 0
452 0 : && (nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
453 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
454 : == 0)
455 : {
456 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
457 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
458 : else
459 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
460 : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
461 0 : NULL, 0, NULL))
462 : {
463 : case sal::detail::textenc::BAD_INPUT_STOP:
464 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
465 0 : nHighSurrogate = 0;
466 0 : break;
467 :
468 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
469 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
470 0 : break;
471 : }
472 : }
473 :
474 0 : if (pContext)
475 : ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate
476 0 : = nHighSurrogate;
477 0 : if (pInfo)
478 0 : *pInfo = nInfo;
479 0 : if (pSrcCvtChars)
480 0 : *pSrcCvtChars = nConverted;
481 :
482 0 : return pDestBufPtr - pDestBuf;
483 : }
484 :
485 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|