LCOV - code coverage report
Current view: top level - libreoffice/i18npool/source/transliteration - transliterationImpl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 85 283 30.0 %
Date: 2012-12-27 Functions: 13 28 46.4 %
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/lang/XComponent.hpp>
      27             : 
      28             : #include <comphelper/componentcontext.hxx>
      29             : #include <comphelper/processfactory.hxx>
      30             : #include <rtl/instance.hxx>
      31             : #include <rtl/string.h>
      32             : #include <rtl/ustring.hxx>
      33             : #include <rtl/ustrbuf.hxx>
      34             : 
      35             : #include <algorithm>
      36             : 
      37             : #if OSL_DEBUG_LEVEL > 1
      38             : #include <stdio.h>
      39             : #endif
      40             : 
      41             : using namespace com::sun::star::uno;
      42             : using namespace com::sun::star::lang;
      43             : 
      44             : using ::rtl::OUString;
      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          44 : TransliterationImpl::TransliterationImpl(const Reference <XComponentContext>& xContext) : mxContext(xContext)
     142             : {
     143          44 :     numCascade = 0;
     144          44 :     caseignoreOnly = sal_True;
     145             : 
     146          44 :     mxLocaledata.set(LocaleData::create(xContext));
     147          44 : }
     148             : 
     149         775 : TransliterationImpl::~TransliterationImpl()
     150             : {
     151          25 :     mxLocaledata.clear();
     152          25 :     clear();
     153         750 : }
     154             : 
     155             : 
     156             : // Methods
     157             : OUString SAL_CALL
     158           0 : TransliterationImpl::getName() throw(RuntimeException)
     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)
     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          42 : TransliterationImpl::loadModule( TransliterationModules modType, const Locale& rLocale )
     179             :         throw(RuntimeException)
     180             : {
     181          42 :         clear();
     182          42 :     if (modType&TransliterationModules_IGNORE_MASK && modType&TransliterationModules_NON_IGNORE_MASK) {
     183           0 :         throw ERROR;
     184          42 :     } else if (modType&TransliterationModules_IGNORE_MASK) {
     185             : #define TransliterationModules_IGNORE_CASE_MASK (TransliterationModules_IGNORE_CASE | \
     186             :                                                 TransliterationModules_IGNORE_WIDTH | \
     187             :                                                 TransliterationModules_IGNORE_KANA)
     188             :         sal_Int32 mask = ((modType&TransliterationModules_IGNORE_CASE_MASK) == modType) ?
     189          40 :                 TransliterationModules_IGNORE_CASE_MASK : TransliterationModules_IGNORE_MASK;
     190         160 :         for (sal_Int16 i = 0; TMlist[i].tm & mask; i++) {
     191         120 :             if (modType & TMlist[i].tm)
     192         116 :                 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName),
     193         116 :                                                 bodyCascade[numCascade], rLocale))
     194          58 :                     numCascade++;
     195             :         }
     196           2 :     } else if (modType&TransliterationModules_NON_IGNORE_MASK) {
     197          42 :         for (sal_Int16 i = 0; TMlist[i].tm; i++) {
     198          42 :             if (TMlist[i].tm == modType) {
     199           2 :                 if (loadModuleByName(OUString::createFromAscii(TMlist[i].implName), bodyCascade[numCascade], rLocale))
     200           2 :                     numCascade++;
     201           2 :                 break;
     202             :             }
     203             :         }
     204             :     }
     205          42 : }
     206             : 
     207             : void SAL_CALL
     208           0 : TransliterationImpl::loadModuleNew( const Sequence < TransliterationModulesNew > & modType, const Locale& rLocale )
     209             :   throw(RuntimeException)
     210             : {
     211           0 :     clear();
     212           0 :     sal_Int32 mask = 0, count = modType.getLength();
     213           0 :     if (count > maxCascade)
     214           0 :         throw ERROR; // could not handle more than maxCascade
     215           0 :     for (sal_Int16 i = 0; i < count; i++) {
     216           0 :         for (sal_Int16 j = 0; TMlist[j].tmn; j++) {
     217           0 :             if (TMlist[j].tmn == modType[i]) {
     218           0 :                 if (mask == 0)
     219             :                     mask = TMlist[i].tm && (TMlist[i].tm&TransliterationModules_IGNORE_MASK) ?
     220           0 :                         TransliterationModules_IGNORE_MASK : TransliterationModules_NON_IGNORE_MASK;
     221           0 :                 else if (mask == TransliterationModules_IGNORE_MASK &&
     222             :                         (TMlist[i].tm&TransliterationModules_IGNORE_MASK) == 0)
     223           0 :                     throw ERROR; // could not mess up ignore trans. with non_ignore trans.
     224           0 :                 if (loadModuleByName(OUString::createFromAscii(TMlist[j].implName), bodyCascade[numCascade], rLocale))
     225           0 :                     numCascade++;
     226           0 :                 break;
     227             :             }
     228             :         }
     229             :     }
     230           0 : }
     231             : 
     232             : void SAL_CALL
     233           0 : TransliterationImpl::loadModuleByImplName(const OUString& implName, const Locale& rLocale)
     234             :   throw(RuntimeException)
     235             : {
     236           0 :     clear();
     237           0 :     if (loadModuleByName(implName, bodyCascade[numCascade], rLocale))
     238           0 :         numCascade++;
     239           0 : }
     240             : 
     241             : 
     242             : void SAL_CALL
     243           0 : TransliterationImpl::loadModulesByImplNames(const Sequence< OUString >& implNameList, const Locale& rLocale ) throw(RuntimeException)
     244             : {
     245           0 :     if (implNameList.getLength() > maxCascade || implNameList.getLength() <= 0)
     246           0 :         throw ERROR;
     247             : 
     248           0 :     clear();
     249           0 :     for (sal_Int32 i = 0; i < implNameList.getLength(); i++)
     250           0 :         if (loadModuleByName(implNameList[i], bodyCascade[numCascade], rLocale))
     251           0 :             numCascade++;
     252           0 : }
     253             : 
     254             : 
     255             : Sequence<OUString> SAL_CALL
     256           0 : TransliterationImpl::getAvailableModules( const Locale& rLocale, sal_Int16 sType ) throw(RuntimeException)
     257             : {
     258           0 :     const Sequence<OUString> &translist = mxLocaledata->getTransliterations(rLocale);
     259           0 :     Sequence<OUString> r(translist.getLength());
     260           0 :     Reference<XExtendedTransliteration> body;
     261           0 :     sal_Int32 n = 0;
     262           0 :     for (sal_Int32 i = 0; i < translist.getLength(); i++)
     263             :     {
     264           0 :         if (loadModuleByName(translist[i], body, rLocale)) {
     265           0 :             if (body->getType() & sType)
     266           0 :                 r[n++] = translist[i];
     267           0 :             body.clear();
     268             :         }
     269             :     }
     270           0 :     r.realloc(n);
     271           0 :     return (r);
     272             : }
     273             : 
     274             : 
     275             : OUString SAL_CALL
     276          27 : TransliterationImpl::transliterate( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
     277             :                     Sequence< sal_Int32 >& offset ) throw(RuntimeException)
     278             : {
     279          27 :     if (numCascade == 0)
     280           0 :         return inStr;
     281             : 
     282          27 :     if (offset.getLength() != nCount)
     283          19 :         offset.realloc(nCount);
     284          27 :     if (numCascade == 1)
     285             :     {
     286          27 :         if ( startPos == 0 && nCount == inStr.getLength() )
     287          27 :             return bodyCascade[0]->transliterate( inStr, 0, nCount, offset);
     288             :         else
     289             :         {
     290           0 :             OUString tmpStr = inStr.copy(startPos, nCount);
     291           0 :             tmpStr = bodyCascade[0]->transliterate(tmpStr, 0, nCount, offset);
     292           0 :             if ( startPos )
     293             :             {
     294           0 :                 sal_Int32 * pArr = offset.getArray();
     295           0 :                 nCount = offset.getLength();
     296           0 :                 for (sal_Int32 j = 0; j < nCount; j++)
     297           0 :                     pArr[j] += startPos;
     298             :             }
     299           0 :             return tmpStr;
     300             :         }
     301             :     }
     302             :     else
     303             :     {
     304           0 :         OUString tmpStr = inStr.copy(startPos, nCount);
     305           0 :         sal_Int32 * pArr = offset.getArray();
     306           0 :         for (sal_Int32 j = 0; j < nCount; j++)
     307           0 :             pArr[j] = startPos + j;
     308             : 
     309           0 :         sal_Int16 from = 0, to = 1, tmp;
     310           0 :         Sequence<sal_Int32> off[2];
     311             : 
     312           0 :         off[to] = offset;
     313           0 :         off[from].realloc(nCount);
     314           0 :         for (sal_Int32 i = 0; i < numCascade; i++) {
     315           0 :             tmpStr = bodyCascade[i]->transliterate(tmpStr, 0, nCount, off[from]);
     316             : 
     317           0 :             nCount = tmpStr.getLength();
     318             : 
     319           0 :             tmp = from; from = to; to = tmp;
     320           0 :             for (sal_Int32 j = 0; j < nCount; j++)
     321           0 :                 off[to][j] = off[from][off[to][j]];
     322             :         }
     323           0 :         offset = off[to];
     324           0 :         return tmpStr;
     325             :     }
     326             : }
     327             : 
     328             : 
     329             : //
     330             : OUString SAL_CALL
     331           0 : TransliterationImpl::folding( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount,
     332             :         Sequence< sal_Int32 >& offset ) throw(RuntimeException)
     333             : {
     334           0 :     if (numCascade == 0)
     335           0 :         return inStr;
     336             : 
     337           0 :     if (offset.getLength() != nCount)
     338           0 :         offset.realloc(nCount);
     339           0 :     if (numCascade == 1)
     340             :     {
     341           0 :         if ( startPos == 0 && nCount == inStr.getLength() )
     342           0 :             return bodyCascade[0]->folding( inStr, 0, nCount, offset);
     343             :         else
     344             :         {
     345           0 :             OUString tmpStr = inStr.copy(startPos, nCount);
     346           0 :             tmpStr = bodyCascade[0]->folding(tmpStr, 0, nCount, offset);
     347           0 :             if ( startPos )
     348             :             {
     349           0 :                 sal_Int32 * pArr = offset.getArray();
     350           0 :                 nCount = offset.getLength();
     351           0 :                 for (sal_Int32 j = 0; j < nCount; j++)
     352           0 :                     pArr[j] += startPos;
     353             :             }
     354           0 :             return tmpStr;
     355             :         }
     356             :     }
     357             :     else
     358             :     {
     359           0 :         OUString tmpStr = inStr.copy(startPos, nCount);
     360           0 :         sal_Int32 * pArr = offset.getArray();
     361           0 :         for (sal_Int32 j = 0; j < nCount; j++)
     362           0 :             pArr[j] = startPos + j;
     363             : 
     364           0 :         sal_Int16 from = 0, to = 1, tmp;
     365           0 :         Sequence<sal_Int32> off[2];
     366             : 
     367           0 :         off[to] = offset;
     368           0 :         for (sal_Int32 i = 0; i < numCascade; i++) {
     369           0 :             tmpStr = bodyCascade[i]->folding(tmpStr, 0, nCount, off[from]);
     370             : 
     371           0 :             nCount = tmpStr.getLength();
     372             : 
     373           0 :             tmp = from; from = to; to = tmp;
     374           0 :             for (sal_Int32 j = 0; j < nCount; j++)
     375           0 :                 off[to][j] = off[from][off[to][j]];
     376             :         }
     377           0 :         offset = off[to];
     378           0 :         return tmpStr;
     379             :     }
     380             : }
     381             : 
     382             : OUString SAL_CALL
     383           1 : TransliterationImpl::transliterateString2String( const OUString& inStr, sal_Int32 startPos, sal_Int32 nCount ) throw(RuntimeException)
     384             : {
     385           1 :     if (numCascade == 0)
     386           0 :         return inStr;
     387           1 :     else if (numCascade == 1)
     388           1 :         return bodyCascade[0]->transliterateString2String( inStr, startPos, nCount);
     389             :     else {
     390           0 :         OUString tmpStr = bodyCascade[0]->transliterateString2String(inStr, startPos, nCount);
     391             : 
     392           0 :         for (sal_Int32 i = 1; i < numCascade; i++)
     393           0 :             tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
     394           0 :         return tmpStr;
     395             :     }
     396             : }
     397             : 
     398             : OUString SAL_CALL
     399           0 : TransliterationImpl::transliterateChar2String( sal_Unicode inChar ) throw(RuntimeException)
     400             : {
     401           0 :     if (numCascade == 0)
     402           0 :         return OUString(&inChar, 1);
     403           0 :     else if (numCascade == 1)
     404           0 :         return bodyCascade[0]->transliterateChar2String( inChar);
     405             :     else {
     406           0 :         OUString tmpStr = bodyCascade[0]->transliterateChar2String(inChar);
     407             : 
     408           0 :         for (sal_Int32 i = 1; i < numCascade; i++)
     409           0 :             tmpStr = bodyCascade[i]->transliterateString2String(tmpStr, 0, tmpStr.getLength());
     410           0 :         return tmpStr;
     411             :     }
     412             : }
     413             : 
     414             : sal_Unicode SAL_CALL
     415           0 : TransliterationImpl::transliterateChar2Char( sal_Unicode inChar ) throw(MultipleCharsOutputException, RuntimeException)
     416             : {
     417           0 :     sal_Unicode tmpChar = inChar;
     418           0 :     for (sal_Int32 i = 0; i < numCascade; i++)
     419           0 :         tmpChar = bodyCascade[i]->transliterateChar2Char(tmpChar);
     420           0 :     return tmpChar;
     421             : }
     422             : 
     423             : 
     424             : sal_Bool SAL_CALL
     425        1692 : TransliterationImpl::equals(
     426             :     const OUString& str1, sal_Int32 pos1, sal_Int32 nCount1, sal_Int32& nMatch1,
     427             :     const OUString& str2, sal_Int32 pos2, sal_Int32 nCount2, sal_Int32& nMatch2)
     428             :     throw(RuntimeException)
     429             : {
     430             :     // since this is an API function make it user fail safe
     431        1692 :     if ( nCount1 < 0 ) {
     432           0 :         pos1 += nCount1;
     433           0 :         nCount1 = -nCount1;
     434             :     }
     435        1692 :     if ( nCount2 < 0 ) {
     436           0 :         pos2 += nCount2;
     437           0 :         nCount2 = -nCount2;
     438             :     }
     439        4570 :     if ( !nCount1 || !nCount2 ||
     440        2878 :             pos1 >= str1.getLength() || pos2 >= str2.getLength() ||
     441             :             pos1 < 0 || pos2 < 0 ) {
     442         253 :         nMatch1 = nMatch2 = 0;
     443             :         // two empty strings return true, else false
     444         253 :         return !nCount1 && !nCount2 && pos1 == str1.getLength() && pos2 == str2.getLength();
     445             :     }
     446        1439 :     if ( pos1 + nCount1 > str1.getLength() )
     447           0 :         nCount1 = str1.getLength() - pos1;
     448        1439 :     if ( pos2 + nCount2 > str2.getLength() )
     449           0 :         nCount2 = str2.getLength() - pos2;
     450             : 
     451        1439 :     if (caseignoreOnly && caseignore.is())
     452        1439 :         return caseignore->equals(str1, pos1, nCount1, nMatch1, str2, pos2, nCount2, nMatch2);
     453             : 
     454           0 :     Sequence<sal_Int32> offset1, offset2;
     455             : 
     456           0 :     OUString tmpStr1 = folding(str1, pos1, nCount1, offset1);
     457           0 :     OUString tmpStr2 = folding(str2, pos2, nCount2, offset2);
     458             :     // Length of offset1 and offset2 may still be 0 if there was no folding
     459             :     // necessary!
     460             : 
     461           0 :     const sal_Unicode *p1 = tmpStr1.getStr();
     462           0 :     const sal_Unicode *p2 = tmpStr2.getStr();
     463           0 :     sal_Int32 i, nLen = ::std::min( tmpStr1.getLength(), tmpStr2.getLength());
     464           0 :     for (i = 0; i < nLen; ++i, ++p1, ++p2 ) {
     465           0 :         if (*p1 != *p2) {
     466             :             // return number of matched code points so far
     467           0 :             nMatch1 = (i < offset1.getLength()) ? offset1[i] : i;
     468           0 :             nMatch2 = (i < offset2.getLength()) ? offset2[i] : i;
     469           0 :             return sal_False;
     470             :         }
     471             :     }
     472             :     // i==nLen
     473           0 :     if ( tmpStr1.getLength() != tmpStr2.getLength() ) {
     474             :         // return number of matched code points so far
     475           0 :         nMatch1 = (i <= offset1.getLength()) ? offset1[i-1] + 1 : i;
     476           0 :         nMatch2 = (i <= offset2.getLength()) ? offset2[i-1] + 1 : i;
     477           0 :         return sal_False;
     478             :     } else {
     479           0 :         nMatch1 = nCount1;
     480           0 :         nMatch2 = nCount2;
     481           0 :         return sal_True;
     482           0 :     }
     483             : }
     484             : 
     485             : #define MaxOutput 2
     486             : 
     487             : Sequence< OUString > SAL_CALL
     488           0 : TransliterationImpl::getRange(const Sequence< OUString > &inStrs,
     489             :                 const sal_Int32 length, sal_Int16 _numCascade) throw(RuntimeException)
     490             : {
     491           0 :     if (_numCascade >= numCascade || ! bodyCascade[_numCascade].is())
     492           0 :         return inStrs;
     493             : 
     494           0 :     sal_Int32 j_tmp = 0;
     495           0 :     Sequence< OUString > ostr(MaxOutput*length);
     496           0 :     for (sal_Int32 j = 0; j < length; j+=2) {
     497           0 :         const Sequence< OUString >& temp = bodyCascade[_numCascade]->transliterateRange(inStrs[j], inStrs[j+1]);
     498             : 
     499           0 :         for ( sal_Int32 k = 0; k < temp.getLength(); k++) {
     500           0 :             if ( j_tmp >= MaxOutput*length ) throw ERROR;
     501           0 :             ostr[j_tmp++]  = temp[k];
     502             :         }
     503           0 :     }
     504           0 :     ostr.realloc(j_tmp);
     505             : 
     506           0 :     return this->getRange(ostr, j_tmp, ++_numCascade);
     507             : }
     508             : 
     509             : 
     510             : Sequence< OUString > SAL_CALL
     511           0 : TransliterationImpl::transliterateRange( const OUString& str1, const OUString& str2 )
     512             : throw(RuntimeException)
     513             : {
     514           0 :     if (numCascade == 1)
     515           0 :         return bodyCascade[0]->transliterateRange(str1, str2);
     516             : 
     517           0 :     Sequence< OUString > ostr(2);
     518           0 :     ostr[0] = str1;
     519           0 :     ostr[1] = str2;
     520             : 
     521           0 :     return this->getRange(ostr, 2, 0);
     522             : }
     523             : 
     524             : 
     525             : sal_Int32 SAL_CALL
     526           0 : TransliterationImpl::compareSubstring(
     527             :     const OUString& str1, sal_Int32 off1, sal_Int32 len1,
     528             :     const OUString& str2, sal_Int32 off2, sal_Int32 len2)
     529             :     throw(RuntimeException)
     530             : {
     531           0 :     if (caseignoreOnly && caseignore.is())
     532           0 :         return caseignore->compareSubstring(str1, off1, len1, str2, off2, len2);
     533             : 
     534           0 :     Sequence <sal_Int32> offset;
     535             : 
     536           0 :     OUString in_str1 = this->transliterate(str1, off1, len1, offset);
     537           0 :     OUString in_str2 = this->transliterate(str2, off2, len2, offset);
     538           0 :     const sal_Unicode* unistr1 = in_str1.getStr();
     539           0 :     const sal_Unicode* unistr2 = in_str2.getStr();
     540           0 :     sal_Int32 strlen1 = in_str1.getLength();
     541           0 :     sal_Int32 strlen2 = in_str2.getLength();
     542             : 
     543           0 :     while (strlen1 && strlen2) {
     544           0 :         if (*unistr1 != *unistr2)
     545           0 :            return *unistr1 > *unistr2 ? 1 : -1;
     546             : 
     547           0 :         unistr1++; unistr2++; strlen1--; strlen2--;
     548             :     }
     549           0 :     return strlen1 == strlen2 ? 0 : (strlen1 > strlen2 ? 1 : -1);
     550             : }
     551             : 
     552             : 
     553             : sal_Int32 SAL_CALL
     554           3 : TransliterationImpl::compareString(const OUString& str1, const OUString& str2 ) throw (RuntimeException)
     555             : {
     556           3 :     if (caseignoreOnly && caseignore.is())
     557           3 :         return caseignore->compareString(str1, str2);
     558             :     else
     559           0 :         return this->compareSubstring(str1, 0, str1.getLength(), str2, 0, str2.getLength());
     560             : }
     561             : 
     562             : 
     563             : void
     564          67 : TransliterationImpl::clear()
     565             : {
     566         108 :     for (sal_Int32 i = 0; i < numCascade; i++)
     567          41 :         if (bodyCascade[i].is())
     568          41 :             bodyCascade[i].clear();
     569          67 :     numCascade = 0;
     570          67 :     caseignore.clear();
     571          67 :     caseignoreOnly = sal_True;
     572          67 : }
     573             : 
     574             : namespace
     575             : {
     576             :     /** structure to cache the last transliteration body used. */
     577          24 :     struct TransBody
     578             :     {
     579             :         ::rtl::OUString Name;
     580             :         ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XExtendedTransliteration > Body;
     581             :     };
     582             :     class theTransBodyMutex : public rtl::Static<osl::Mutex, theTransBodyMutex> {};
     583             : }
     584             : 
     585         100 : void TransliterationImpl::loadBody( OUString &implName, Reference<XExtendedTransliteration>& body )
     586             :     throw (RuntimeException)
     587             : {
     588             :     assert(!implName.isEmpty());
     589         100 :     ::osl::MutexGuard guard(theTransBodyMutex::get());
     590         100 :     static TransBody lastTransBody;
     591         100 :     if (implName != lastTransBody.Name)
     592             :     {
     593             :         lastTransBody.Body.set(
     594          34 :             mxContext->getServiceManager()->createInstanceWithContext(implName, mxContext), UNO_QUERY_THROW);
     595          34 :         lastTransBody.Name = implName;
     596             :     }
     597         100 :     body = lastTransBody.Body;
     598         100 : }
     599             : 
     600             : sal_Bool SAL_CALL
     601          60 : TransliterationImpl::loadModuleByName( const OUString& implName,
     602             :         Reference<XExtendedTransliteration>& body, const Locale& rLocale) throw(RuntimeException)
     603             : {
     604          60 :     OUString cname = OUString(TRLT_IMPLNAME_PREFIX) + implName;
     605          60 :     loadBody(cname, body);
     606          60 :     if (body.is()) {
     607          60 :         body->loadModule((TransliterationModules)0, rLocale); // toUpper/toLoad need rLocale
     608             : 
     609             :         // if the module is ignore case/kana/width, load caseignore for equals/compareString mothed
     610          93 :         for (sal_Int16 i = 0; i < 3; i++) {
     611          91 :             if (implName.compareToAscii(TMlist[i].implName) == 0) {
     612          58 :                 if (i == 0) // current module is caseignore
     613          40 :                     body->loadModule(TMlist[0].tm, rLocale); // caseingore need to setup module name
     614          58 :                 if (! caseignore.is()) {
     615             :                     OUString bname = OUString(TRLT_IMPLNAME_PREFIX) +
     616          40 :                                 OUString::createFromAscii(TMlist[0].implName);
     617          40 :                     loadBody(bname, caseignore);
     618             :                 }
     619          58 :                 if (caseignore.is())
     620          58 :                     caseignore->loadModule(TMlist[i].tm, rLocale);
     621          58 :                 return sal_True;
     622             :             }
     623             :         }
     624           2 :         caseignoreOnly = sal_False; // has other module than just ignore case/kana/width
     625             :     }
     626           2 :     return body.is();
     627             : }
     628             : 
     629             : const sal_Char cTrans[] = "com.sun.star.i18n.Transliteration";
     630             : 
     631             : OUString SAL_CALL
     632           0 : TransliterationImpl::getImplementationName() throw( RuntimeException )
     633             : {
     634           0 :     return OUString::createFromAscii(cTrans);
     635             : }
     636             : 
     637             : 
     638             : sal_Bool SAL_CALL
     639           0 : TransliterationImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
     640             : {
     641           0 :     return !rServiceName.compareToAscii(cTrans);
     642             : }
     643             : 
     644             : Sequence< OUString > SAL_CALL
     645           0 : TransliterationImpl::getSupportedServiceNames(void) throw( RuntimeException )
     646             : {
     647           0 :     Sequence< OUString > aRet(1);
     648           0 :     aRet[0] = OUString::createFromAscii(cTrans);
     649           0 :     return aRet;
     650             : }
     651             : 
     652             : } } } }
     653             : 
     654             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10