1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <transliterationImpl.hxx>
22 #include <servicename.hxx>
24 #include <com/sun/star/i18n/LocaleData2.hpp>
25 #include <com/sun/star/i18n/TransliterationType.hpp>
26 #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
28 #include <comphelper/sequence.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <o3tl/string_view.hxx>
31 #include <rtl/ustring.hxx>
37 using namespace com::sun::star::uno
;
38 using namespace com::sun::star::i18n
;
39 using namespace com::sun::star::lang
;
44 #define TmItem1( name ) \
45 {TransliterationModules_##name, TransliterationModulesNew_##name, #name}
47 #define TmItem2( name ) \
48 {TransliterationModules(0), TransliterationModulesNew_##name, #name}
54 TransliterationModules tm
;
55 TransliterationModulesNew tmn
;
61 TMList
const TMlist
[] = { // Modules ModulesNew
62 TmItem1 (IGNORE_CASE
), // 0. (1<<8 256) (7)
63 TmItem1 (IGNORE_WIDTH
), // 1. (1<<9 512) (8)
64 TmItem1 (IGNORE_KANA
), // 2. (1<<10 1024) (9)
65 // No enum define for this trans. application has to use impl name to load it
66 // TmItem1 (IGNORE_CASE_SIMPLE), // (1<<11 1024) (66)
68 {TransliterationModules_IgnoreTraditionalKanji_ja_JP
,
69 TransliterationModulesNew_IgnoreTraditionalKanji_ja_JP
, "ignoreTraditionalKanji_ja_JP"},
70 // 3. (1<<12 4096) (10)
71 {TransliterationModules_IgnoreTraditionalKana_ja_JP
,
72 TransliterationModulesNew_IgnoreTraditionalKana_ja_JP
, "ignoreTraditionalKana_ja_JP"},
73 // 4. (1<<13 8192) (11)
74 {TransliterationModules_IgnoreMinusSign_ja_JP
, TransliterationModulesNew_IgnoreMinusSign_ja_JP
,
75 "ignoreMinusSign_ja_JP"}, // 5. (1<<13 16384) (12)
76 {TransliterationModules_IgnoreIterationMark_ja_JP
,
77 TransliterationModulesNew_IgnoreIterationMark_ja_JP
, "ignoreIterationMark_ja_JP"},
78 // 6. (1<<14 32768) (13)
79 {TransliterationModules_IgnoreSeparator_ja_JP
, TransliterationModulesNew_IgnoreSeparator_ja_JP
,
80 "ignoreSeparator_ja_JP"}, // 7. (1<<15 65536) (14)
81 {TransliterationModules_IgnoreSize_ja_JP
, TransliterationModulesNew_IgnoreSize_ja_JP
,
82 "ignoreSize_ja_JP"}, // 15. (1<<23 16777216) (22)
83 {TransliterationModules_IgnoreMiddleDot_ja_JP
, TransliterationModulesNew_IgnoreMiddleDot_ja_JP
,
84 "ignoreMiddleDot_ja_JP"}, // 17. (1<<25 67108864) (24)
85 {TransliterationModules_IgnoreSpace_ja_JP
, TransliterationModulesNew_IgnoreSpace_ja_JP
,
86 "ignoreSpace_ja_JP"}, // 18. (1<<26 134217728) (25)
87 {TransliterationModules_IgnoreZiZu_ja_JP
, TransliterationModulesNew_IgnoreZiZu_ja_JP
,
88 "ignoreZiZu_ja_JP"}, // 8. (1<<16 131072) (15)
89 {TransliterationModules_IgnoreBaFa_ja_JP
, TransliterationModulesNew_IgnoreBaFa_ja_JP
,
90 "ignoreBaFa_ja_JP"}, // 9. (1<<17 262144) (16)
91 {TransliterationModules_IgnoreTiJi_ja_JP
, TransliterationModulesNew_IgnoreTiJi_ja_JP
,
92 "ignoreTiJi_ja_JP"}, // 10. (1<<18 524288) (17)
93 {TransliterationModules_IgnoreHyuByu_ja_JP
, TransliterationModulesNew_IgnoreHyuByu_ja_JP
,
94 "ignoreHyuByu_ja_JP"}, // 11. (1<<19 1048576) (18)
95 {TransliterationModules_IgnoreSeZe_ja_JP
, TransliterationModulesNew_IgnoreSeZe_ja_JP
,
96 "ignoreSeZe_ja_JP"}, // 12. (1<<20 2097152) (19)
97 {TransliterationModules_IgnoreIandEfollowedByYa_ja_JP
,
98 TransliterationModulesNew_IgnoreIandEfollowedByYa_ja_JP
, "ignoreIandEfollowedByYa_ja_JP"},
99 // 13. (1<<21 4194304) (20)
100 {TransliterationModules_IgnoreKiKuFollowedBySa_ja_JP
,
101 TransliterationModulesNew_IgnoreKiKuFollowedBySa_ja_JP
, "ignoreKiKuFollowedBySa_ja_JP"},
102 // 14. (1<<22 8388608) (21)
103 {TransliterationModules_IgnoreProlongedSoundMark_ja_JP
,
104 TransliterationModulesNew_IgnoreProlongedSoundMark_ja_JP
, "ignoreProlongedSoundMark_ja_JP"},
105 // 16. (1<<24 33554432) (23)
107 TmItem1 (UPPERCASE_LOWERCASE
), // 19. (1) (1)
108 TmItem1 (LOWERCASE_UPPERCASE
), // 20. (2) (2)
109 TmItem1 (HALFWIDTH_FULLWIDTH
), // 21. (3) (3)
110 TmItem1 (FULLWIDTH_HALFWIDTH
), // 22. (4) (4)
111 TmItem1 (KATAKANA_HIRAGANA
), // 23. (5) (5)
112 TmItem1 (HIRAGANA_KATAKANA
), // 24. (6) (6)
114 {TransliterationModules_SmallToLarge_ja_JP
, TransliterationModulesNew_SmallToLarge_ja_JP
,
115 "smallToLarge_ja_JP"}, // 25. (1<<27 268435456) (26)
116 {TransliterationModules_LargeToSmall_ja_JP
, TransliterationModulesNew_LargeToSmall_ja_JP
,
117 "largeToSmall_ja_JP"}, // 26. (1<<28 536870912) (27)
118 TmItem2 (NumToTextLower_zh_CN
), // 27. () (28)
119 TmItem2 (NumToTextUpper_zh_CN
), // 28. () (29)
120 TmItem2 (NumToTextLower_zh_TW
), // 29. () (30)
121 TmItem2 (NumToTextUpper_zh_TW
), // 30. () (31)
122 TmItem2 (NumToTextFormalHangul_ko
), // 31. () (32)
123 TmItem2 (NumToTextFormalLower_ko
), // 32. () (33)
124 TmItem2 (NumToTextFormalUpper_ko
), // 33. () (34)
125 TmItem2 (NumToTextInformalHangul_ko
), // 34. () (35)
126 TmItem2 (NumToTextInformalLower_ko
), // 35. () (36)
127 TmItem2 (NumToTextInformalUpper_ko
), // 36. () (37)
128 TmItem2 (NumToCharLower_zh_CN
), // 37. () (38)
129 TmItem2 (NumToCharUpper_zh_CN
), // 38. () (39)
130 TmItem2 (NumToCharLower_zh_TW
), // 39. () (40)
131 TmItem2 (NumToCharUpper_zh_TW
), // 40. () (41)
132 TmItem2 (NumToCharHangul_ko
), // 41. () (42)
133 TmItem2 (NumToCharLower_ko
), // 42. () (43)
134 TmItem2 (NumToCharUpper_ko
), // 43. () (44)
135 TmItem2 (NumToCharFullwidth
), // 44. () (45)
136 TmItem2 (NumToCharKanjiShort_ja_JP
), // 45. () (46)
137 TmItem2 (TextToNumLower_zh_CN
), // 46. () (47)
138 TmItem2 (TextToNumUpper_zh_CN
), // 47. () (48)
139 TmItem2 (TextToNumLower_zh_TW
), // 48. () (49)
140 TmItem2 (TextToNumUpper_zh_TW
), // 49. () (50)
141 TmItem2 (TextToNumFormalHangul_ko
), // 50. () (51)
142 TmItem2 (TextToNumFormalLower_ko
), // 51. () (52)
143 TmItem2 (TextToNumFormalUpper_ko
), // 52. () (53)
144 TmItem2 (TextToNumInformalHangul_ko
), // 53. () (54)
145 TmItem2 (TextToNumInformalLower_ko
), // 54. () (55)
146 TmItem2 (TextToNumInformalUpper_ko
), // 55. () (56)
148 TmItem2 (CharToNumLower_zh_CN
), // 56. () (59)
149 TmItem2 (CharToNumUpper_zh_CN
), // 57. () (60)
150 TmItem2 (CharToNumLower_zh_TW
), // 58. () (61)
151 TmItem2 (CharToNumUpper_zh_TW
), // 59. () (62)
152 TmItem2 (CharToNumHangul_ko
), // 60. () (63)
153 TmItem2 (CharToNumLower_ko
), // 61. () (64)
154 TmItem2 (CharToNumUpper_ko
), // 62. () (65)
156 // no enum defined for these trans. application has to use impl name to load them
157 // TmItem2 (NumToCharArabic_Indic), // () (67)
158 // TmItem2 (NumToCharEstern_Arabic_Indic),// () (68)
159 // TmItem2 (NumToCharIndic), // () (69)
160 // TmItem2 (NumToCharThai), // () (70)
161 {TransliterationModules(0), TransliterationModulesNew(0), nullptr}
164 // Constructor/Destructor
165 TransliterationImpl::TransliterationImpl(const Reference
<XComponentContext
>& xContext
) : mxContext(xContext
)
168 caseignoreOnly
= true;
170 mxLocaledata
.set(LocaleData2::create(xContext
));
173 TransliterationImpl::~TransliterationImpl()
175 mxLocaledata
.clear();
182 TransliterationImpl::getName()
184 if (numCascade
== 1 && bodyCascade
[0].is())
185 return bodyCascade
[0]->getName();
187 return ( u
"Not Loaded"_ustr
);
188 throw RuntimeException();
192 TransliterationImpl::getType()
195 return (TransliterationType::CASCADE
|TransliterationType::IGNORE
);
196 if (numCascade
> 0 && bodyCascade
[0].is())
197 return bodyCascade
[0]->getType();
198 throw RuntimeException();
201 static TransliterationModules
operator&(TransliterationModules lhs
, TransliterationModules rhs
) {
202 return TransliterationModules(sal_Int32(lhs
) & sal_Int32(rhs
));
204 static TransliterationModules
operator|(TransliterationModules lhs
, TransliterationModules rhs
) {
205 return TransliterationModules(sal_Int32(lhs
) | sal_Int32(rhs
));
209 TransliterationImpl::loadModule( TransliterationModules modType
, const Locale
& rLocale
)
212 if (bool(modType
& TransliterationModules_IGNORE_MASK
) &&
213 bool(modType
& TransliterationModules_NON_IGNORE_MASK
))
215 throw RuntimeException();
216 } else if (bool(modType
& TransliterationModules_IGNORE_MASK
)) {
217 #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \
218 TransliterationModules_IGNORE_WIDTH | \
219 TransliterationModules_IGNORE_KANA)
220 TransliterationModules mask
= ((modType
& TransliterationModules_IGNORE_CASE_MASK
) == modType
) ?
221 TransliterationModules_IGNORE_CASE_MASK
: TransliterationModules_IGNORE_MASK
;
222 for (sal_Int16 i
= 0; bool(TMlist
[i
].tm
& mask
); i
++) {
223 if (bool(modType
& TMlist
[i
].tm
))
224 if (loadModuleByName(OUString::createFromAscii(TMlist
[i
].implName
),
225 bodyCascade
[numCascade
], rLocale
))
228 // additional transliterations from TransliterationModulesExtra (we cannot extend TransliterationModules)
229 if (bool(modType
& TransliterationModules(TransliterationModulesExtra::IGNORE_DIACRITICS_CTL
)))
231 if (loadModuleByName(u
"ignoreDiacritics_CTL", bodyCascade
[numCascade
], rLocale
))
234 if (bool(modType
& TransliterationModules(TransliterationModulesExtra::IGNORE_KASHIDA_CTL
)))
235 if (loadModuleByName(u
"ignoreKashida_CTL", bodyCascade
[numCascade
], rLocale
))
238 } else if (bool(modType
& TransliterationModules_NON_IGNORE_MASK
)) {
239 for (sal_Int16 i
= 0; bool(TMlist
[i
].tm
); i
++) {
240 if (TMlist
[i
].tm
== modType
) {
241 if (loadModuleByName(OUString::createFromAscii(TMlist
[i
].implName
), bodyCascade
[numCascade
], rLocale
))
250 TransliterationImpl::loadModuleNew( const Sequence
< TransliterationModulesNew
> & modType
, const Locale
& rLocale
)
253 TransliterationModules mask
= TransliterationModules_END_OF_MODULE
;
254 sal_Int32 count
= modType
.getLength();
255 if (count
> maxCascade
)
256 throw RuntimeException(); // could not handle more than maxCascade
257 for (sal_Int32 i
= 0; i
< count
; i
++) {
258 for (sal_Int16 j
= 0; bool(TMlist
[j
].tmn
); j
++) {
259 if (TMlist
[j
].tmn
== modType
[i
]) {
260 if (mask
== TransliterationModules_END_OF_MODULE
)
261 mask
= bool(TMlist
[i
].tm
) && bool(TMlist
[i
].tm
& TransliterationModules_IGNORE_MASK
) ?
262 TransliterationModules_IGNORE_MASK
: TransliterationModules_NON_IGNORE_MASK
;
263 else if (mask
== TransliterationModules_IGNORE_MASK
&&
264 (TMlist
[i
].tm
&TransliterationModules_IGNORE_MASK
) == TransliterationModules_END_OF_MODULE
)
265 throw RuntimeException(); // could not mess up ignore trans. with non_ignore trans.
266 if (loadModuleByName(OUString::createFromAscii(TMlist
[j
].implName
), bodyCascade
[numCascade
], rLocale
))
275 TransliterationImpl::loadModuleByImplName(const OUString
& implName
, const Locale
& rLocale
)
278 if (loadModuleByName(implName
, bodyCascade
[numCascade
], rLocale
))
284 TransliterationImpl::loadModulesByImplNames(const Sequence
< OUString
>& implNameList
, const Locale
& rLocale
)
286 if (implNameList
.getLength() > maxCascade
|| implNameList
.getLength() <= 0)
287 throw RuntimeException();
290 for (const auto& rName
: implNameList
)
291 if (loadModuleByName(rName
, bodyCascade
[numCascade
], rLocale
))
296 Sequence
<OUString
> SAL_CALL
297 TransliterationImpl::getAvailableModules( const Locale
& rLocale
, sal_Int16 sType
)
299 const Sequence
<OUString
> translist
= mxLocaledata
->getTransliterations(rLocale
);
300 std::vector
<OUString
> r
;
301 r
.reserve(translist
.getLength());
302 Reference
<XExtendedTransliteration
> body
;
303 for (const auto& rTrans
: translist
)
305 if (loadModuleByName(rTrans
, body
, rLocale
)) {
306 if (body
->getType() & sType
)
311 return comphelper::containerToSequence(r
);
316 TransliterationImpl::transliterate( const OUString
& inStr
, sal_Int32 startPos
, sal_Int32 nCount
,
317 Sequence
< sal_Int32
>& offset
)
324 if ( startPos
== 0 && nCount
== inStr
.getLength() )
325 return bodyCascade
[0]->transliterate( inStr
, 0, nCount
, offset
);
328 OUString tmpStr
= inStr
.copy(startPos
, nCount
);
329 tmpStr
= bodyCascade
[0]->transliterate(tmpStr
, 0, nCount
, offset
);
332 for (sal_Int32
& j
: asNonConstRange(offset
))
340 OUString tmpStr
= inStr
.copy(startPos
, nCount
);
342 auto [begin
, end
] = asNonConstRange(offset
);
343 std::iota(begin
, end
, startPos
);
345 Sequence
<sal_Int32
> from(nCount
);
346 Sequence
<sal_Int32
> to
= offset
;
347 for (sal_Int32 i
= 0; i
< numCascade
; i
++) {
348 tmpStr
= bodyCascade
[i
]->transliterate(tmpStr
, 0, nCount
, from
);
350 nCount
= tmpStr
.getLength();
352 assert(from
.getLength() == nCount
);
354 for (sal_Int32
& ix
: asNonConstRange(to
))
357 offset
= std::move(to
);
364 TransliterationImpl::folding( const OUString
& inStr
, sal_Int32 startPos
, sal_Int32 nCount
,
365 Sequence
< sal_Int32
>& offset
)
370 if (offset
.getLength() != nCount
)
371 offset
.realloc(nCount
);
374 if ( startPos
== 0 && nCount
== inStr
.getLength() )
375 return bodyCascade
[0]->folding( inStr
, 0, nCount
, offset
);
378 OUString tmpStr
= inStr
.copy(startPos
, nCount
);
379 tmpStr
= bodyCascade
[0]->folding(tmpStr
, 0, nCount
, offset
);
382 for (sal_Int32
& j
: asNonConstRange(offset
))
390 OUString tmpStr
= inStr
.copy(startPos
, nCount
);
392 auto [begin
, end
] = asNonConstRange(offset
);
393 std::iota(begin
, end
, startPos
);
395 Sequence
<sal_Int32
> from
;
396 Sequence
<sal_Int32
> to
= offset
;
398 for (sal_Int32 i
= 0; i
< numCascade
; i
++) {
399 tmpStr
= bodyCascade
[i
]->folding(tmpStr
, 0, nCount
, from
);
401 nCount
= tmpStr
.getLength();
403 assert(from
.getLength() == nCount
);
405 for (sal_Int32
& ix
: asNonConstRange(to
))
408 offset
= std::move(to
);
414 TransliterationImpl::transliterateString2String( const OUString
& inStr
, sal_Int32 startPos
, sal_Int32 nCount
)
418 else if (numCascade
== 1)
419 return bodyCascade
[0]->transliterateString2String( inStr
, startPos
, nCount
);
421 OUString tmpStr
= bodyCascade
[0]->transliterateString2String(inStr
, startPos
, nCount
);
423 for (sal_Int32 i
= 1; i
< numCascade
; i
++)
424 tmpStr
= bodyCascade
[i
]->transliterateString2String(tmpStr
, 0, tmpStr
.getLength());
430 TransliterationImpl::transliterateChar2String( sal_Unicode inChar
)
433 return OUString(&inChar
, 1);
434 else if (numCascade
== 1)
435 return bodyCascade
[0]->transliterateChar2String( inChar
);
437 OUString tmpStr
= bodyCascade
[0]->transliterateChar2String(inChar
);
439 for (sal_Int32 i
= 1; i
< numCascade
; i
++)
440 tmpStr
= bodyCascade
[i
]->transliterateString2String(tmpStr
, 0, tmpStr
.getLength());
446 TransliterationImpl::transliterateChar2Char( sal_Unicode inChar
)
448 sal_Unicode tmpChar
= inChar
;
449 for (sal_Int32 i
= 0; i
< numCascade
; i
++)
450 tmpChar
= bodyCascade
[i
]->transliterateChar2Char(tmpChar
);
456 TransliterationImpl::equals(
457 const OUString
& str1
, sal_Int32 pos1
, sal_Int32 nCount1
, sal_Int32
& nMatch1
,
458 const OUString
& str2
, sal_Int32 pos2
, sal_Int32 nCount2
, sal_Int32
& nMatch2
)
460 // since this is an API function make it user fail safe
469 if ( !nCount1
|| !nCount2
||
470 pos1
>= str1
.getLength() || pos2
>= str2
.getLength() ||
471 pos1
< 0 || pos2
< 0 ) {
472 nMatch1
= nMatch2
= 0;
473 // two empty strings return true, else false
474 return !nCount1
&& !nCount2
&& pos1
== str1
.getLength() && pos2
== str2
.getLength();
476 if ( pos1
+ nCount1
> str1
.getLength() )
477 nCount1
= str1
.getLength() - pos1
;
478 if ( pos2
+ nCount2
> str2
.getLength() )
479 nCount2
= str2
.getLength() - pos2
;
481 if (caseignoreOnly
&& caseignore
.is())
482 return caseignore
->equals(str1
, pos1
, nCount1
, nMatch1
, str2
, pos2
, nCount2
, nMatch2
);
484 Sequence
<sal_Int32
> offset1
, offset2
;
486 OUString tmpStr1
= folding(str1
, pos1
, nCount1
, offset1
);
487 OUString tmpStr2
= folding(str2
, pos2
, nCount2
, offset2
);
488 // Length of offset1 and offset2 may still be 0 if there was no folding
491 const sal_Unicode
*p1
= tmpStr1
.getStr();
492 const sal_Unicode
*p2
= tmpStr2
.getStr();
493 sal_Int32 i
, nLen
= ::std::min( tmpStr1
.getLength(), tmpStr2
.getLength());
494 for (i
= 0; i
< nLen
; ++i
, ++p1
, ++p2
) {
496 // return number of matched code points so far
497 nMatch1
= (i
< offset1
.getLength()) ? offset1
.getConstArray()[i
] : i
;
498 nMatch2
= (i
< offset2
.getLength()) ? offset2
.getConstArray()[i
] : i
;
503 if ( tmpStr1
.getLength() != tmpStr2
.getLength() ) {
504 // return number of matched code points so far
505 nMatch1
= (i
<= offset1
.getLength()) ? offset1
.getConstArray()[i
-1] + 1 : i
;
506 nMatch2
= (i
<= offset2
.getLength()) ? offset2
.getConstArray()[i
-1] + 1 : i
;
516 TransliterationImpl::getRange(const Sequence
< OUString
> &inStrs
,
517 const sal_Int32 length
, sal_Int16 _numCascade
)
519 if (_numCascade
>= numCascade
|| ! bodyCascade
[_numCascade
].is())
523 constexpr sal_Int32 nMaxOutput
= 2;
524 const sal_Int32 nMaxOutputLength
= nMaxOutput
*length
;
525 std::vector
<OUString
> ostr
;
526 ostr
.reserve(nMaxOutputLength
);
527 for (sal_Int32 j
= 0; j
< length
; j
+=2) {
528 const Sequence
< OUString
> temp
= bodyCascade
[_numCascade
]->transliterateRange(inStrs
[j
], inStrs
[j
+1]);
530 for (const auto& rStr
: temp
) {
531 if ( j_tmp
++ >= nMaxOutputLength
) throw RuntimeException();
532 ostr
.push_back(rStr
);
536 return getRange(comphelper::containerToSequence(ostr
), j_tmp
, ++_numCascade
);
540 Sequence
< OUString
> SAL_CALL
541 TransliterationImpl::transliterateRange( const OUString
& str1
, const OUString
& str2
)
544 return bodyCascade
[0]->transliterateRange(str1
, str2
);
546 Sequence
< OUString
> ostr
{ str1
, str2
};
548 return getRange(ostr
, 2, 0);
553 TransliterationImpl::compareSubstring(
554 const OUString
& str1
, sal_Int32 off1
, sal_Int32 len1
,
555 const OUString
& str2
, sal_Int32 off2
, sal_Int32 len2
)
557 if (caseignoreOnly
&& caseignore
.is())
558 return caseignore
->compareSubstring(str1
, off1
, len1
, str2
, off2
, len2
);
560 Sequence
<sal_Int32
> offset
;
562 OUString in_str1
= transliterate(str1
, off1
, len1
, offset
);
563 OUString in_str2
= transliterate(str2
, off2
, len2
, offset
);
564 const sal_Unicode
* unistr1
= in_str1
.getStr();
565 const sal_Unicode
* unistr2
= in_str2
.getStr();
566 sal_Int32 strlen1
= in_str1
.getLength();
567 sal_Int32 strlen2
= in_str2
.getLength();
569 while (strlen1
&& strlen2
) {
570 if (*unistr1
!= *unistr2
)
571 return *unistr1
> *unistr2
? 1 : -1;
573 unistr1
++; unistr2
++; strlen1
--; strlen2
--;
575 return strlen1
== strlen2
? 0 : (strlen1
> strlen2
? 1 : -1);
580 TransliterationImpl::compareString(const OUString
& str1
, const OUString
& str2
)
582 if (caseignoreOnly
&& caseignore
.is())
583 return caseignore
->compareString(str1
, str2
);
585 return compareSubstring(str1
, 0, str1
.getLength(), str2
, 0, str2
.getLength());
590 TransliterationImpl::clear()
592 for (sal_Int32 i
= 0; i
< numCascade
; i
++)
593 if (bodyCascade
[i
].is())
594 bodyCascade
[i
].clear();
597 caseignoreOnly
= true;
602 /** structure to cache the last transliteration body used. */
606 css::uno::Reference
< css::i18n::XExtendedTransliteration
> Body
;
610 void TransliterationImpl::loadBody( OUString
const &implName
, Reference
<XExtendedTransliteration
>& body
)
612 assert(!implName
.isEmpty());
613 static std::mutex transBodyMutex
;
614 std::unique_lock
guard(transBodyMutex
);
615 static TransBody lastTransBody
;
616 if (implName
!= lastTransBody
.Name
)
618 lastTransBody
.Body
.set(
619 mxContext
->getServiceManager()->createInstanceWithContext(implName
, mxContext
), UNO_QUERY_THROW
);
620 lastTransBody
.Name
= implName
;
622 body
= lastTransBody
.Body
;
626 TransliterationImpl::loadModuleByName( std::u16string_view implName
,
627 Reference
<XExtendedTransliteration
>& body
, const Locale
& rLocale
)
629 OUString cname
= OUString::Concat(TRLT_IMPLNAME_PREFIX
) + implName
;
630 loadBody(cname
, body
);
632 body
->loadModule(TransliterationModules(0), rLocale
); // toUpper/toLoad need rLocale
634 // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed
635 for (sal_Int16 i
= 0; i
< 3; i
++) {
636 if (o3tl::equalsAscii(implName
, TMlist
[i
].implName
)) {
637 if (i
== 0) // current module is caseignore
638 body
->loadModule(TMlist
[0].tm
, rLocale
); // caseignore need to setup module name
639 if (! caseignore
.is()) {
640 OUString bname
= TRLT_IMPLNAME_PREFIX
+
641 OUString::createFromAscii(TMlist
[0].implName
);
642 loadBody(bname
, caseignore
);
645 caseignore
->loadModule(TMlist
[i
].tm
, rLocale
);
649 caseignoreOnly
= false; // has other module than just ignore case/kana/width
655 TransliterationImpl::getImplementationName()
657 return u
"com.sun.star.i18n.Transliteration"_ustr
;
661 TransliterationImpl::supportsService(const OUString
& rServiceName
)
663 return cppu::supportsService(this, rServiceName
);
666 Sequence
< OUString
> SAL_CALL
667 TransliterationImpl::getSupportedServiceNames()
669 return { u
"com.sun.star.i18n.Transliteration"_ustr
};
674 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
675 com_sun_star_i18n_Transliteration_get_implementation(
676 css::uno::XComponentContext
*context
,
677 css::uno::Sequence
<css::uno::Any
> const &)
679 return cppu::acquire(new i18npool::TransliterationImpl(context
));
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */