Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "sal/config.h"
30 : :
31 : : #include "rtl/textcvt.h"
32 : : #include "sal/types.h"
33 : :
34 : : #include "context.hxx"
35 : : #include "converter.hxx"
36 : : #include "convertgb18030.hxx"
37 : : #include "tenchelp.hxx"
38 : : #include "unichars.hxx"
39 : :
40 : : namespace {
41 : :
42 : : enum ImplGb18030ToUnicodeState
43 : : {
44 : : IMPL_GB_18030_TO_UNICODE_STATE_0,
45 : : IMPL_GB_18030_TO_UNICODE_STATE_1,
46 : : IMPL_GB_18030_TO_UNICODE_STATE_2,
47 : : IMPL_GB_18030_TO_UNICODE_STATE_3
48 : : };
49 : :
50 : : struct ImplGb18030ToUnicodeContext
51 : : {
52 : : ImplGb18030ToUnicodeState m_eState;
53 : : sal_uInt32 m_nCode;
54 : : };
55 : :
56 : : }
57 : :
58 : 0 : void * ImplCreateGb18030ToUnicodeContext()
59 : : {
60 : 0 : ImplGb18030ToUnicodeContext * pContext = new ImplGb18030ToUnicodeContext;
61 : 0 : pContext->m_eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
62 : 0 : return pContext;
63 : : }
64 : :
65 : 0 : void ImplResetGb18030ToUnicodeContext(void * pContext)
66 : : {
67 [ # # ]: 0 : if (pContext)
68 : : static_cast< ImplGb18030ToUnicodeContext * >(pContext)->m_eState
69 : 0 : = IMPL_GB_18030_TO_UNICODE_STATE_0;
70 : 0 : }
71 : :
72 : 0 : void ImplDestroyGb18030ToUnicodeContext(void * pContext)
73 : : {
74 : 0 : delete static_cast< ImplGb18030ToUnicodeContext * >(pContext);
75 : 0 : }
76 : :
77 : 0 : sal_Size ImplConvertGb18030ToUnicode(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 : : sal_Unicode const * pGb18030Data
88 : 0 : = static_cast< ImplGb18030ConverterData const * >(pData)->m_pGb18030ToUnicodeData;
89 : : ImplGb180302000ToUnicodeRange const * pGb18030Ranges
90 : : = static_cast< ImplGb18030ConverterData const * >(pData)->
91 : 0 : m_pGb18030ToUnicodeRanges;
92 : 0 : ImplGb18030ToUnicodeState eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
93 : 0 : sal_uInt32 nCode = 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< ImplGb18030ToUnicodeContext * >(pContext)->m_eState;
102 : 0 : nCode = static_cast< ImplGb18030ToUnicodeContext * >(pContext)->m_nCode;
103 : : }
104 : :
105 [ # # ]: 0 : for (; nConverted < nSrcBytes; ++nConverted)
106 : : {
107 : 0 : bool bUndefined = true;
108 : 0 : sal_uInt32 nChar = *(sal_uChar const *) pSrcBuf++;
109 [ # # # # : 0 : switch (eState)
# ]
110 : : {
111 : : case IMPL_GB_18030_TO_UNICODE_STATE_0:
112 [ # # ]: 0 : if (nChar < 0x80)
113 [ # # ]: 0 : if (pDestBufPtr != pDestBufEnd)
114 : 0 : *pDestBufPtr++ = (sal_Unicode) nChar;
115 : : else
116 : 0 : goto no_output;
117 [ # # ]: 0 : else if (nChar == 0x80)
118 : 0 : goto bad_input;
119 [ # # ]: 0 : else if (nChar <= 0xFE)
120 : : {
121 : 0 : nCode = nChar - 0x81;
122 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_1;
123 : : }
124 : : else
125 : : {
126 : 0 : bUndefined = false;
127 : 0 : goto bad_input;
128 : : }
129 : 0 : break;
130 : :
131 : : case IMPL_GB_18030_TO_UNICODE_STATE_1:
132 [ # # ][ # # ]: 0 : if (nChar >= 0x30 && nChar <= 0x39)
133 : : {
134 : 0 : nCode = nCode * 10 + (nChar - 0x30);
135 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_2;
136 : : }
137 [ # # ][ # # ]: 0 : else if ((nChar >= 0x40 && nChar <= 0x7E)
[ # # ][ # # ]
138 : : || (nChar >= 0x80 && nChar <= 0xFE))
139 : : {
140 : : nCode = nCode * 190 + (nChar <= 0x7E ? nChar - 0x40 :
141 [ # # ]: 0 : nChar - 0x80 + 63);
142 [ # # ]: 0 : if (pDestBufPtr != pDestBufEnd)
143 : 0 : *pDestBufPtr++ = pGb18030Data[nCode];
144 : : else
145 : 0 : goto no_output;
146 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
147 : : }
148 : : else
149 : : {
150 : 0 : bUndefined = false;
151 : 0 : goto bad_input;
152 : : }
153 : 0 : break;
154 : :
155 : : case IMPL_GB_18030_TO_UNICODE_STATE_2:
156 [ # # ][ # # ]: 0 : if (nChar >= 0x81 && nChar <= 0xFE)
157 : : {
158 : 0 : nCode = nCode * 126 + (nChar - 0x81);
159 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_3;
160 : : }
161 : : else
162 : : {
163 : 0 : bUndefined = false;
164 : 0 : goto bad_input;
165 : : }
166 : 0 : break;
167 : :
168 : : case IMPL_GB_18030_TO_UNICODE_STATE_3:
169 [ # # ][ # # ]: 0 : if (nChar >= 0x30 && nChar <= 0x39)
170 : : {
171 : 0 : nCode = nCode * 10 + (nChar - 0x30);
172 : :
173 : : // 90 30 81 30 to E3 32 9A 35 maps to U+10000 to U+10FFFF:
174 [ # # ][ # # ]: 0 : if (nCode >= 189000 && nCode <= 1237575)
175 [ # # ]: 0 : if (pDestBufEnd - pDestBufPtr >= 2)
176 : : {
177 : 0 : nCode -= 189000 - 0x10000;
178 : : *pDestBufPtr++
179 : 0 : = (sal_Unicode) ImplGetHighSurrogate(nCode);
180 : : *pDestBufPtr++
181 : 0 : = (sal_Unicode) ImplGetLowSurrogate(nCode);
182 : : }
183 : : else
184 : 0 : goto no_output;
185 : : else
186 : : {
187 : : ImplGb180302000ToUnicodeRange const * pRange
188 : 0 : = pGb18030Ranges;
189 : 0 : sal_uInt32 nFirstNonRange = 0;
190 : 0 : for (;;)
191 : : {
192 [ # # ]: 0 : if (pRange->m_nNonRangeDataIndex == -1)
193 : 0 : goto bad_input;
194 [ # # ]: 0 : else if (nCode < pRange->m_nFirstLinear)
195 : : {
196 [ # # ]: 0 : if (pDestBufPtr != pDestBufEnd)
197 : : *pDestBufPtr++
198 : : = pGb18030Data[
199 : : pRange->m_nNonRangeDataIndex
200 : 0 : + (nCode - nFirstNonRange)];
201 : : else
202 : 0 : goto no_output;
203 : 0 : break;
204 : : }
205 [ # # ]: 0 : else if (nCode < pRange->m_nPastLinear)
206 : : {
207 [ # # ]: 0 : if (pDestBufPtr != pDestBufEnd)
208 : : *pDestBufPtr++
209 : : = (sal_Unicode)
210 : : (pRange->m_nFirstUnicode
211 : : + (nCode
212 : : - pRange->
213 : 0 : m_nFirstLinear));
214 : : else
215 : 0 : goto no_output;
216 : 0 : break;
217 : : }
218 : 0 : nFirstNonRange = (pRange++)->m_nPastLinear;
219 : : }
220 : : }
221 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
222 : : }
223 : : else
224 : : {
225 : 0 : bUndefined = false;
226 : 0 : goto bad_input;
227 : : }
228 : 0 : break;
229 : : }
230 : 0 : continue;
231 : :
232 : : bad_input:
233 [ # # # # ]: 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
234 : : bUndefined, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
235 [ # # ]: 0 : &nInfo))
236 : : {
237 : : case sal::detail::textenc::BAD_INPUT_STOP:
238 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
239 : 0 : break;
240 : :
241 : : case sal::detail::textenc::BAD_INPUT_CONTINUE:
242 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
243 : 0 : continue;
244 : :
245 : : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
246 : 0 : goto no_output;
247 : : }
248 : 0 : break;
249 : :
250 : : no_output:
251 : 0 : --pSrcBuf;
252 : 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
253 : 0 : break;
254 : : }
255 : :
256 [ # # ][ # # ]: 0 : if (eState != IMPL_GB_18030_TO_UNICODE_STATE_0
257 : : && (nInfo & (RTL_TEXTTOUNICODE_INFO_ERROR
258 : : | RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL))
259 : : == 0)
260 : : {
261 [ # # ]: 0 : if ((nFlags & RTL_TEXTTOUNICODE_FLAGS_FLUSH) == 0)
262 : 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL;
263 : : else
264 [ # # # ]: 0 : switch (sal::detail::textenc::handleBadInputTextToUnicodeConversion(
265 : : false, true, 0, nFlags, &pDestBufPtr, pDestBufEnd,
266 [ # # ]: 0 : &nInfo))
267 : : {
268 : : case sal::detail::textenc::BAD_INPUT_STOP:
269 : : case sal::detail::textenc::BAD_INPUT_CONTINUE:
270 : 0 : eState = IMPL_GB_18030_TO_UNICODE_STATE_0;
271 : 0 : break;
272 : :
273 : : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
274 : 0 : nInfo |= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
275 : 0 : break;
276 : : }
277 : : }
278 : :
279 [ # # ]: 0 : if (pContext)
280 : : {
281 : 0 : static_cast< ImplGb18030ToUnicodeContext * >(pContext)->m_eState = eState;
282 : 0 : static_cast< ImplGb18030ToUnicodeContext * >(pContext)->m_nCode = nCode;
283 : : }
284 [ # # ]: 0 : if (pInfo)
285 : 0 : *pInfo = nInfo;
286 [ # # ]: 0 : if (pSrcCvtBytes)
287 : 0 : *pSrcCvtBytes = nConverted;
288 : :
289 : 0 : return pDestBufPtr - pDestBuf;
290 : : }
291 : :
292 : 0 : sal_Size ImplConvertUnicodeToGb18030(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 : : sal_uInt32 const * pGb18030Data
303 : : = static_cast< ImplGb18030ConverterData const * >(pData)->
304 : 0 : m_pUnicodeToGb18030Data;
305 : : ImplUnicodeToGb180302000Range const * pGb18030Ranges
306 : : = static_cast< ImplGb18030ConverterData const * >(pData)->
307 : 0 : m_pUnicodeToGb18030Ranges;
308 : 0 : sal_Unicode nHighSurrogate = 0;
309 : 0 : sal_uInt32 nInfo = 0;
310 : 0 : sal_Size nConverted = 0;
311 : 0 : char * pDestBufPtr = pDestBuf;
312 : 0 : char * pDestBufEnd = pDestBuf + nDestBytes;
313 : :
314 [ # # ]: 0 : if (pContext)
315 : : nHighSurrogate
316 : 0 : = ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate;
317 : :
318 [ # # ]: 0 : for (; nConverted < nSrcChars; ++nConverted)
319 : : {
320 : 0 : bool bUndefined = true;
321 : 0 : sal_uInt32 nChar = *pSrcBuf++;
322 [ # # ]: 0 : if (nHighSurrogate == 0)
323 : : {
324 [ # # ]: 0 : if (ImplIsHighSurrogate(nChar))
325 : : {
326 : 0 : nHighSurrogate = (sal_Unicode) nChar;
327 : 0 : continue;
328 : : }
329 : : }
330 [ # # ]: 0 : else if (ImplIsLowSurrogate(nChar))
331 : 0 : nChar = ImplCombineSurrogates(nHighSurrogate, nChar);
332 : : else
333 : : {
334 : 0 : bUndefined = false;
335 : 0 : goto bad_input;
336 : : }
337 : :
338 [ # # ][ # # ]: 0 : if (ImplIsLowSurrogate(nChar) || ImplIsNoncharacter(nChar))
[ # # ]
339 : : {
340 : 0 : bUndefined = false;
341 : 0 : goto bad_input;
342 : : }
343 : :
344 [ # # ]: 0 : if (nChar < 0x80)
345 [ # # ]: 0 : if (pDestBufPtr != pDestBufEnd)
346 : 0 : *pDestBufPtr++ = static_cast< char >(nChar);
347 : : else
348 : 0 : goto no_output;
349 [ # # ]: 0 : else if (nChar < 0x10000)
350 : : {
351 : 0 : ImplUnicodeToGb180302000Range const * pRange = pGb18030Ranges;
352 : 0 : sal_Unicode nFirstNonRange = 0x80;
353 : 0 : for (;;)
354 : : {
355 [ # # ]: 0 : if (nChar < pRange->m_nFirstUnicode)
356 : : {
357 : : sal_uInt32 nCode
358 : : = pGb18030Data[pRange->m_nNonRangeDataIndex
359 : 0 : + (nChar - nFirstNonRange)];
360 [ # # ][ # # ]: 0 : if (pDestBufEnd - pDestBufPtr
361 : : >= (nCode <= 0xFFFF ? 2 : 4))
362 : : {
363 [ # # ]: 0 : if (nCode > 0xFFFF)
364 : : {
365 : 0 : *pDestBufPtr++ = static_cast< char >(nCode >> 24);
366 : 0 : *pDestBufPtr++ = static_cast< char >(nCode >> 16 & 0xFF);
367 : : }
368 : 0 : *pDestBufPtr++ = static_cast< char >(nCode >> 8 & 0xFF);
369 : 0 : *pDestBufPtr++ = static_cast< char >(nCode & 0xFF);
370 : : }
371 : : else
372 : 0 : goto no_output;
373 : 0 : break;
374 : : }
375 [ # # ]: 0 : else if (nChar <= pRange->m_nLastUnicode)
376 : : {
377 [ # # ]: 0 : if (pDestBufEnd - pDestBufPtr >= 4)
378 : : {
379 : : sal_uInt32 nCode
380 : : = pRange->m_nFirstLinear
381 : 0 : + (nChar - pRange->m_nFirstUnicode);
382 : 0 : *pDestBufPtr++ = static_cast< char >(nCode / 12600 + 0x81);
383 : : *pDestBufPtr++
384 : 0 : = static_cast< char >(nCode / 1260 % 10 + 0x30);
385 : 0 : *pDestBufPtr++ = static_cast< char >(nCode / 10 % 126 + 0x81);
386 : 0 : *pDestBufPtr++ = static_cast< char >(nCode % 10 + 0x30);
387 : : }
388 : : else
389 : 0 : goto no_output;
390 : 0 : break;
391 : : }
392 : : nFirstNonRange
393 : 0 : = (sal_Unicode) ((pRange++)->m_nLastUnicode + 1);
394 : : }
395 : : }
396 : : else
397 [ # # ]: 0 : if (pDestBufEnd - pDestBufPtr >= 4)
398 : : {
399 : 0 : sal_uInt32 nCode = nChar - 0x10000;
400 : 0 : *pDestBufPtr++ = static_cast< char >(nCode / 12600 + 0x90);
401 : 0 : *pDestBufPtr++ = static_cast< char >(nCode / 1260 % 10 + 0x30);
402 : 0 : *pDestBufPtr++ = static_cast< char >(nCode / 10 % 126 + 0x81);
403 : 0 : *pDestBufPtr++ = static_cast< char >(nCode % 10 + 0x30);
404 : : }
405 : : else
406 : 0 : goto no_output;
407 : 0 : nHighSurrogate = 0;
408 : 0 : continue;
409 : :
410 : : bad_input:
411 [ # # # # ]: 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
412 : : bUndefined, nChar, nFlags, &pDestBufPtr, pDestBufEnd,
413 [ # # ]: 0 : &nInfo, NULL, 0, NULL))
414 : : {
415 : : case sal::detail::textenc::BAD_INPUT_STOP:
416 : 0 : nHighSurrogate = 0;
417 : 0 : break;
418 : :
419 : : case sal::detail::textenc::BAD_INPUT_CONTINUE:
420 : 0 : nHighSurrogate = 0;
421 : 0 : continue;
422 : :
423 : : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
424 : 0 : goto no_output;
425 : : }
426 : 0 : break;
427 : :
428 : : no_output:
429 : 0 : --pSrcBuf;
430 : 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
431 : 0 : break;
432 : : }
433 : :
434 [ # # ][ # # ]: 0 : if (nHighSurrogate != 0
435 : : && (nInfo & (RTL_UNICODETOTEXT_INFO_ERROR
436 : : | RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
437 : : == 0)
438 : : {
439 [ # # ]: 0 : if ((nFlags & RTL_UNICODETOTEXT_FLAGS_FLUSH) != 0)
440 : 0 : nInfo |= RTL_UNICODETOTEXT_INFO_SRCBUFFERTOSMALL;
441 : : else
442 [ # # # ]: 0 : switch (sal::detail::textenc::handleBadInputUnicodeToTextConversion(
443 : : false, 0, nFlags, &pDestBufPtr, pDestBufEnd, &nInfo,
444 [ # # ]: 0 : NULL, 0, NULL))
445 : : {
446 : : case sal::detail::textenc::BAD_INPUT_STOP:
447 : : case sal::detail::textenc::BAD_INPUT_CONTINUE:
448 : 0 : nHighSurrogate = 0;
449 : 0 : break;
450 : :
451 : : case sal::detail::textenc::BAD_INPUT_NO_OUTPUT:
452 : 0 : nInfo |= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL;
453 : 0 : break;
454 : : }
455 : : }
456 : :
457 [ # # ]: 0 : if (pContext)
458 : : ((ImplUnicodeToTextContext *) pContext)->m_nHighSurrogate
459 : 0 : = nHighSurrogate;
460 [ # # ]: 0 : if (pInfo)
461 : 0 : *pInfo = nInfo;
462 [ # # ]: 0 : if (pSrcCvtChars)
463 : 0 : *pSrcCvtChars = nConverted;
464 : :
465 : 0 : return pDestBufPtr - pDestBuf;
466 : : }
467 : :
468 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|