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 "convertiso2022cn.hxx"
27 : #include "tenchelp.hxx"
28 : #include "unichars.hxx"
29 :
30 : namespace {
31 :
32 : enum ImplIso2022CnToUnicodeState // order is important:
33 : {
34 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII,
35 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO,
36 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2,
37 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432,
38 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2,
39 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC,
40 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR,
41 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN,
42 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK
43 : };
44 :
45 : struct ImplIso2022CnToUnicodeContext
46 : {
47 : ImplIso2022CnToUnicodeState m_eState;
48 : sal_uInt32 m_nRow;
49 : bool m_bSo;
50 : bool m_b116431;
51 : };
52 :
53 : enum ImplUnicodeToIso2022CnDesignator
54 : {
55 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE,
56 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312,
57 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431
58 : };
59 :
60 : struct ImplUnicodeToIso2022CnContext
61 : {
62 : sal_Unicode m_nHighSurrogate;
63 : ImplUnicodeToIso2022CnDesignator m_eSoDesignator;
64 : bool m_b116432Designator;
65 : bool m_bSo;
66 : };
67 :
68 : }
69 :
70 4 : void * ImplCreateIso2022CnToUnicodeContext()
71 : {
72 : ImplIso2022CnToUnicodeContext * pContext =
73 4 : new ImplIso2022CnToUnicodeContext;
74 4 : pContext->m_eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
75 4 : pContext->m_bSo = false;
76 4 : pContext->m_b116431 = false;
77 4 : return pContext;
78 : }
79 :
80 0 : void ImplResetIso2022CnToUnicodeContext(void * pContext)
81 : {
82 0 : if (pContext)
83 : {
84 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState
85 0 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
86 0 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo = false;
87 0 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431 = false;
88 : }
89 0 : }
90 :
91 4 : void ImplDestroyIso2022CnToUnicodeContext(void * pContext)
92 : {
93 4 : delete static_cast< ImplIso2022CnToUnicodeContext * >(pContext);
94 4 : }
95 :
96 74 : sal_Size ImplConvertIso2022CnToUnicode(void const * pData,
97 : void * pContext,
98 : char const * pSrcBuf,
99 : sal_Size nSrcBytes,
100 : sal_Unicode * pDestBuf,
101 : sal_Size nDestChars,
102 : sal_uInt32 nFlags,
103 : sal_uInt32 * pInfo,
104 : sal_Size * pSrcCvtBytes)
105 : {
106 : ImplDBCSToUniLeadTab const * pGb2312Data
107 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
108 74 : m_pGb2312ToUnicodeData;
109 : sal_uInt16 const * pCns116431992Data
110 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
111 74 : m_pCns116431992ToUnicodeData;
112 : sal_Int32 const * pCns116431992RowOffsets
113 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
114 74 : m_pCns116431992ToUnicodeRowOffsets;
115 : sal_Int32 const * pCns116431992PlaneOffsets
116 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
117 74 : m_pCns116431992ToUnicodePlaneOffsets;
118 : ImplIso2022CnToUnicodeState eState
119 74 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
120 74 : sal_uInt32 nRow = 0;
121 74 : bool bSo = false;
122 74 : bool b116431 = false;
123 74 : sal_uInt32 nInfo = 0;
124 74 : sal_Size nConverted = 0;
125 74 : sal_Unicode * pDestBufPtr = pDestBuf;
126 74 : sal_Unicode * pDestBufEnd = pDestBuf + nDestChars;
127 :
128 74 : if (pContext)
129 : {
130 74 : eState = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState;
131 74 : nRow = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow;
132 74 : bSo = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo;
133 74 : b116431 = static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431;
134 : }
135 :
136 214 : for (; nConverted < nSrcBytes; ++nConverted)
137 : {
138 140 : bool bUndefined = true;
139 140 : sal_uInt32 nChar = *reinterpret_cast<unsigned char const *>(pSrcBuf++);
140 : sal_uInt32 nPlane;
141 140 : switch (eState)
142 : {
143 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII:
144 52 : if (nChar == 0x0E) // SO
145 : {
146 8 : bSo = true;
147 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO;
148 : }
149 44 : else if (nChar == 0x1B) // ESC
150 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
151 36 : else if (nChar < 0x80)
152 36 : if (pDestBufPtr != pDestBufEnd)
153 36 : *pDestBufPtr++ = (sal_Unicode) nChar;
154 : else
155 0 : goto no_output;
156 : else
157 : {
158 0 : bUndefined = false;
159 0 : goto bad_input;
160 : }
161 52 : break;
162 :
163 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO:
164 28 : if (nChar == 0x0F) // SI
165 : {
166 8 : bSo = false;
167 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
168 : }
169 20 : else if (nChar == 0x1B) // ESC
170 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC;
171 12 : else if (nChar >= 0x21 && nChar <= 0x7E)
172 : {
173 12 : nRow = nChar;
174 12 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2;
175 : }
176 : else
177 : {
178 0 : bUndefined = false;
179 0 : goto bad_input;
180 : }
181 28 : break;
182 :
183 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO_2:
184 12 : if (nChar >= 0x21 && nChar <= 0x7E)
185 12 : if (b116431)
186 : {
187 4 : nPlane = 0;
188 4 : goto transform;
189 : }
190 : else
191 : {
192 8 : sal_uInt16 nUnicode = 0;
193 : sal_uInt32 nFirst;
194 8 : nRow += 0x80;
195 8 : nChar += 0x80;
196 8 : nFirst = pGb2312Data[nRow].mnTrailStart;
197 8 : if (nChar >= nFirst
198 8 : && nChar <= pGb2312Data[nRow].mnTrailEnd)
199 8 : nUnicode = pGb2312Data[nRow].
200 8 : mpToUniTrailTab[nChar - nFirst];
201 8 : if (nUnicode != 0)
202 8 : if (pDestBufPtr != pDestBufEnd)
203 : {
204 8 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
205 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO;
206 : }
207 : else
208 0 : goto no_output;
209 : else
210 0 : goto bad_input;
211 8 : }
212 : else
213 : {
214 0 : bUndefined = false;
215 0 : goto bad_input;
216 : }
217 8 : break;
218 :
219 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432:
220 4 : if (nChar >= 0x21 && nChar <= 0x7E)
221 : {
222 4 : nRow = nChar;
223 4 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2;
224 : }
225 : else
226 : {
227 0 : bUndefined = false;
228 0 : goto bad_input;
229 : }
230 4 : break;
231 :
232 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432_2:
233 4 : if (nChar >= 0x21 && nChar <= 0x7E)
234 : {
235 4 : nPlane = 1;
236 4 : goto transform;
237 : }
238 : else
239 : {
240 0 : bUndefined = false;
241 0 : goto bad_input;
242 : }
243 : break;
244 :
245 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC:
246 16 : if (nChar == 0x24) // $
247 12 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR;
248 4 : else if (nChar == 0x4E) // N
249 4 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_116432;
250 : else
251 : {
252 0 : bUndefined = false;
253 0 : goto bad_input;
254 : }
255 16 : break;
256 :
257 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR:
258 12 : if (nChar == 0x29) // )
259 8 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN;
260 4 : else if (nChar == 0x2A) // *
261 : eState
262 4 : = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK;
263 : else
264 : {
265 0 : bUndefined = false;
266 0 : goto bad_input;
267 : }
268 12 : break;
269 :
270 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_RPAREN:
271 8 : if (nChar == 0x41) // A
272 : {
273 6 : b116431 = false;
274 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
275 6 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
276 : }
277 2 : else if (nChar == 0x47) // G
278 : {
279 2 : b116431 = true;
280 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
281 2 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
282 : }
283 : else
284 : {
285 0 : bUndefined = false;
286 0 : goto bad_input;
287 : }
288 8 : break;
289 :
290 : case IMPL_ISO_2022_CN_TO_UNICODE_STATE_ESC_DOLLAR_ASTERISK:
291 4 : if (nChar == 0x48) // H
292 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
293 4 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
294 : else
295 : {
296 0 : bUndefined = false;
297 0 : goto bad_input;
298 : }
299 4 : break;
300 : }
301 132 : continue;
302 :
303 : transform:
304 : {
305 8 : sal_Int32 nPlaneOffset = pCns116431992PlaneOffsets[nPlane];
306 8 : if (nPlaneOffset == -1)
307 0 : goto bad_input;
308 : else
309 : {
310 : sal_Int32 nOffset
311 8 : = pCns116431992RowOffsets[nPlaneOffset + (nRow - 0x21)];
312 8 : if (nOffset == -1)
313 0 : goto bad_input;
314 : else
315 : {
316 8 : sal_uInt32 nFirstLast = pCns116431992Data[nOffset++];
317 8 : sal_uInt32 nFirst = nFirstLast & 0xFF;
318 8 : sal_uInt32 nLast = nFirstLast >> 8;
319 8 : nChar -= 0x20;
320 8 : if (nChar >= nFirst && nChar <= nLast)
321 : {
322 : sal_uInt32 nUnicode
323 8 : = pCns116431992Data[nOffset + (nChar - nFirst)];
324 8 : if (nUnicode == 0xFFFF)
325 0 : goto bad_input;
326 8 : else if (ImplIsHighSurrogate(nUnicode))
327 0 : if (pDestBufEnd - pDestBufPtr >= 2)
328 : {
329 0 : nOffset += nLast - nFirst + 1;
330 0 : nFirst = pCns116431992Data[nOffset++];
331 0 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
332 : *pDestBufPtr++
333 : = (sal_Unicode)
334 : pCns116431992Data[
335 0 : nOffset + (nChar - nFirst)];
336 : }
337 : else
338 0 : goto no_output;
339 : else
340 8 : if (pDestBufPtr != pDestBufEnd)
341 8 : *pDestBufPtr++ = (sal_Unicode) nUnicode;
342 : else
343 0 : goto no_output;
344 : }
345 : else
346 : goto bad_input;
347 : eState = bSo ? IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO :
348 8 : IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
349 : }
350 : }
351 8 : continue;
352 : }
353 :
354 : bad_input:
355 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
356 : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
357 0 : &nInfo))
358 : {
359 : case sal::detail::textenc::BAD_INPUT_STOP:
360 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
361 0 : b116431 = false;
362 0 : break;
363 :
364 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
365 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
366 0 : b116431 = false;
367 0 : continue;
368 :
369 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
370 0 : goto no_output;
371 : }
372 0 : break;
373 :
374 : no_output:
375 0 : --pSrcBuf;
376 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
377 0 : break;
378 : }
379 :
380 74 : if (eState > IMPL_ISO_2022_CN_TO_UNICODE_STATE_SO
381 30 : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
382 : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
383 : == 0)
384 : {
385 30 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
386 30 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
387 : else
388 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
389 : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
390 0 : &nInfo))
391 : {
392 : case sal::detail::textenc::BAD_INPUT_STOP:
393 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
394 0 : eState = IMPL_ISO_2022_CN_TO_UNICODE_STATE_ASCII;
395 0 : b116431 = false;
396 0 : break;
397 :
398 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
399 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
400 0 : break;
401 : }
402 : }
403 :
404 74 : if (pContext)
405 : {
406 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_eState = eState;
407 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_nRow = nRow;
408 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_bSo = bSo;
409 74 : static_cast< ImplIso2022CnToUnicodeContext * >(pContext)->m_b116431 = b116431;
410 : }
411 74 : if (pInfo)
412 74 : *pInfo = nInfo;
413 74 : if (pSrcCvtBytes)
414 74 : *pSrcCvtBytes = nConverted;
415 :
416 74 : return pDestBufPtr - pDestBuf;
417 : }
418 :
419 1 : void * ImplCreateUnicodeToIso2022CnContext()
420 : {
421 : ImplUnicodeToIso2022CnContext * pContext =
422 1 : new ImplUnicodeToIso2022CnContext;
423 1 : pContext->m_nHighSurrogate = 0;
424 1 : pContext->m_eSoDesignator = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
425 1 : pContext->m_b116432Designator = false;
426 1 : pContext->m_bSo = false;
427 1 : return pContext;
428 : }
429 :
430 0 : void ImplResetUnicodeToIso2022CnContext(void * pContext)
431 : {
432 0 : if (pContext)
433 : {
434 0 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate = 0;
435 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator
436 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
437 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_b116432Designator
438 0 : = false;
439 0 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo = false;
440 : }
441 0 : }
442 :
443 1 : void ImplDestroyUnicodeToIso2022CnContext(void * pContext)
444 : {
445 1 : delete static_cast< ImplUnicodeToIso2022CnContext * >(pContext);
446 1 : }
447 :
448 4 : static sal_uInt32 ImplIso2022CnTranslateTo2312(ImplUniToDBCSHighTab const *
449 : pGb2312Data,
450 : sal_uInt32 nChar)
451 : {
452 4 : sal_uInt32 nIndex1 = nChar >> 8;
453 4 : if (nIndex1 < 0x100)
454 : {
455 4 : sal_uInt32 nIndex2 = nChar & 0xFF;
456 4 : sal_uInt32 nFirst = pGb2312Data[nIndex1].mnLowStart;
457 4 : if (nIndex2 >= nFirst && nIndex2 <= pGb2312Data[nIndex1].mnLowEnd)
458 4 : return pGb2312Data[nIndex1].mpToUniTrailTab[nIndex2 - nFirst]
459 4 : & 0x7F7F;
460 : }
461 0 : return 0;
462 : }
463 :
464 : static sal_uInt32
465 1 : ImplIso2022CnTranslateTo116431(sal_uInt8 const * pCns116431992Data,
466 : sal_Int32 const * pCns116431992PageOffsets,
467 : sal_Int32 const * pCns116431992PlaneOffsets,
468 : sal_uInt32 nChar)
469 : {
470 1 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
471 : sal_uInt32 nFirst;
472 : sal_uInt32 nLast;
473 : sal_uInt32 nPlane;
474 1 : if (nOffset == -1)
475 0 : return 0;
476 1 : nOffset = pCns116431992PageOffsets[nOffset + ((nChar & 0xFF00) >> 8)];
477 1 : if (nOffset == -1)
478 0 : return 0;
479 1 : nFirst = pCns116431992Data[nOffset++];
480 1 : nLast = pCns116431992Data[nOffset++];
481 1 : nChar &= 0xFF;
482 1 : if (nChar < nFirst || nChar > nLast)
483 0 : return 0;
484 1 : nOffset += 3 * (nChar - nFirst);
485 1 : nPlane = pCns116431992Data[nOffset++];
486 1 : if (nPlane != 1)
487 1 : return 0;
488 0 : return (0x20 + pCns116431992Data[nOffset]) << 8
489 0 : | (0x20 + pCns116431992Data[nOffset + 1]);
490 : }
491 :
492 1 : sal_Size ImplConvertUnicodeToIso2022Cn(void const * pData,
493 : void * pContext,
494 : sal_Unicode const * pSrcBuf,
495 : sal_Size nSrcChars,
496 : char * pDestBuf,
497 : sal_Size nDestBytes,
498 : sal_uInt32 nFlags,
499 : sal_uInt32 * pInfo,
500 : sal_Size * pSrcCvtChars)
501 : {
502 : ImplUniToDBCSHighTab const * pGb2312Data
503 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
504 1 : m_pUnicodeToGb2312Data;
505 : sal_uInt8 const * pCns116431992Data
506 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
507 1 : m_pUnicodeToCns116431992Data;
508 : sal_Int32 const * pCns116431992PageOffsets
509 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
510 1 : m_pUnicodeToCns116431992PageOffsets;
511 : sal_Int32 const * pCns116431992PlaneOffsets
512 : = static_cast< ImplIso2022CnConverterData const * >(pData)->
513 1 : m_pUnicodeToCns116431992PlaneOffsets;
514 1 : sal_Unicode nHighSurrogate = 0;
515 : ImplUnicodeToIso2022CnDesignator eSoDesignator
516 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
517 1 : bool b116432Designator = false;
518 1 : bool bSo = false;
519 1 : sal_uInt32 nInfo = 0;
520 1 : sal_Size nConverted = 0;
521 1 : char * pDestBufPtr = pDestBuf;
522 1 : char * pDestBufEnd = pDestBuf + nDestBytes;
523 : bool bWritten;
524 :
525 1 : if (pContext)
526 : {
527 : nHighSurrogate
528 1 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate;
529 : eSoDesignator
530 1 : = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator;
531 : b116432Designator = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->
532 1 : m_b116432Designator;
533 1 : bSo = static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo;
534 : }
535 :
536 15 : for (; nConverted < nSrcChars; ++nConverted)
537 : {
538 14 : bool bUndefined = true;
539 14 : sal_uInt32 nChar = *pSrcBuf++;
540 14 : if (nHighSurrogate == 0)
541 : {
542 14 : if (ImplIsHighSurrogate(nChar))
543 : {
544 0 : nHighSurrogate = (sal_Unicode) nChar;
545 0 : continue;
546 : }
547 : }
548 0 : else if (ImplIsLowSurrogate(nChar))
549 0 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
550 : else
551 : {
552 0 : bUndefined = false;
553 0 : goto bad_input;
554 : }
555 :
556 14 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
557 : {
558 0 : bUndefined = false;
559 0 : goto bad_input;
560 : }
561 :
562 14 : if (nChar == 0x0A || nChar == 0x0D) // LF, CR
563 : {
564 2 : if (bSo)
565 : {
566 1 : if (pDestBufPtr != pDestBufEnd)
567 : {
568 1 : *pDestBufPtr++ = 0x0F; // SI
569 1 : bSo = false;
570 : eSoDesignator
571 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
572 1 : b116432Designator = false;
573 : }
574 : else
575 0 : goto no_output;
576 : }
577 4 : if (pDestBufPtr != pDestBufEnd)
578 2 : *pDestBufPtr++ = static_cast< char >(nChar);
579 : else
580 0 : goto no_output;
581 : }
582 12 : else if (nChar == 0x0E || nChar == 0x0F || nChar == 0x1B)
583 : goto bad_input;
584 12 : else if (nChar < 0x80)
585 : {
586 8 : if (bSo)
587 : {
588 0 : if (pDestBufPtr != pDestBufEnd)
589 : {
590 0 : *pDestBufPtr++ = 0x0F; // SI
591 0 : bSo = false;
592 : }
593 : else
594 0 : goto no_output;
595 : }
596 8 : if (pDestBufPtr != pDestBufEnd)
597 8 : *pDestBufPtr++ = static_cast< char >(nChar);
598 : else
599 0 : goto no_output;
600 : }
601 : else
602 : {
603 4 : sal_uInt32 nBytes = 0;
604 : ImplUnicodeToIso2022CnDesignator eNewDesignator =
605 4 : IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
606 4 : switch (eSoDesignator)
607 : {
608 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE:
609 2 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
610 2 : if (nBytes != 0)
611 : {
612 : eNewDesignator
613 2 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312;
614 2 : break;
615 : }
616 : nBytes = ImplIso2022CnTranslateTo116431(
617 : pCns116431992Data,
618 : pCns116431992PageOffsets,
619 : pCns116431992PlaneOffsets,
620 0 : nChar);
621 0 : if (nBytes != 0)
622 : {
623 : eNewDesignator
624 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431;
625 0 : break;
626 : }
627 0 : break;
628 :
629 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312:
630 2 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
631 2 : if (nBytes != 0)
632 : {
633 : eNewDesignator
634 1 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
635 1 : break;
636 : }
637 : nBytes = ImplIso2022CnTranslateTo116431(
638 : pCns116431992Data,
639 : pCns116431992PageOffsets,
640 : pCns116431992PlaneOffsets,
641 1 : nChar);
642 1 : if (nBytes != 0)
643 : {
644 : eNewDesignator
645 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431;
646 0 : break;
647 : }
648 1 : break;
649 :
650 : case IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_116431:
651 : nBytes = ImplIso2022CnTranslateTo116431(
652 : pCns116431992Data,
653 : pCns116431992PageOffsets,
654 : pCns116431992PlaneOffsets,
655 0 : nChar);
656 0 : if (nBytes != 0)
657 : {
658 : eNewDesignator
659 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE;
660 0 : break;
661 : }
662 0 : nBytes = ImplIso2022CnTranslateTo2312(pGb2312Data, nChar);
663 0 : if (nBytes != 0)
664 : {
665 : eNewDesignator
666 0 : = IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312;
667 0 : break;
668 : }
669 0 : break;
670 : }
671 4 : if (nBytes != 0)
672 : {
673 3 : if (eNewDesignator
674 : != IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_NONE)
675 : {
676 2 : if (bSo)
677 : {
678 0 : if (pDestBufPtr != pDestBufEnd)
679 : {
680 0 : *pDestBufPtr++ = 0x0F; // SI
681 0 : bSo = false;
682 : }
683 : else
684 0 : goto no_output;
685 : }
686 2 : if (pDestBufEnd - pDestBufPtr >= 4)
687 : {
688 2 : *pDestBufPtr++ = 0x1B; // ESC
689 2 : *pDestBufPtr++ = 0x24; // $
690 2 : *pDestBufPtr++ = 0x29; // )
691 : *pDestBufPtr++
692 : = eNewDesignator
693 : == IMPL_UNICODE_TO_ISO_2022_CN_DESIGNATOR_2312 ?
694 2 : 0x41 : 0x47; // A, G
695 2 : eSoDesignator = eNewDesignator;
696 : }
697 : else
698 0 : goto no_output;
699 : }
700 3 : if (!bSo)
701 : {
702 2 : if (pDestBufPtr != pDestBufEnd)
703 : {
704 2 : *pDestBufPtr++ = 0x0E; // SO
705 2 : bSo = true;
706 : }
707 : else
708 0 : goto no_output;
709 : }
710 3 : if (pDestBufEnd - pDestBufPtr >= 4)
711 : {
712 3 : *pDestBufPtr++ = static_cast< char >(nBytes >> 8);
713 3 : *pDestBufPtr++ = static_cast< char >(nBytes & 0xFF);
714 : }
715 : else
716 0 : goto no_output;
717 : }
718 : else
719 : {
720 1 : sal_Int32 nOffset = pCns116431992PlaneOffsets[nChar >> 16];
721 : sal_uInt32 nFirst;
722 : sal_uInt32 nLast;
723 : sal_uInt32 nPlane;
724 1 : if (nOffset == -1)
725 0 : goto bad_input;
726 : nOffset
727 : = pCns116431992PageOffsets[nOffset
728 1 : + ((nChar & 0xFF00) >> 8)];
729 1 : if (nOffset == -1)
730 0 : goto bad_input;
731 1 : nFirst = pCns116431992Data[nOffset++];
732 1 : nLast = pCns116431992Data[nOffset++];
733 1 : nChar &= 0xFF;
734 1 : if (nChar < nFirst || nChar > nLast)
735 : goto bad_input;
736 1 : nOffset += 3 * (nChar - nFirst);
737 1 : nPlane = pCns116431992Data[nOffset++];
738 1 : if (nPlane != 2)
739 0 : goto bad_input;
740 1 : if (!b116432Designator)
741 : {
742 1 : if (pDestBufEnd - pDestBufPtr >= 4)
743 : {
744 1 : *pDestBufPtr++ = 0x1B; // ESC
745 1 : *pDestBufPtr++ = 0x24; // $
746 1 : *pDestBufPtr++ = 0x2A; // *
747 1 : *pDestBufPtr++ = 0x48; // H
748 1 : b116432Designator = true;
749 : }
750 : else
751 0 : goto no_output;
752 : }
753 1 : if (pDestBufEnd - pDestBufPtr >= 4)
754 : {
755 1 : *pDestBufPtr++ = 0x1B; // ESC
756 1 : *pDestBufPtr++ = 0x4E; // N
757 : *pDestBufPtr++
758 1 : = static_cast< char >(0x20 + pCns116431992Data[nOffset++]);
759 : *pDestBufPtr++
760 1 : = static_cast< char >(0x20 + pCns116431992Data[nOffset]);
761 : }
762 : else
763 0 : goto no_output;
764 : }
765 : }
766 14 : nHighSurrogate = 0;
767 14 : continue;
768 :
769 : bad_input:
770 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
771 : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
772 0 : &nInfo, "\x0F" /* SI */, bSo ? 1 : 0, &bWritten))
773 : {
774 : case sal::detail::textenc::BAD_INPUT_STOP:
775 0 : nHighSurrogate = 0;
776 0 : break;
777 :
778 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
779 0 : if (bWritten)
780 0 : bSo = false;
781 0 : nHighSurrogate = 0;
782 0 : continue;
783 :
784 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
785 0 : goto no_output;
786 : }
787 0 : break;
788 :
789 : no_output:
790 0 : --pSrcBuf;
791 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
792 0 : break;
793 : }
794 :
795 1 : if ((nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
796 : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
797 : == 0)
798 : {
799 1 : bool bFlush = true;
800 1 : if (nHighSurrogate != 0)
801 : {
802 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
803 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
804 : else
805 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
806 : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
807 0 : "\x0F" /* SI */, bSo ? 1 : 0, &bWritten))
808 : {
809 : case sal::detail::textenc::BAD_INPUT_STOP:
810 0 : nHighSurrogate = 0;
811 0 : bFlush = false;
812 0 : break;
813 :
814 : case sal::detail::textenc::BAD_INPUT_CONTINUE:
815 0 : if (bWritten)
816 0 : bSo = false;
817 0 : nHighSurrogate = 0;
818 0 : break;
819 :
820 : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
821 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
822 0 : break;
823 : }
824 : }
825 1 : if (bFlush && bSo && (nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
826 : {
827 1 : if (pDestBufPtr != pDestBufEnd)
828 : {
829 1 : *pDestBufPtr++ = 0x0F; // SI
830 1 : bSo = false;
831 : }
832 : else
833 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
834 : }
835 : }
836 :
837 1 : if (pContext)
838 : {
839 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_nHighSurrogate
840 1 : = nHighSurrogate;
841 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_eSoDesignator
842 1 : = eSoDesignator;
843 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_b116432Designator
844 1 : = b116432Designator;
845 1 : static_cast< ImplUnicodeToIso2022CnContext * >(pContext)->m_bSo = bSo;
846 : }
847 1 : if (pInfo)
848 1 : *pInfo = nInfo;
849 1 : if (pSrcCvtChars)
850 1 : *pSrcCvtChars = nConverted;
851 :
852 1 : return pDestBufPtr - pDestBuf;
853 : }
854 :
855 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|