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 "rtl/textcvt.h"
23 : #include "sal/types.h"
24 :
25 : #include "context.hxx"
26 : #include "converter.hxx"
27 : #include "converteuctw.hxx"
28 : #include "tenchelp.hxx"
29 : #include "unichars.hxx"
30 :
31 : namespace {
32 :
33 : enum ImplEucTwToUnicodeState
34 : {
35 : IMPL_EUC_TW_TO_UNICODE_STATE_0,
36 : IMPL_EUC_TW_TO_UNICODE_STATE_1,
37 : IMPL_EUC_TW_TO_UNICODE_STATE_2_1,
38 : IMPL_EUC_TW_TO_UNICODE_STATE_2_2,
39 : IMPL_EUC_TW_TO_UNICODE_STATE_2_3
40 : };
41 :
42 : struct ImplEucTwToUnicodeContext
43 : {
44 : ImplEucTwToUnicodeState m_eState;
45 : sal_Int32 m_nPlane; // 0--15
46 : sal_Int32 m_nRow; // 0--93
47 : };
48 :
49 : }
50 :
51 4 : void * ImplCreateEucTwToUnicodeContext()
52 : {
53 4 : ImplEucTwToUnicodeContext * pContext = new ImplEucTwToUnicodeContext;
54 4 : pContext->m_eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
55 4 : return pContext;
56 : }
57 :
58 0 : void ImplResetEucTwToUnicodeContext(void * pContext)
59 : {
60 0 : if (pContext)
61 : static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_eState
62 0 : = IMPL_EUC_TW_TO_UNICODE_STATE_0;
63 0 : }
64 :
65 4 : void ImplDestroyEucTwToUnicodeContext(void * pContext)
66 : {
67 4 : delete static_cast< ImplEucTwToUnicodeContext * >(pContext);
68 4 : }
69 :
70 56 : sal_Size ImplConvertEucTwToUnicode(void const * pData,
71 : void * pContext,
72 : char const * pSrcBuf,
73 : sal_Size nSrcBytes,
74 : sal_Unicode * pDestBuf,
75 : sal_Size nDestChars,
76 : sal_uInt32 nFlags,
77 : sal_uInt32 * pInfo,
78 : sal_Size * pSrcCvtBytes)
79 : {
80 : sal_uInt16 const * pCns116431992Data
81 : = static_cast< ImplEucTwConverterData const * >(pData)->
82 56 : m_pCns116431992ToUnicodeData;
83 : sal_Int32 const * pCns116431992RowOffsets
84 : = static_cast< ImplEucTwConverterData const * >(pData)->
85 56 : m_pCns116431992ToUnicodeRowOffsets;
86 : sal_Int32 const * pCns116431992PlaneOffsets
87 : = static_cast< ImplEucTwConverterData const * >(pData)->
88 56 : m_pCns116431992ToUnicodePlaneOffsets;
89 56 : ImplEucTwToUnicodeState eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
90 56 : sal_Int32 nPlane = 0;
91 56 : sal_Int32 nRow = 0;
92 56 : sal_uInt32 nInfo = 0;
93 56 : sal_Size nConverted = 0;
94 56 : sal_Unicode * pDestBufPtr = pDestBuf;
95 56 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
96 :
97 56 : if (pContext)
98 : {
99 30 : eState = static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_eState;
100 30 : nPlane = static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_nPlane;
101 30 : nRow = static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_nRow;
102 : }
103 :
104 148 : for (; nConverted < nSrcBytes; ++nConverted)
105 : {
106 92 : bool bUndefined = true;
107 92 : sal_uInt32 nChar = *(unsigned char const *) pSrcBuf++;
108 92 : switch (eState)
109 : {
110 : case IMPL_EUC_TW_TO_UNICODE_STATE_0:
111 62 : if (nChar < 0x80)
112 42 : if (pDestBufPtr != pDestBufEnd)
113 42 : *pDestBufPtr++ = (sal_Unicode) nChar;
114 : else
115 0 : goto no_output;
116 20 : else if (nChar >= 0xA1 && nChar <= 0xFE)
117 : {
118 8 : nRow = nChar - 0xA1;
119 8 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_1;
120 : }
121 12 : else if (nChar == 0x8E)
122 12 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_2_1;
123 : else
124 : {
125 0 : bUndefined = false;
126 0 : goto bad_input;
127 : }
128 62 : break;
129 :
130 : case IMPL_EUC_TW_TO_UNICODE_STATE_1:
131 6 : if (nChar >= 0xA1 && nChar <= 0xFE)
132 : {
133 6 : nPlane = 0;
134 6 : goto transform;
135 : }
136 : else
137 : {
138 0 : bUndefined = false;
139 0 : goto bad_input;
140 : }
141 : break;
142 :
143 : case IMPL_EUC_TW_TO_UNICODE_STATE_2_1:
144 10 : if (nChar >= 0xA1 && nChar <= 0xB0)
145 : {
146 10 : nPlane = nChar - 0xA1;
147 10 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_2_2;
148 : }
149 : else
150 : {
151 0 : bUndefined = false;
152 0 : goto bad_input;
153 : }
154 10 : break;
155 :
156 : case IMPL_EUC_TW_TO_UNICODE_STATE_2_2:
157 8 : if (nChar >= 0xA1 && nChar <= 0xFE)
158 : {
159 8 : nRow = nChar - 0xA1;
160 8 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_2_3;
161 : }
162 : else
163 : {
164 0 : bUndefined = false;
165 0 : goto bad_input;
166 : }
167 8 : break;
168 :
169 : case IMPL_EUC_TW_TO_UNICODE_STATE_2_3:
170 6 : if (nChar >= 0xA1 && nChar <= 0xFE)
171 : goto transform;
172 : else
173 : {
174 0 : bUndefined = false;
175 0 : goto bad_input;
176 : }
177 : break;
178 : }
179 80 : continue;
180 :
181 : transform:
182 : {
183 12 : sal_Int32 nPlaneOffset = pCns116431992PlaneOffsets[nPlane];
184 12 : if (nPlaneOffset == -1)
185 0 : goto bad_input;
186 : else
187 : {
188 : sal_Int32 nOffset
189 12 : = pCns116431992RowOffsets[nPlaneOffset + nRow];
190 12 : if (nOffset == -1)
191 0 : goto bad_input;
192 : else
193 : {
194 12 : sal_uInt32 nFirstLast = pCns116431992Data[nOffset++];
195 12 : sal_uInt32 nFirst = nFirstLast & 0xFF;
196 12 : sal_uInt32 nLast = nFirstLast >> 8;
197 12 : nChar -= 0xA0;
198 12 : if (nChar >= nFirst && nChar <= nLast)
199 : {
200 : sal_uInt32 nUnicode
201 12 : = pCns116431992Data[nOffset + (nChar - nFirst)];
202 12 : if (nUnicode == 0xFFFF)
203 0 : goto bad_input;
204 12 : else if (ImplIsHighSurrogate(nUnicode))
205 6 : if (pDestBufEnd - pDestBufPtr >= 2)
206 : {
207 6 : nOffset += nLast - nFirst + 1;
208 6 : nFirst = pCns116431992Data[nOffset++];
209 6 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
210 : *pDestBufPtr++
211 : = (sal_Unicode)
212 : pCns116431992Data[
213 6 : nOffset + (nChar - nFirst)];
214 : }
215 : else
216 0 : goto no_output;
217 : else
218 6 : if (pDestBufPtr != pDestBufEnd)
219 6 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
220 : else
221 0 : goto no_output;
222 : }
223 : else
224 : goto bad_input;
225 12 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
226 : }
227 : }
228 12 : continue;
229 : }
230 :
231 : bad_input:
232 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
233 : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
234 0 : &nInfo))
235 : {
236 : case sal::detail::textenc::BAD_INPUT_STOP:
237 0 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
238 0 : break;
239 :
240 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
241 0 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
242 0 : continue;
243 :
244 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
245 0 : goto no_output;
246 : }
247 0 : break;
248 :
249 : no_output:
250 0 : --pSrcBuf;
251 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
252 0 : break;
253 : }
254 :
255 56 : if (eState != IMPL_EUC_TW_TO_UNICODE_STATE_0
256 16 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
257 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
258 : == 0)
259 : {
260 16 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
261 16 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
262 : else
263 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
264 : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
265 0 : &nInfo))
266 : {
267 : case sal::detail::textenc::BAD_INPUT_STOP:
268 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
269 0 : eState = IMPL_EUC_TW_TO_UNICODE_STATE_0;
270 0 : break;
271 :
272 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
273 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
274 0 : break;
275 : }
276 : }
277 :
278 56 : if (pContext)
279 : {
280 30 : static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_eState = eState;
281 30 : static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_nPlane = nPlane;
282 30 : static_cast< ImplEucTwToUnicodeContext * >(pContext)->m_nRow = nRow;
283 : }
284 56 : if (pInfo)
285 56 : *pInfo = nInfo;
286 56 : if (pSrcCvtBytes)
287 56 : *pSrcCvtBytes = nConverted;
288 :
289 56 : return pDestBufPtr - pDestBuf;
290 : }
291 :
292 2 : sal_Size ImplConvertUnicodeToEucTw(void const * pData,
293 : void * pContext,
294 : sal_Unicode const * pSrcBuf,
295 : sal_Size nSrcChars,
296 : char * pDestBuf,
297 : sal_Size nDestBytes,
298 : sal_uInt32 nFlags,
299 : sal_uInt32 * pInfo,
300 : sal_Size * pSrcCvtChars)
301 : {
302 : sal_uInt8 const * pCns116431992Data
303 : = static_cast< ImplEucTwConverterData const * >(pData)->
304 2 : m_pUnicodeToCns116431992Data;
305 : sal_Int32 const * pCns116431992PageOffsets
306 : = static_cast< ImplEucTwConverterData const * >(pData)->
307 2 : m_pUnicodeToCns116431992PageOffsets;
308 : sal_Int32 const * pCns116431992PlaneOffsets
309 : = static_cast< ImplEucTwConverterData const * >(pData)->
310 2 : m_pUnicodeToCns116431992PlaneOffsets;
311 2 : sal_Unicode nHighSurrogate = 0;
312 2 : sal_uInt32 nInfo = 0;
313 2 : sal_Size nConverted = 0;
314 2 : char * pDestBufPtr = pDestBuf;
315 2 : char * pDestBufEnd = pDestBuf + nDestBytes;
316 :
317 2 : if (pContext)
318 : nHighSurrogate
319 2 : = ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate;
320 :
321 22 : for (; nConverted < nSrcChars; ++nConverted)
322 : {
323 20 : bool bUndefined = true;
324 20 : sal_uInt32 nChar = *pSrcBuf++;
325 20 : if (nHighSurrogate == 0)
326 : {
327 18 : if (ImplIsHighSurrogate(nChar))
328 : {
329 2 : nHighSurrogate = (sal_Unicode) nChar;
330 2 : continue;
331 : }
332 : }
333 2 : else if (ImplIsLowSurrogate(nChar))
334 2 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
335 : else
336 : {
337 0 : bUndefined = false;
338 0 : goto bad_input;
339 : }
340 :
341 18 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
342 : {
343 0 : bUndefined = false;
344 0 : goto bad_input;
345 : }
346 :
347 18 : if (nChar < 0x80)
348 14 : if (pDestBufPtr != pDestBufEnd)
349 14 : *pDestBufPtr++ = static_cast< char >(nChar);
350 : else
351 0 : goto no_output;
352 : else
353 : {
354 4 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
355 : sal_uInt32 nFirst;
356 : sal_uInt32 nLast;
357 : sal_uInt32 nPlane;
358 4 : if (nOffset == -1)
359 0 : goto bad_input;
360 : nOffset
361 4 : = pCns116431992PageOffsets[nOffset + ((nChar & 0xFF00) >> 8)];
362 4 : if (nOffset == -1)
363 0 : goto bad_input;
364 4 : nFirst = pCns116431992Data[nOffset++];
365 4 : nLast = pCns116431992Data[nOffset++];
366 4 : nChar &= 0xFF;
367 4 : if (nChar < nFirst || nChar > nLast)
368 : goto bad_input;
369 4 : nOffset += 3 * (nChar - nFirst);
370 4 : nPlane = pCns116431992Data[nOffset++];
371 4 : if (nPlane == 0)
372 0 : goto bad_input;
373 4 : if (pDestBufEnd - pDestBufPtr < (nPlane == 1 ? 2 : 4))
374 0 : goto no_output;
375 4 : if (nPlane != 1)
376 : {
377 2 : *pDestBufPtr++ = static_cast< char >(static_cast< unsigned char >(0x8E));
378 2 : *pDestBufPtr++ = static_cast< char >(0xA0 + nPlane);
379 : }
380 4 : *pDestBufPtr++ = static_cast< char >(0xA0 + pCns116431992Data[nOffset++]);
381 4 : *pDestBufPtr++ = static_cast< char >(0xA0 + pCns116431992Data[nOffset]);
382 : }
383 18 : nHighSurrogate = 0;
384 18 : continue;
385 :
386 : bad_input:
387 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
388 : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
389 0 : &nInfo, NULL, 0, NULL))
390 : {
391 : case sal::detail::textenc::BAD_INPUT_STOP:
392 0 : nHighSurrogate = 0;
393 0 : break;
394 :
395 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
396 0 : nHighSurrogate = 0;
397 0 : continue;
398 :
399 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
400 0 : goto no_output;
401 : }
402 0 : break;
403 :
404 : no_output:
405 0 : --pSrcBuf;
406 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
407 0 : break;
408 : }
409 :
410 2 : if (nHighSurrogate != 0
411 0 : && (nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
412 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
413 : == 0)
414 : {
415 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
416 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
417 : else
418 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
419 : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
420 0 : NULL, 0, NULL))
421 : {
422 : case sal::detail::textenc::BAD_INPUT_STOP:
423 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
424 0 : nHighSurrogate = 0;
425 0 : break;
426 :
427 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
428 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
429 0 : break;
430 : }
431 : }
432 :
433 2 : if (pContext)
434 : ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate
435 2 : = nHighSurrogate;
436 2 : if (pInfo)
437 2 : *pInfo = nInfo;
438 2 : if (pSrcCvtChars)
439 2 : *pSrcCvtChars = nConverted;
440 :
441 2 : return pDestBufPtr - pDestBuf;
442 : }
443 :
444 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|