LCOV - code coverage report
Current view: top level - i18npool/source/transliteration - transliterationImpl.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 137 298 46.0 %
Date: 2015-06-13 12:38:46 Functions: 17 29 58.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11