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