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