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 "converter.hxx"
26 : #include "convertiso2022kr.hxx"
27 : #include "tenchelp.hxx"
28 : #include "unichars.hxx"
29 :
30 : namespace {
31 :
32 : enum ImplIso2022KrToUnicodeState // order is important:
33 : {
34 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII,
35 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001,
36 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001_2,
37 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC,
38 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR,
39 : IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN
40 : };
41 :
42 : struct ImplIso2022KrToUnicodeContext
43 : {
44 : ImplIso2022KrToUnicodeState m_eState;
45 : sal_uInt32 m_nRow;
46 : };
47 :
48 : enum ImplUnicodeToIso2022KrSet
49 : {
50 : IMPL_UNICODE_TO_ISO_2022_KR_SET_NONE,
51 : IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII,
52 : IMPL_UNICODE_TO_ISO_2022_KR_SET_1001
53 : };
54 :
55 : struct ImplUnicodeToIso2022KrContext
56 : {
57 : sal_Unicode m_nHighSurrogate;
58 : ImplUnicodeToIso2022KrSet m_eSet;
59 : };
60 :
61 : }
62 :
63 4 : void * ImplCreateIso2022KrToUnicodeContext()
64 : {
65 : ImplIso2022KrToUnicodeContext * pContext =
66 4 : new ImplIso2022KrToUnicodeContext;
67 4 : pContext->m_eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
68 4 : return pContext;
69 : }
70 :
71 0 : void ImplResetIso2022KrToUnicodeContext(void * pContext)
72 : {
73 0 : if (pContext)
74 : static_cast< ImplIso2022KrToUnicodeContext * >(pContext)->m_eState
75 0 : = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
76 0 : }
77 :
78 4 : void ImplDestroyIso2022KrToUnicodeContext(void * pContext)
79 : {
80 4 : delete static_cast< ImplIso2022KrToUnicodeContext * >(pContext);
81 4 : }
82 :
83 31 : sal_Size ImplConvertIso2022KrToUnicode(void const * pData,
84 : void * pContext,
85 : char const * pSrcBuf,
86 : sal_Size nSrcBytes,
87 : sal_Unicode * pDestBuf,
88 : sal_Size nDestChars,
89 : sal_uInt32 nFlags,
90 : sal_uInt32 * pInfo,
91 : sal_Size * pSrcCvtBytes)
92 : {
93 : ImplDBCSToUniLeadTab const * pKsX1001Data
94 : = static_cast< ImplIso2022KrConverterData const * >(pData)->
95 31 : m_pKsX1001ToUnicodeData;
96 : ImplIso2022KrToUnicodeState eState
97 31 : = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
98 31 : sal_uInt32 nRow = 0;
99 31 : sal_uInt32 nInfo = 0;
100 31 : sal_Size nConverted = 0;
101 31 : sal_Unicode * pDestBufPtr = pDestBuf;
102 31 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
103 :
104 31 : if (pContext)
105 : {
106 31 : eState = static_cast< ImplIso2022KrToUnicodeContext * >(pContext)->m_eState;
107 31 : nRow = static_cast< ImplIso2022KrToUnicodeContext * >(pContext)->m_nRow;
108 : }
109 :
110 85 : for (; nConverted < nSrcBytes; ++nConverted)
111 : {
112 54 : bool bUndefined = true;
113 54 : sal_uInt32 nChar = *reinterpret_cast<unsigned char const *>(pSrcBuf++);
114 54 : switch (eState)
115 : {
116 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII:
117 30 : if (nChar == 0x0E) // SO
118 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001;
119 26 : else if (nChar == 0x1B) // ESC
120 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC;
121 22 : else if (nChar < 0x80)
122 22 : if (pDestBufPtr != pDestBufEnd)
123 22 : *pDestBufPtr++ = (sal_Unicode) nChar;
124 : else
125 0 : goto no_output;
126 : else
127 : {
128 0 : bUndefined = false;
129 0 : goto bad_input;
130 : }
131 30 : break;
132 :
133 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001:
134 8 : if (nChar == 0x0F) // SI
135 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
136 4 : else if (nChar >= 0x21 && nChar <= 0x7E)
137 : {
138 4 : nRow = nChar + 0x80;
139 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001_2;
140 : }
141 : else
142 : {
143 0 : bUndefined = false;
144 0 : goto bad_input;
145 : }
146 8 : break;
147 :
148 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001_2:
149 4 : if (nChar >= 0x21 && nChar <= 0x7E)
150 : {
151 4 : sal_uInt16 nUnicode = 0;
152 4 : sal_uInt32 nFirst = pKsX1001Data[nRow].mnTrailStart;
153 4 : nChar += 0x80;
154 4 : if (nChar >= nFirst && nChar <= pKsX1001Data[nRow].mnTrailEnd)
155 4 : nUnicode = pKsX1001Data[nRow].
156 4 : mpToUniTrailTab[nChar - nFirst];
157 4 : if (nUnicode != 0)
158 4 : if (pDestBufPtr != pDestBufEnd)
159 : {
160 4 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
161 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001;
162 : }
163 : else
164 0 : goto no_output;
165 : else
166 0 : goto bad_input;
167 : }
168 : else
169 : {
170 0 : bUndefined = false;
171 0 : goto bad_input;
172 : }
173 4 : break;
174 :
175 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC:
176 4 : if (nChar == 0x24) // $
177 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR;
178 : else
179 : {
180 0 : bUndefined = false;
181 0 : goto bad_input;
182 : }
183 4 : break;
184 :
185 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR:
186 4 : if (nChar == 0x29) // )
187 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN;
188 : else
189 : {
190 0 : bUndefined = false;
191 0 : goto bad_input;
192 : }
193 4 : break;
194 :
195 : case IMPL_ISO_2022_KR_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN:
196 4 : if (nChar == 0x43) // C
197 4 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
198 : else
199 : {
200 0 : bUndefined = false;
201 0 : goto bad_input;
202 : }
203 4 : break;
204 : }
205 54 : continue;
206 :
207 : bad_input:
208 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
209 : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
210 0 : &nInfo))
211 : {
212 : case sal::detail::textenc::BAD_INPUT_STOP:
213 0 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
214 0 : break;
215 :
216 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
217 0 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
218 0 : continue;
219 :
220 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
221 0 : goto no_output;
222 : }
223 0 : break;
224 :
225 : no_output:
226 0 : --pSrcBuf;
227 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
228 0 : break;
229 : }
230 :
231 31 : if (eState > IMPL_ISO_2022_KR_TO_UNICODE_STATE_1001
232 8 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
233 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
234 : == 0)
235 : {
236 8 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
237 8 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
238 : else
239 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
240 : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
241 0 : &nInfo))
242 : {
243 : case sal::detail::textenc::BAD_INPUT_STOP:
244 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
245 0 : eState = IMPL_ISO_2022_KR_TO_UNICODE_STATE_ASCII;
246 0 : break;
247 :
248 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
249 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
250 0 : break;
251 : }
252 : }
253 :
254 31 : if (pContext)
255 : {
256 31 : static_cast< ImplIso2022KrToUnicodeContext * >(pContext)->m_eState = eState;
257 31 : static_cast< ImplIso2022KrToUnicodeContext * >(pContext)->m_nRow = nRow;
258 : }
259 31 : if (pInfo)
260 31 : *pInfo = nInfo;
261 31 : if (pSrcCvtBytes)
262 31 : *pSrcCvtBytes = nConverted;
263 :
264 31 : return pDestBufPtr - pDestBuf;
265 : }
266 :
267 2 : void * ImplCreateUnicodeToIso2022KrContext()
268 : {
269 : ImplUnicodeToIso2022KrContext * pContext =
270 2 : new ImplUnicodeToIso2022KrContext;
271 2 : pContext->m_nHighSurrogate = 0;
272 2 : pContext->m_eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_NONE;
273 2 : return pContext;
274 : }
275 :
276 0 : void ImplResetUnicodeToIso2022KrContext(void * pContext)
277 : {
278 0 : if (pContext)
279 : {
280 0 : static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_nHighSurrogate = 0;
281 : static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_eSet
282 0 : = IMPL_UNICODE_TO_ISO_2022_KR_SET_NONE;
283 : }
284 0 : }
285 :
286 2 : void ImplDestroyUnicodeToIso2022KrContext(void * pContext)
287 : {
288 2 : delete static_cast< ImplUnicodeToIso2022KrContext * >(pContext);
289 2 : }
290 :
291 2 : sal_Size ImplConvertUnicodeToIso2022Kr(void const * pData,
292 : void * pContext,
293 : sal_Unicode const * pSrcBuf,
294 : sal_Size nSrcChars,
295 : char * pDestBuf,
296 : sal_Size nDestBytes,
297 : sal_uInt32 nFlags,
298 : sal_uInt32 * pInfo,
299 : sal_Size * pSrcCvtChars)
300 : {
301 : ImplUniToDBCSHighTab const * pKsX1001Data
302 : = static_cast< ImplIso2022KrConverterData const * >(pData)->
303 2 : m_pUnicodeToKsX1001Data;
304 2 : sal_Unicode nHighSurrogate = 0;
305 2 : ImplUnicodeToIso2022KrSet eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_NONE;
306 2 : sal_uInt32 nInfo = 0;
307 2 : sal_Size nConverted = 0;
308 2 : char * pDestBufPtr = pDestBuf;
309 2 : char * pDestBufEnd = pDestBuf + nDestBytes;
310 : bool bWritten;
311 :
312 2 : if (pContext)
313 : {
314 : nHighSurrogate
315 2 : = static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_nHighSurrogate;
316 2 : eSet = static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_eSet;
317 : }
318 :
319 2 : if (eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_NONE)
320 : {
321 2 : if (pDestBufEnd - pDestBufPtr >= 4)
322 : {
323 2 : *pDestBufPtr++ = 0x1B; // ESC
324 2 : *pDestBufPtr++ = 0x24; // $
325 2 : *pDestBufPtr++ = 0x29; // )
326 2 : *pDestBufPtr++ = 0x43; // C
327 2 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
328 : }
329 : else
330 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
331 : }
332 :
333 2 : if ((nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) == 0)
334 15 : for (; nConverted < nSrcChars; ++nConverted)
335 : {
336 13 : bool bUndefined = true;
337 13 : sal_uInt32 nChar = *pSrcBuf++;
338 13 : if (nHighSurrogate == 0)
339 : {
340 13 : if (ImplIsHighSurrogate(nChar))
341 : {
342 0 : nHighSurrogate = (sal_Unicode) nChar;
343 0 : continue;
344 : }
345 : }
346 0 : else if (ImplIsLowSurrogate(nChar))
347 0 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
348 : else
349 : {
350 0 : bUndefined = false;
351 0 : goto bad_input;
352 : }
353 :
354 13 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
355 : {
356 0 : bUndefined = false;
357 0 : goto bad_input;
358 : }
359 :
360 13 : if (nChar == 0x0A || nChar == 0x0D) // LF, CR
361 : {
362 2 : if (eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_1001)
363 : {
364 1 : if (pDestBufPtr != pDestBufEnd)
365 : {
366 1 : *pDestBufPtr++ = 0x0F; // SI
367 1 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
368 : }
369 : else
370 0 : goto no_output;
371 : }
372 4 : if (pDestBufPtr != pDestBufEnd)
373 2 : *pDestBufPtr++ = static_cast< char >(nChar);
374 : else
375 0 : goto no_output;
376 : }
377 11 : else if (nChar == 0x0E || nChar == 0x0F || nChar == 0x1B)
378 : goto bad_input;
379 11 : else if (nChar < 0x80)
380 : {
381 9 : if (eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_1001)
382 : {
383 0 : if (pDestBufPtr != pDestBufEnd)
384 : {
385 0 : *pDestBufPtr++ = 0x0F; // SI
386 0 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
387 : }
388 : else
389 0 : goto no_output;
390 : }
391 9 : if (pDestBufPtr != pDestBufEnd)
392 9 : *pDestBufPtr++ = static_cast< char >(nChar);
393 : else
394 0 : goto no_output;
395 : }
396 : else
397 : {
398 2 : sal_uInt16 nBytes = 0;
399 2 : sal_uInt32 nIndex1 = nChar >> 8;
400 2 : if (nIndex1 < 0x100)
401 : {
402 2 : sal_uInt32 nIndex2 = nChar & 0xFF;
403 2 : sal_uInt32 nFirst = pKsX1001Data[nIndex1].mnLowStart;
404 2 : if (nIndex2 >= nFirst
405 2 : && nIndex2 <= pKsX1001Data[nIndex1].mnLowEnd)
406 2 : nBytes = pKsX1001Data[nIndex1].
407 2 : mpToUniTrailTab[nIndex2 - nFirst];
408 : }
409 2 : if (nBytes != 0)
410 : {
411 2 : if (eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII)
412 : {
413 2 : if (pDestBufPtr != pDestBufEnd)
414 : {
415 2 : *pDestBufPtr++ = 0x0E; // SO
416 2 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_1001;
417 : }
418 : else
419 0 : goto no_output;
420 : }
421 2 : if (pDestBufEnd - pDestBufPtr >= 2)
422 : {
423 2 : *pDestBufPtr++ = static_cast< char >((nBytes >> 8) & 0x7F);
424 2 : *pDestBufPtr++ = static_cast< char >(nBytes & 0x7F);
425 : }
426 : else
427 0 : goto no_output;
428 : }
429 : else
430 0 : goto bad_input;
431 : }
432 13 : nHighSurrogate = 0;
433 13 : continue;
434 :
435 : bad_input:
436 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
437 : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
438 : &nInfo, "\x0F" /* SI */,
439 : eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII ? 0 : 1,
440 0 : &bWritten))
441 : {
442 : case sal::detail::textenc::BAD_INPUT_STOP:
443 0 : nHighSurrogate = 0;
444 0 : break;
445 :
446 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
447 0 : if (bWritten)
448 0 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
449 0 : nHighSurrogate = 0;
450 0 : continue;
451 :
452 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
453 0 : goto no_output;
454 : }
455 0 : break;
456 :
457 : no_output:
458 0 : --pSrcBuf;
459 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
460 0 : break;
461 : }
462 :
463 2 : if ((nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
464 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
465 : == 0)
466 : {
467 2 : bool bFlush = true;
468 2 : if (nHighSurrogate != 0)
469 : {
470 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
471 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
472 : else
473 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
474 : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
475 : "\x0F" /* SI */,
476 : (eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII
477 : ? 0 : 1),
478 0 : &bWritten))
479 : {
480 : case sal::detail::textenc::BAD_INPUT_STOP:
481 0 : nHighSurrogate = 0;
482 0 : bFlush = false;
483 0 : break;
484 :
485 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
486 0 : if (bWritten)
487 0 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
488 0 : nHighSurrogate = 0;
489 0 : break;
490 :
491 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
492 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
493 0 : break;
494 : }
495 : }
496 2 : if (bFlush
497 2 : && eSet == IMPL_UNICODE_TO_ISO_2022_KR_SET_1001
498 1 : && (nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
499 : {
500 1 : if (pDestBufPtr != pDestBufEnd)
501 : {
502 1 : *pDestBufPtr++ = 0x0F; // SI
503 1 : eSet = IMPL_UNICODE_TO_ISO_2022_KR_SET_ASCII;
504 : }
505 : else
506 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
507 : }
508 : }
509 :
510 2 : if (pContext)
511 : {
512 : static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_nHighSurrogate
513 2 : = nHighSurrogate;
514 2 : static_cast< ImplUnicodeToIso2022KrContext * >(pContext)->m_eSet = eSet;
515 : }
516 2 : if (pInfo)
517 2 : *pInfo = nInfo;
518 2 : if (pSrcCvtChars)
519 2 : *pSrcCvtChars = nConverted;
520 :
521 2 : return pDestBufPtr - pDestBuf;
522 : }
523 :
524 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|