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