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