Branch data 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 : :
21 : : #include "transliterationImpl.hxx"
22 : : #include "servicename.hxx"
23 : :
24 : : #include <com/sun/star/i18n/TransliterationType.hpp>
25 : : #include <com/sun/star/lang/XComponent.hpp>
26 : :
27 : : #include <comphelper/processfactory.hxx>
28 : : #include <rtl/instance.hxx>
29 : : #include <rtl/string.h>
30 : : #include <rtl/ustring.hxx>
31 : : #include <rtl/ustrbuf.hxx>
32 : :
33 : : #include <algorithm>
34 : :
35 : : #if OSL_DEBUG_LEVEL > 1
36 : : #include <stdio.h>
37 : : #endif
38 : :
39 : : using namespace com::sun::star::uno;
40 : : using namespace com::sun::star::lang;
41 : :
42 : : using ::rtl::OUString;
43 : :
44 : : namespace com { namespace sun { namespace star { namespace i18n {
45 : :
46 : : #define ERROR RuntimeException()
47 : :
48 : : #define TmItem1( name ) \
49 : : {TransliterationModules_##name, TransliterationModulesNew_##name, #name}
50 : :
51 : : #define TmItem2( name ) \
52 : : {(TransliterationModules)0, TransliterationModulesNew_##name, #name}
53 : :
54 : : // Ignore Module list
55 : : static struct TMlist {
56 : : TransliterationModules tm;
57 : : TransliterationModulesNew tmn;
58 : : const sal_Char *implName;
59 : : } TMlist[] = { // Modules ModulesNew
60 : : TmItem1 (IGNORE_CASE), // 0. (1<<8 256) (7)
61 : : TmItem1 (IGNORE_WIDTH), // 1. (1<<9 512) (8)
62 : : TmItem1 (IGNORE_KANA), // 2. (1<<10 1024) (9)
63 : : // No enum define for this trans. application has to use impl name to load it
64 : : // TmItem1 (IGNORE_CASE_SIMPLE), // (1<<11 1024) (66)
65 : :
66 : : TmItem1 (ignoreTraditionalKanji_ja_JP), // 3. (1<<12 4096) (10)
67 : : TmItem1 (ignoreTraditionalKana_ja_JP), // 4. (1<<13 8192) (11)
68 : : TmItem1 (ignoreMinusSign_ja_JP), // 5. (1<<13 16384) (12)
69 : : TmItem1 (ignoreIterationMark_ja_JP), // 6. (1<<14 32768) (13)
70 : : TmItem1 (ignoreSeparator_ja_JP), // 7. (1<<15 65536) (14)
71 : : TmItem1 (ignoreSize_ja_JP), // 15. (1<<23 16777216) (22)
72 : : TmItem1 (ignoreMiddleDot_ja_JP), // 17. (1<<25 67108864) (24)
73 : : TmItem1 (ignoreSpace_ja_JP), // 18. (1<<26 134217728) (25)
74 : : TmItem1 (ignoreZiZu_ja_JP), // 8. (1<<16 131072) (15)
75 : : TmItem1 (ignoreBaFa_ja_JP), // 9. (1<<17 262144) (16)
76 : : TmItem1 (ignoreTiJi_ja_JP), // 10. (1<<18 524288) (17)
77 : : TmItem1 (ignoreHyuByu_ja_JP), // 11. (1<<19 1048576) (18)
78 : : TmItem1 (ignoreSeZe_ja_JP), // 12. (1<<20 2097152) (19)
79 : : TmItem1 (ignoreIandEfollowedByYa_ja_JP), // 13. (1<<21 4194304) (20)
80 : : TmItem1 (ignoreKiKuFollowedBySa_ja_JP), // 14. (1<<22 8388608) (21)
81 : : TmItem1 (ignoreProlongedSoundMark_ja_JP), // 16. (1<<24 33554432) (23)
82 : :
83 : : TmItem1 (UPPERCASE_LOWERCASE), // 19. (1) (1)
84 : : TmItem1 (LOWERCASE_UPPERCASE), // 20. (2) (2)
85 : : TmItem1 (HALFWIDTH_FULLWIDTH), // 21. (3) (3)
86 : : TmItem1 (FULLWIDTH_HALFWIDTH), // 22. (4) (4)
87 : : TmItem1 (KATAKANA_HIRAGANA), // 23. (5) (5)
88 : : TmItem1 (HIRAGANA_KATAKANA), // 24. (6) (6)
89 : :
90 : : TmItem1 (smallToLarge_ja_JP), // 25. (1<<27 268435456) (26)
91 : : TmItem1 (largeToSmall_ja_JP), // 26. (1<<28 536870912) (27)
92 : : TmItem2 (NumToTextLower_zh_CN), // 27. () (28)
93 : : TmItem2 (NumToTextUpper_zh_CN), // 28. () (29)
94 : : TmItem2 (NumToTextLower_zh_TW), // 29. () (30)
95 : : TmItem2 (NumToTextUpper_zh_TW), // 30. () (31)
96 : : TmItem2 (NumToTextFormalHangul_ko), // 31. () (32)
97 : : TmItem2 (NumToTextFormalLower_ko), // 32. () (33)
98 : : TmItem2 (NumToTextFormalUpper_ko), // 33. () (34)
99 : : TmItem2 (NumToTextInformalHangul_ko), // 34. () (35)
100 : : TmItem2 (NumToTextInformalLower_ko), // 35. () (36)
101 : : TmItem2 (NumToTextInformalUpper_ko), // 36. () (37)
102 : : TmItem2 (NumToCharLower_zh_CN), // 37. () (38)
103 : : TmItem2 (NumToCharUpper_zh_CN), // 38. () (39)
104 : : TmItem2 (NumToCharLower_zh_TW), // 39. () (40)
105 : : TmItem2 (NumToCharUpper_zh_TW), // 40. () (41)
106 : : TmItem2 (NumToCharHangul_ko), // 41. () (42)
107 : : TmItem2 (NumToCharLower_ko), // 42. () (43)
108 : : TmItem2 (NumToCharUpper_ko), // 43. () (44)
109 : : TmItem2 (NumToCharFullwidth), // 44. () (45)
110 : : TmItem2 (NumToCharKanjiShort_ja_JP), // 45. () (46)
111 : : TmItem2 (TextToNumLower_zh_CN), // 46. () (47)
112 : : TmItem2 (TextToNumUpper_zh_CN), // 47. () (48)
113 : : TmItem2 (TextToNumLower_zh_TW), // 48. () (49)
114 : : TmItem2 (TextToNumUpper_zh_TW), // 49. () (50)
115 : : TmItem2 (TextToNumFormalHangul_ko), // 50. () (51)
116 : : TmItem2 (TextToNumFormalLower_ko), // 51. () (52)
117 : : TmItem2 (TextToNumFormalUpper_ko), // 52. () (53)
118 : : TmItem2 (TextToNumInformalHangul_ko), // 53. () (54)
119 : : TmItem2 (TextToNumInformalLower_ko), // 54. () (55)
120 : : TmItem2 (TextToNumInformalUpper_ko), // 55. () (56)
121 : :
122 : : TmItem2 (CharToNumLower_zh_CN), // 56. () (59)
123 : : TmItem2 (CharToNumUpper_zh_CN), // 57. () (60)
124 : : TmItem2 (CharToNumLower_zh_TW), // 58. () (61)
125 : : TmItem2 (CharToNumUpper_zh_TW), // 59. () (62)
126 : : TmItem2 (CharToNumHangul_ko), // 60. () (63)
127 : : TmItem2 (CharToNumLower_ko), // 61. () (64)
128 : : TmItem2 (CharToNumUpper_ko), // 62. () (65)
129 : :
130 : : // no enum defined for these trans. application has to use impl name to load them
131 : : // TmItem2 (NumToCharArabic_Indic), // () (67)
132 : : // TmItem2 (NumToCharEstern_Arabic_Indic),// () (68)
133 : : // TmItem2 (NumToCharIndic), // () (69)
134 : : // TmItem2 (NumToCharThai), // () (70)
135 : : {(TransliterationModules)0, (TransliterationModulesNew)0, NULL}
136 : : };
137 : :
138 : : // Constructor/Destructor
139 [ + + ]: 10220 : TransliterationImpl::TransliterationImpl(const Reference <XMultiServiceFactory>& xMSF) : xSMgr(xMSF)
140 : : {
141 : 365 : numCascade = 0;
142 : 365 : caseignoreOnly = sal_True;
143 : :
144 [ + - ]: 365 : if ( xMSF.is() )
145 : : {
146 : : Reference < XInterface > xI=
147 [ + - ][ + - ]: 365 : xMSF->createInstance(OUString("com.sun.star.i18n.LocaleData"));
148 [ + - ]: 365 : if ( xI.is() ) {
149 [ + - ][ + - ]: 365 : Any x = xI->queryInterface( ::getCppuType( (const uno::Reference< i18n::XLocaleData >*)0) );
[ + - ]
150 [ + - ]: 365 : x >>= localedata;
151 : 365 : }
152 : : }
153 [ # # # # ]: 365 : }
154 : :
155 : 7685 : TransliterationImpl::~TransliterationImpl()
156 : : {
157 : 265 : localedata.clear();
158 [ + - ]: 265 : clear();
159 [ + - ]: 7950 : }
[ + + - + ]
[ # # # # ]
160 : :
161 : :
162 : : // Methods
163 : : OUString SAL_CALL
164 : 0 : TransliterationImpl::getName() throw(RuntimeException)
165 : : {
166 [ # # ][ # # ]: 0 : if (numCascade == 1 && bodyCascade[0].is())
[ # # ]
167 : 0 : return bodyCascade[0]->getName();
168 [ # # ]: 0 : if (numCascade < 1)
169 : 0 : return ( OUString("Not Loaded"));
170 [ # # ]: 0 : throw ERROR;
171 : : }
172 : :
173 : : sal_Int16 SAL_CALL
174 : 0 : TransliterationImpl::getType() throw(RuntimeException)
175 : : {
176 [ # # ]: 0 : if (numCascade > 1)
177 : 0 : return (TransliterationType::CASCADE|TransliterationType::IGNORE);
178 [ # # ][ # # ]: 0 : if (numCascade > 0 && bodyCascade[0].is())
[ # # ]
179 : 0 : return(bodyCascade[0]->getType());
180 [ # # ]: 0 : throw ERROR;
181 : : }
182 : :
183 : : void SAL_CALL
184 : 381 : TransliterationImpl::loadModule( TransliterationModules modType, const Locale& rLocale )
185 : : throw(RuntimeException)
186 : : {
187 : 381 : clear();
188 [ - + ][ + + ]: 381 : if (modType&TransliterationModules_IGNORE_MASK && modType&TransliterationModules_NON_IGNORE_MASK) {
189 [ # # ]: 0 : throw ERROR;
190 [ + + ]: 381 : } else if (modType&TransliterationModules_IGNORE_MASK) {
191 : : #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \
192 : : TransliterationModules_IGNORE_WIDTH | \
193 : : TransliterationModules_IGNORE_KANA)
194 : : sal_Int32 mask = ((modType&TransliterationModules_IGNORE_CASE_MASK) == modType) ?
195 [ + - ]: 375 : TransliterationModules_IGNORE_CASE_MASK : TransliterationModules_IGNORE_MASK;
196 [ + + ]: 1500 : for (sal_Int16 i = 0; TMlist[i].tm & mask; i++) {
197 [ + + ]: 1125 : if (modType & TMlist[i].tm)
198 [ + - ]: 565 : if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName),
199 [ + - ]: 565 : bodyCascade[numCascade], rLocale))
200 : 565 : numCascade++;
201 : : }
202 [ + - ]: 6 : } else if (modType&TransliterationModules_NON_IGNORE_MASK) {
203 [ + - ]: 132 : for (sal_Int16 i = 0; TMlist[i].tm; i++) {
204 [ + + ]: 126 : if (TMlist[i].tm == modType) {
205 [ + - ][ + - ]: 6 : if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), bodyCascade[numCascade], rLocale))
206 : 6 : numCascade++;
207 : 6 : break;
208 : : }
209 : : }
210 : : }
211 : 381 : }
212 : :
213 : : void SAL_CALL
214 : 0 : TransliterationImpl::loadModuleNew( const Sequence < TransliterationModulesNew > & modType, const Locale& rLocale )
215 : : throw(RuntimeException)
216 : : {
217 : 0 : clear();
218 : 0 : sal_Int32 mask = 0, count = modType.getLength();
219 [ # # ]: 0 : if (count > maxCascade)
220 [ # # ]: 0 : throw ERROR; // could not handle more than maxCascade
221 [ # # ]: 0 : for (sal_Int16 i = 0; i < count; i++) {
222 [ # # ]: 0 : for (sal_Int16 j = 0; TMlist[j].tmn; j++) {
223 [ # # ]: 0 : if (TMlist[j].tmn == modType[i]) {
224 [ # # ]: 0 : if (mask == 0)
225 : : mask = TMlist[i].tm && (TMlist[i].tm&TransliterationModules_IGNORE_MASK) ?
226 [ # # ][ # # ]: 0 : TransliterationModules_IGNORE_MASK : TransliterationModules_NON_IGNORE_MASK;
227 [ # # ][ # # ]: 0 : else if (mask == TransliterationModules_IGNORE_MASK &&
228 : : (TMlist[i].tm&TransliterationModules_IGNORE_MASK) == 0)
229 [ # # ]: 0 : throw ERROR; // could not mess up ignore trans. with non_ignore trans.
230 [ # # ][ # # ]: 0 : if (loadModuleByName(OUString::createFromAscii(TMlist[j].implName), bodyCascade[numCascade], rLocale))
231 : 0 : numCascade++;
232 : 0 : break;
233 : : }
234 : : }
235 : : }
236 : 0 : }
237 : :
238 : : void SAL_CALL
239 : 0 : TransliterationImpl::loadModuleByImplName(const OUString& implName, const Locale& rLocale)
240 : : throw(RuntimeException)
241 : : {
242 : 0 : clear();
243 [ # # ]: 0 : if (loadModuleByName(implName, bodyCascade[numCascade], rLocale))
244 : 0 : numCascade++;
245 : 0 : }
246 : :
247 : :
248 : : void SAL_CALL
249 : 0 : TransliterationImpl::loadModulesByImplNames(const Sequence< OUString >& implNameList, const Locale& rLocale ) throw(RuntimeException)
250 : : {
251 [ # # ][ # # ]: 0 : if (implNameList.getLength() > maxCascade || implNameList.getLength() <= 0)
[ # # ]
252 [ # # ]: 0 : throw ERROR;
253 : :
254 : 0 : clear();
255 [ # # ]: 0 : for (sal_Int32 i = 0; i < implNameList.getLength(); i++)
256 [ # # ]: 0 : if (loadModuleByName(implNameList[i], bodyCascade[numCascade], rLocale))
257 : 0 : numCascade++;
258 : 0 : }
259 : :
260 : :
261 : : Sequence<OUString> SAL_CALL
262 : 0 : TransliterationImpl::getAvailableModules( const Locale& rLocale, sal_Int16 sType ) throw(RuntimeException)
263 : : {
264 [ # # ][ # # ]: 0 : const Sequence<OUString> &translist = localedata->getTransliterations(rLocale);
265 [ # # ]: 0 : Sequence<OUString> r(translist.getLength());
266 : 0 : Reference<XExtendedTransliteration> body;
267 : 0 : sal_Int32 n = 0;
268 [ # # ]: 0 : for (sal_Int32 i = 0; i < translist.getLength(); i++)
269 : : {
270 [ # # ][ # # ]: 0 : if (loadModuleByName(translist[i], body, rLocale)) {
271 [ # # ][ # # ]: 0 : if (body->getType() & sType)
[ # # ]
272 [ # # ]: 0 : r[n++] = translist[i];
273 : 0 : body.clear();
274 : : }
275 : : }
276 [ # # ]: 0 : r.realloc(n);
277 [ # # ]: 0 : return (r);
278 : : }
279 : :
280 : :
281 : : OUString SAL_CALL
282 : 705 : TransliterationImpl::transliterate( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
283 : : Sequence< sal_Int32 >& offset ) throw(RuntimeException)
284 : : {
285 [ - + ]: 705 : if (numCascade == 0)
286 : 0 : return inStr;
287 : :
288 [ + + ]: 705 : if (offset.getLength() != nCount)
289 : 57 : offset.realloc(nCount);
290 [ + - ]: 705 : if (numCascade == 1)
291 : : {
292 [ + - ][ + - ]: 705 : if ( startPos == 0 && nCount == inStr.getLength() )
[ + - ]
293 : 705 : return bodyCascade[0]->transliterate( inStr, 0, nCount, offset);
294 : : else
295 : : {
296 : 0 : OUString tmpStr = inStr.copy(startPos, nCount);
297 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[0]->transliterate(tmpStr, 0, nCount, offset);
298 [ # # ]: 0 : if ( startPos )
299 : : {
300 [ # # ]: 0 : sal_Int32 * pArr = offset.getArray();
301 : 0 : nCount = offset.getLength();
302 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
303 : 0 : pArr[j] += startPos;
304 : : }
305 : 0 : return tmpStr;
306 : : }
307 : : }
308 : : else
309 : : {
310 : 0 : OUString tmpStr = inStr.copy(startPos, nCount);
311 [ # # ]: 0 : sal_Int32 * pArr = offset.getArray();
312 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
313 : 0 : pArr[j] = startPos + j;
314 : :
315 : 0 : sal_Int16 from = 0, to = 1, tmp;
316 [ # # ][ # # ]: 0 : Sequence<sal_Int32> off[2];
[ # # # #
# # ]
317 : :
318 [ # # ]: 0 : off[to] = offset;
319 [ # # ]: 0 : off[from].realloc(nCount);
320 [ # # ]: 0 : for (sal_Int32 i = 0; i < numCascade; i++) {
321 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[i]->transliterate(tmpStr, 0, nCount, off[from]);
322 : :
323 : 0 : nCount = tmpStr.getLength();
324 : :
325 : 0 : tmp = from; from = to; to = tmp;
326 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
327 [ # # ][ # # ]: 0 : off[to][j] = off[from][off[to][j]];
[ # # ]
328 : : }
329 [ # # ]: 0 : offset = off[to];
330 [ # # ][ # # ]: 705 : return tmpStr;
331 : : }
332 : : }
333 : :
334 : :
335 : : //
336 : : OUString SAL_CALL
337 : 0 : TransliterationImpl::folding( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
338 : : Sequence< sal_Int32 >& offset ) throw(RuntimeException)
339 : : {
340 [ # # ]: 0 : if (numCascade == 0)
341 : 0 : return inStr;
342 : :
343 [ # # ]: 0 : if (offset.getLength() != nCount)
344 : 0 : offset.realloc(nCount);
345 [ # # ]: 0 : if (numCascade == 1)
346 : : {
347 [ # # ][ # # ]: 0 : if ( startPos == 0 && nCount == inStr.getLength() )
[ # # ]
348 : 0 : return bodyCascade[0]->folding( inStr, 0, nCount, offset);
349 : : else
350 : : {
351 : 0 : OUString tmpStr = inStr.copy(startPos, nCount);
352 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[0]->folding(tmpStr, 0, nCount, offset);
353 [ # # ]: 0 : if ( startPos )
354 : : {
355 [ # # ]: 0 : sal_Int32 * pArr = offset.getArray();
356 : 0 : nCount = offset.getLength();
357 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
358 : 0 : pArr[j] += startPos;
359 : : }
360 : 0 : return tmpStr;
361 : : }
362 : : }
363 : : else
364 : : {
365 : 0 : OUString tmpStr = inStr.copy(startPos, nCount);
366 [ # # ]: 0 : sal_Int32 * pArr = offset.getArray();
367 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
368 : 0 : pArr[j] = startPos + j;
369 : :
370 : 0 : sal_Int16 from = 0, to = 1, tmp;
371 [ # # ][ # # ]: 0 : Sequence<sal_Int32> off[2];
[ # # # #
# # ]
372 : :
373 [ # # ]: 0 : off[to] = offset;
374 [ # # ]: 0 : for (sal_Int32 i = 0; i < numCascade; i++) {
375 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[i]->folding(tmpStr, 0, nCount, off[from]);
376 : :
377 : 0 : nCount = tmpStr.getLength();
378 : :
379 : 0 : tmp = from; from = to; to = tmp;
380 [ # # ]: 0 : for (sal_Int32 j = 0; j < nCount; j++)
381 [ # # ][ # # ]: 0 : off[to][j] = off[from][off[to][j]];
[ # # ]
382 : : }
383 [ # # ]: 0 : offset = off[to];
384 [ # # ][ # # ]: 0 : return tmpStr;
385 : : }
386 : : }
387 : :
388 : : OUString SAL_CALL
389 : 61 : TransliterationImpl::transliterateString2String( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount ) throw(RuntimeException)
390 : : {
391 [ - + ]: 61 : if (numCascade == 0)
392 : 0 : return inStr;
393 [ + - ]: 61 : else if (numCascade == 1)
394 : 61 : return bodyCascade[0]->transliterateString2String( inStr, startPos, nCount);
395 : : else {
396 [ # # ][ # # ]: 0 : OUString tmpStr = bodyCascade[0]->transliterateString2String(inStr, startPos, nCount);
397 : :
398 [ # # ]: 0 : for (sal_Int32 i = 1; i < numCascade; i++)
399 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
400 : 61 : return tmpStr;
401 : : }
402 : : }
403 : :
404 : : OUString SAL_CALL
405 : 0 : TransliterationImpl::transliterateChar2String( sal_Unicode inChar ) throw(RuntimeException)
406 : : {
407 [ # # ]: 0 : if (numCascade == 0)
408 : 0 : return OUString(&inChar, 1);
409 [ # # ]: 0 : else if (numCascade == 1)
410 : 0 : return bodyCascade[0]->transliterateChar2String( inChar);
411 : : else {
412 [ # # ][ # # ]: 0 : OUString tmpStr = bodyCascade[0]->transliterateChar2String(inChar);
413 : :
414 [ # # ]: 0 : for (sal_Int32 i = 1; i < numCascade; i++)
415 [ # # ][ # # ]: 0 : tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
416 : 0 : return tmpStr;
417 : : }
418 : : }
419 : :
420 : : sal_Unicode SAL_CALL
421 : 0 : TransliterationImpl::transliterateChar2Char( sal_Unicode inChar ) throw(MultipleCharsOutputException, RuntimeException)
422 : : {
423 : 0 : sal_Unicode tmpChar = inChar;
424 [ # # ]: 0 : for (sal_Int32 i = 0; i < numCascade; i++)
425 : 0 : tmpChar = bodyCascade[i]->transliterateChar2Char(tmpChar);
426 : 0 : return tmpChar;
427 : : }
428 : :
429 : :
430 : : sal_Bool SAL_CALL
431 : 8219 : TransliterationImpl::equals(
432 : : const OUString& str1, sal_Int32 pos1, sal_Int32 nCount1, sal_Int32& nMatch1,
433 : : const OUString& str2, sal_Int32 pos2, sal_Int32 nCount2, sal_Int32& nMatch2)
434 : : throw(RuntimeException)
435 : : {
436 : : // since this is an API function make it user fail safe
437 [ - + ]: 8219 : if ( nCount1 < 0 ) {
438 : 0 : pos1 += nCount1;
439 : 0 : nCount1 = -nCount1;
440 : : }
441 [ - + ]: 8219 : if ( nCount2 < 0 ) {
442 : 0 : pos2 += nCount2;
443 : 0 : nCount2 = -nCount2;
444 : : }
445 [ + + ][ + + : 21501 : if ( !nCount1 || !nCount2 ||
+ - + - ]
[ + - ][ - + ]
[ + + ]
446 : 13282 : pos1 >= str1.getLength() || pos2 >= str2.getLength() ||
447 : : pos1 < 0 || pos2 < 0 ) {
448 : 1578 : nMatch1 = nMatch2 = 0;
449 : : // two empty strings return true, else false
450 [ + + ][ + + ]: 1578 : return !nCount1 && !nCount2 && pos1 == str1.getLength() && pos2 == str2.getLength();
[ + - ][ + - ]
451 : : }
452 [ - + ]: 6641 : if ( pos1 + nCount1 > str1.getLength() )
453 : 0 : nCount1 = str1.getLength() - pos1;
454 [ - + ]: 6641 : if ( pos2 + nCount2 > str2.getLength() )
455 : 0 : nCount2 = str2.getLength() - pos2;
456 : :
457 [ + - ][ + - ]: 6641 : if (caseignoreOnly && caseignore.is())
[ + - ]
458 [ + - ][ + - ]: 6641 : return caseignore->equals(str1, pos1, nCount1, nMatch1, str2, pos2, nCount2, nMatch2);
459 : :
460 [ # # ][ # # ]: 0 : Sequence<sal_Int32> offset1, offset2;
461 : :
462 [ # # ]: 0 : OUString tmpStr1 = folding(str1, pos1, nCount1, offset1);
463 [ # # ]: 0 : OUString tmpStr2 = folding(str2, pos2, nCount2, offset2);
464 : : // Length of offset1 and offset2 may still be 0 if there was no folding
465 : : // necessary!
466 : :
467 : 0 : const sal_Unicode *p1 = tmpStr1.getStr();
468 : 0 : const sal_Unicode *p2 = tmpStr2.getStr();
469 [ # # ]: 0 : sal_Int32 i, nLen = ::std::min( tmpStr1.getLength(), tmpStr2.getLength());
470 [ # # ]: 0 : for (i = 0; i < nLen; ++i, ++p1, ++p2 ) {
471 [ # # ]: 0 : if (*p1 != *p2) {
472 : : // return number of matched code points so far
473 [ # # ][ # # ]: 0 : nMatch1 = (i < offset1.getLength()) ? offset1[i] : i;
474 [ # # ][ # # ]: 0 : nMatch2 = (i < offset2.getLength()) ? offset2[i] : i;
475 : 0 : return sal_False;
476 : : }
477 : : }
478 : : // i==nLen
479 [ # # ]: 0 : if ( tmpStr1.getLength() != tmpStr2.getLength() ) {
480 : : // return number of matched code points so far
481 [ # # ][ # # ]: 0 : nMatch1 = (i <= offset1.getLength()) ? offset1[i-1] + 1 : i;
482 [ # # ][ # # ]: 0 : nMatch2 = (i <= offset2.getLength()) ? offset2[i-1] + 1 : i;
483 : 0 : return sal_False;
484 : : } else {
485 : 0 : nMatch1 = nCount1;
486 : 0 : nMatch2 = nCount2;
487 : 0 : return sal_True;
488 [ # # ][ # # ]: 8219 : }
489 : : }
490 : :
491 : : #define MaxOutput 2
492 : :
493 : : Sequence< OUString > SAL_CALL
494 : 0 : TransliterationImpl::getRange(const Sequence< OUString > &inStrs,
495 : : const sal_Int32 length, sal_Int16 _numCascade) throw(RuntimeException)
496 : : {
497 [ # # ][ # # ]: 0 : if (_numCascade >= numCascade || ! bodyCascade[_numCascade].is())
[ # # ]
498 [ # # ]: 0 : return inStrs;
499 : :
500 : 0 : sal_Int32 j_tmp = 0;
501 [ # # ]: 0 : Sequence< OUString > ostr(MaxOutput*length);
502 [ # # ]: 0 : for (sal_Int32 j = 0; j < length; j+=2) {
503 [ # # ][ # # ]: 0 : const Sequence< OUString >& temp = bodyCascade[_numCascade]->transliterateRange(inStrs[j], inStrs[j+1]);
504 : :
505 [ # # ]: 0 : for ( sal_Int32 k = 0; k < temp.getLength(); k++) {
506 [ # # ][ # # ]: 0 : if ( j_tmp >= MaxOutput*length ) throw ERROR;
507 [ # # ]: 0 : ostr[j_tmp++] = temp[k];
508 : : }
509 [ # # ]: 0 : }
510 [ # # ]: 0 : ostr.realloc(j_tmp);
511 : :
512 [ # # ][ # # ]: 0 : return this->getRange(ostr, j_tmp, ++_numCascade);
513 : : }
514 : :
515 : :
516 : : Sequence< OUString > SAL_CALL
517 : 0 : TransliterationImpl::transliterateRange( const OUString& str1, const OUString& str2 )
518 : : throw(RuntimeException)
519 : : {
520 [ # # ]: 0 : if (numCascade == 1)
521 [ # # ][ # # ]: 0 : return bodyCascade[0]->transliterateRange(str1, str2);
522 : :
523 [ # # ]: 0 : Sequence< OUString > ostr(2);
524 [ # # ]: 0 : ostr[0] = str1;
525 [ # # ]: 0 : ostr[1] = str2;
526 : :
527 [ # # ][ # # ]: 0 : return this->getRange(ostr, 2, 0);
528 : : }
529 : :
530 : :
531 : : sal_Int32 SAL_CALL
532 : 0 : TransliterationImpl::compareSubstring(
533 : : const OUString& str1, sal_Int32 off1, sal_Int32 len1,
534 : : const OUString& str2, sal_Int32 off2, sal_Int32 len2)
535 : : throw(RuntimeException)
536 : : {
537 [ # # ][ # # ]: 0 : if (caseignoreOnly && caseignore.is())
[ # # ]
538 [ # # ][ # # ]: 0 : return caseignore->compareSubstring(str1, off1, len1, str2, off2, len2);
539 : :
540 [ # # ]: 0 : Sequence <sal_Int32> offset;
541 : :
542 [ # # ]: 0 : OUString in_str1 = this->transliterate(str1, off1, len1, offset);
543 [ # # ]: 0 : OUString in_str2 = this->transliterate(str2, off2, len2, offset);
544 : 0 : const sal_Unicode* unistr1 = in_str1.getStr();
545 : 0 : const sal_Unicode* unistr2 = in_str2.getStr();
546 : 0 : sal_Int32 strlen1 = in_str1.getLength();
547 : 0 : sal_Int32 strlen2 = in_str2.getLength();
548 : :
549 [ # # ][ # # ]: 0 : while (strlen1 && strlen2) {
[ # # ]
550 [ # # ]: 0 : if (*unistr1 != *unistr2)
551 [ # # ]: 0 : return *unistr1 > *unistr2 ? 1 : -1;
552 : :
553 : 0 : unistr1++; unistr2++; strlen1--; strlen2--;
554 : : }
555 [ # # ][ # # ]: 0 : return strlen1 == strlen2 ? 0 : (strlen1 > strlen2 ? 1 : -1);
[ # # ]
556 : : }
557 : :
558 : :
559 : : sal_Int32 SAL_CALL
560 : 143 : TransliterationImpl::compareString(const OUString& str1, const OUString& str2 ) throw (RuntimeException)
561 : : {
562 [ + - ][ + - ]: 143 : if (caseignoreOnly && caseignore.is())
[ + - ]
563 : 143 : return caseignore->compareString(str1, str2);
564 : : else
565 : 143 : return this->compareSubstring(str1, 0, str1.getLength(), str2, 0, str2.getLength());
566 : : }
567 : :
568 : :
569 : : void
570 : 646 : TransliterationImpl::clear()
571 : : {
572 [ + + ]: 1091 : for (sal_Int32 i = 0; i < numCascade; i++)
573 [ + - ]: 445 : if (bodyCascade[i].is())
574 : 445 : bodyCascade[i].clear();
575 : 646 : numCascade = 0;
576 : 646 : caseignore.clear();
577 : 646 : caseignoreOnly = sal_True;
578 : 646 : }
579 : :
580 : : namespace
581 : : {
582 : : /** structure to cache the last transliteration body used. */
583 : 228 : struct TransBody
584 : : {
585 : : ::rtl::OUString Name;
586 : : ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XExtendedTransliteration > Body;
587 : : };
588 : : class theTransBodyMutex : public rtl::Static<osl::Mutex, theTransBodyMutex> {};
589 : : }
590 : :
591 : 946 : void TransliterationImpl::loadBody( OUString &implName, Reference<XExtendedTransliteration>& body )
592 : : throw (RuntimeException)
593 : : {
594 : : assert(!implName.isEmpty());
595 [ + - ][ + - ]: 946 : ::osl::MutexGuard guard(theTransBodyMutex::get());
596 [ + + ][ + - ]: 946 : static TransBody lastTransBody;
[ + - ][ # # ]
597 [ + + ]: 946 : if (implName != lastTransBody.Name)
598 : : {
599 : : lastTransBody.Body.set(
600 [ + - ][ + - ]: 361 : xSMgr->createInstance(implName), UNO_QUERY_THROW);
[ + - ]
601 : 361 : lastTransBody.Name = implName;
602 : : }
603 [ + - ][ + - ]: 946 : body = lastTransBody.Body;
604 : 946 : }
605 : :
606 : : sal_Bool SAL_CALL
607 : 571 : TransliterationImpl::loadModuleByName( const OUString& implName,
608 : : Reference<XExtendedTransliteration>& body, const Locale& rLocale) throw(RuntimeException)
609 : : {
610 : 571 : OUString cname = OUString(TRLT_IMPLNAME_PREFIX) + implName;
611 [ + - ]: 571 : loadBody(cname, body);
612 [ + - ]: 571 : if (body.is()) {
613 [ + - ][ + - ]: 571 : body->loadModule((TransliterationModules)0, rLocale); // toUpper/toLoad need rLocale
614 : :
615 : : // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed
616 [ + + ]: 846 : for (sal_Int16 i = 0; i < 3; i++) {
617 [ + + ]: 840 : if (implName.compareToAscii(TMlist[i].implName) == 0) {
618 [ + + ]: 565 : if (i == 0) // current module is caseignore
619 [ + - ][ + - ]: 375 : body->loadModule(TMlist[0].tm, rLocale); // caseingore need to setup module name
620 [ + + ]: 565 : if (! caseignore.is()) {
621 : : OUString bname = OUString(TRLT_IMPLNAME_PREFIX) +
622 : 375 : OUString::createFromAscii(TMlist[0].implName);
623 [ + - ]: 375 : loadBody(bname, caseignore);
624 : : }
625 [ + - ]: 565 : if (caseignore.is())
626 [ + - ][ + - ]: 565 : caseignore->loadModule(TMlist[i].tm, rLocale);
627 : 565 : return sal_True;
628 : : }
629 : : }
630 : 6 : caseignoreOnly = sal_False; // has other module than just ignore case/kana/width
631 : : }
632 : 571 : return body.is();
633 : : }
634 : :
635 : : const sal_Char cTrans[] = "com.sun.star.i18n.Transliteration";
636 : :
637 : : OUString SAL_CALL
638 : 0 : TransliterationImpl::getImplementationName() throw( RuntimeException )
639 : : {
640 : 0 : return OUString::createFromAscii(cTrans);
641 : : }
642 : :
643 : :
644 : : sal_Bool SAL_CALL
645 : 0 : TransliterationImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
646 : : {
647 : 0 : return !rServiceName.compareToAscii(cTrans);
648 : : }
649 : :
650 : : Sequence< OUString > SAL_CALL
651 : 0 : TransliterationImpl::getSupportedServiceNames(void) throw( RuntimeException )
652 : : {
653 : 0 : Sequence< OUString > aRet(1);
654 [ # # ]: 0 : aRet[0] = OUString::createFromAscii(cTrans);
655 : 0 : return aRet;
656 : : }
657 : :
658 : : } } } }
659 : :
660 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|