LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/l10ntools/source - merge.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 71 236 30.1 %
Date: 2013-07-09 Functions: 10 21 47.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             : #include "sal/config.h"
      21             : 
      22             : #include <algorithm>
      23             : #include <fstream>
      24             : #include <string>
      25             : #include <vector>
      26             : 
      27             : #include "export.hxx"
      28             : #include "po.hxx"
      29             : 
      30             : namespace
      31             : {
      32         324 :     static OString lcl_NormalizeFilename(const OString& rFilename)
      33             :     {
      34             :         return rFilename.copy(
      35             :             std::max(
      36         324 :                 rFilename.lastIndexOf( '\\' ),
      37         648 :                 rFilename.lastIndexOf( '/' ))+1);
      38             :     };
      39             : 
      40           0 :     static bool lcl_ReadPoChecked(
      41             :         PoEntry& o_rPoEntry, PoIfstream& rPoFile,
      42             :         const OString& rFileName)
      43             :     {
      44             :         try
      45             :         {
      46           0 :             rPoFile.readEntry( o_rPoEntry );
      47             :         }
      48           0 :         catch( PoIfstream::Exception& aException )
      49             :         {
      50           0 :             if( aException == PoIfstream::INVALIDENTRY )
      51             :             {
      52             :                 printf(
      53             :                     "Warning : %s contains invalid entry\n",
      54           0 :                     rFileName.getStr() );
      55           0 :                 return false;
      56             :             }
      57           0 :         }
      58           0 :         return true;
      59             :     }
      60             : }
      61             : 
      62             : //
      63             : //  class ResData
      64             : //
      65             : 
      66           0 : ResData::ResData( const OString &rGId )
      67             :     :
      68             :     nIdLevel( ID_LEVEL_NULL ),
      69             :     bChild( sal_False ),
      70             :     bChildWithText( sal_False ),
      71             :     bText( sal_False ),
      72             :     bHelpText( sal_False ),
      73             :     bQuickHelpText( sal_False ),
      74             :     bTitle( sal_False ),
      75             :     bList( sal_False ),
      76             :     sGId( rGId ),
      77             :     sTextTyp( "Text" ),
      78             :     pStringList( NULL ),
      79             :     pUIEntries( NULL ),
      80             :     pItemList( NULL ),
      81             :     pFilterList( NULL ),
      82           0 :     pPairedList( NULL )
      83             : {
      84           0 :     sGId = sGId.replaceAll("\r", OString());
      85           0 : }
      86             : 
      87         830 : ResData::ResData( const OString &rGId, const OString &rFilename)
      88             :     :
      89             :     nIdLevel( ID_LEVEL_NULL ),
      90             :     bChild( sal_False ),
      91             :     bChildWithText( sal_False ),
      92             :     bText( sal_False ),
      93             :     bHelpText( sal_False ),
      94             :     bQuickHelpText( sal_False ),
      95             :     bTitle( sal_False ),
      96             :     bList( sal_False ),
      97             :     sGId( rGId ),
      98             :     sFilename( rFilename ),
      99             :     sTextTyp( "Text" ),
     100             :     pStringList( NULL ),
     101             :     pUIEntries( NULL ),
     102             :     pItemList( NULL ),
     103             :     pFilterList( NULL ),
     104         830 :     pPairedList( NULL )
     105             : {
     106         830 :     sGId = sGId.replaceAll("\r", OString());
     107         830 : }
     108             : 
     109             : 
     110        1660 : ResData::~ResData()
     111             : {
     112         830 :     if ( pStringList ) {
     113             :         // delete existing res. of type StringList
     114          19 :         for ( size_t i = 0; i < pStringList->size(); i++ ) {
     115          17 :             ExportListEntry* test = (*pStringList)[ i ];
     116          17 :             if( test != NULL ) delete test;
     117             :         }
     118           2 :         delete pStringList;
     119             :     }
     120         830 :     if ( pFilterList ) {
     121             :         // delete existing res. of type FilterList
     122           0 :         for ( size_t i = 0; i < pFilterList->size(); i++ ) {
     123           0 :             ExportListEntry* test = (*pFilterList)[ i ];
     124           0 :             delete test;
     125             :         }
     126           0 :         delete pFilterList;
     127             :     }
     128         830 :     if ( pItemList ) {
     129             :         // delete existing res. of type ItemList
     130           0 :         for ( size_t i = 0; i < pItemList->size(); i++ ) {
     131           0 :             ExportListEntry* test = (*pItemList)[ i ];
     132           0 :             delete test;
     133             :         }
     134           0 :         delete pItemList;
     135             :     }
     136         830 :     if ( pUIEntries ) {
     137             :         // delete existing res. of type UIEntries
     138           0 :         for ( size_t i = 0; i < pUIEntries->size(); i++ ) {
     139           0 :             ExportListEntry* test = (*pUIEntries)[ i ];
     140           0 :             delete test;
     141             :         }
     142           0 :         delete pUIEntries;
     143             :     }
     144         830 : }
     145             : 
     146             : //
     147             : // class MergeEntrys
     148             : //
     149             : 
     150           0 : sal_Bool MergeEntrys::GetText( OString &rReturn,
     151             :     sal_uInt16 nTyp, const OString &nLangIndex, sal_Bool bDel )
     152             : {
     153             : 
     154           0 :     sal_Bool bReturn=sal_True;
     155           0 :     switch ( nTyp ) {
     156             :         case STRING_TYP_TEXT :
     157           0 :             rReturn = sText[ nLangIndex ];
     158           0 :             if ( bDel )
     159           0 :                 sText[ nLangIndex ] = "";
     160           0 :             bReturn = bTextFirst[ nLangIndex ];
     161           0 :             bTextFirst[ nLangIndex ] = sal_False;
     162           0 :             break;
     163             :         case STRING_TYP_QUICKHELPTEXT :
     164           0 :             rReturn = sQuickHelpText[ nLangIndex ];
     165           0 :             if ( bDel )
     166           0 :                 sQuickHelpText[ nLangIndex ] = "";
     167           0 :             bReturn = bQuickHelpTextFirst[ nLangIndex ];
     168           0 :             bQuickHelpTextFirst[ nLangIndex ] = sal_False;
     169           0 :             break;
     170             :         case STRING_TYP_TITLE :
     171           0 :             rReturn = sTitle[ nLangIndex ];
     172           0 :             if ( bDel )
     173           0 :                 sTitle[ nLangIndex ] = "";
     174           0 :             bReturn = bTitleFirst[ nLangIndex ];
     175           0 :             bTitleFirst[ nLangIndex ] = sal_False;
     176           0 :             break;
     177             :     }
     178           0 :     return bReturn;
     179             : }
     180             : 
     181             : 
     182           0 : OString MergeEntrys::GetQTZText(const ResData& rResData, const OString& rOrigText)
     183             : {
     184           0 :     const OString sFilename = rResData.sFilename.copy(rResData.sFilename.lastIndexOf('/')+1);
     185             :     const OString sKey =
     186           0 :         PoEntry::genKeyId(sFilename + rResData.sGId + rResData.sId + rResData.sResTyp + rOrigText);
     187           0 :     return sKey + "||" + rOrigText;
     188             : }
     189             : 
     190             : //
     191             : // class MergeDataHashMap
     192             : //
     193             : 
     194           0 : std::pair<MergeDataHashMap::iterator,bool> MergeDataHashMap::insert(const OString& rKey, MergeData* pMergeData)
     195             : {
     196           0 :     std::pair<iterator,bool> aTemp = m_aHashMap.insert(HashMap_t::value_type( rKey, pMergeData ));
     197           0 :     if( m_aHashMap.size() == 1 )
     198             :     {
     199             :         // When first insert, set an iterator to the first element
     200           0 :         aFirstInOrder = aTemp.first;
     201             :     }
     202             :     else
     203             :     {
     204             :         // Define insertion order by setting an iterator to the next element.
     205           0 :         aLastInsertion->second->m_aNextData = aTemp.first;
     206             :     }
     207           0 :     aLastInsertion = aTemp.first;
     208           0 :     return aTemp;
     209             : }
     210             : 
     211         324 : MergeDataHashMap::iterator MergeDataHashMap::find(const OString& rKey)
     212             : {
     213         324 :     iterator aHint = m_aHashMap.end();
     214             : 
     215             :     // Add a hint
     216         324 :     if( bFirstSearch && !m_aHashMap.empty() )
     217             :     {
     218           0 :         aHint = aFirstInOrder;
     219             :     }
     220         324 :     else if( aLastFound == aLastInsertion )
     221             :     {
     222             :         // Next to the last element is the first element
     223         324 :         aHint = aFirstInOrder;
     224             :     }
     225           0 :     else if( aLastFound != m_aHashMap.end() && aLastFound != aLastInsertion )
     226             :     {
     227           0 :         aHint = aLastFound->second->m_aNextData;
     228             :     }
     229             : 
     230             :     // If hint works than no need for search
     231         324 :     if( aHint != m_aHashMap.end() && aHint->first == rKey )
     232             :     {
     233           0 :         aLastFound = aHint;
     234             :     }
     235             :     else
     236             :     {
     237         324 :         aLastFound = m_aHashMap.find(rKey);
     238             :     }
     239             : 
     240         324 :     bFirstSearch = false;
     241         324 :     return aLastFound;
     242             : }
     243             : 
     244             : //
     245             : // class MergeData
     246             : //
     247             : 
     248           0 : MergeData::MergeData(
     249             :     const OString &rTyp, const OString &rGID,
     250             :     const OString &rLID , const OString &rFilename )
     251             :     : sTyp( rTyp ),
     252             :     sGID( rGID ),
     253             :     sLID( rLID ) ,
     254             :     sFilename( rFilename ),
     255           0 :     pMergeEntrys( new MergeEntrys() )
     256             : {
     257           0 : }
     258             : 
     259           0 : MergeData::~MergeData()
     260             : {
     261           0 :     delete pMergeEntrys;
     262           0 : }
     263             : 
     264           0 : MergeEntrys* MergeData::GetMergeEntries()
     265             : {
     266           0 :     return pMergeEntrys;
     267             : }
     268             : 
     269           0 : sal_Bool MergeData::operator==( ResData *pData )
     270             : {
     271           0 :     return pData->sId == sLID && pData->sGId == sGID
     272           0 :         && pData->sResTyp.equalsIgnoreAsciiCase(sTyp);
     273             : }
     274             : 
     275             : //
     276             : // class MergeDataFile
     277             : //
     278             : 
     279          13 : MergeDataFile::MergeDataFile(
     280             :     const OString &rFileName, const OString &rFile,
     281          13 :     bool bCaseSensitive, bool bWithQtz )
     282             : {
     283          13 :     std::ifstream aInputStream( rFileName.getStr() );
     284          13 :     if ( !aInputStream.is_open() )
     285             :     {
     286           0 :         printf("Warning : Can't open po path container file\n");
     287           0 :         return;
     288             :     }
     289          26 :     std::string sPoFile;
     290          13 :     aInputStream >> sPoFile;
     291          13 :     bool bFirstLang = true;
     292          26 :     while( !aInputStream.eof() )
     293             :     {
     294           0 :         bool bSkipCurrentPOFile = false;
     295           0 :         const OString sFileName( lcl_NormalizeFilename(rFile) );
     296           0 :         const bool bReadAll = sFileName.isEmpty();
     297           0 :         const OString sPoFileName(sPoFile.data(), sPoFile.length());
     298           0 :         PoIfstream aPoInput;
     299           0 :         aPoInput.open( sPoFileName );
     300           0 :         if ( !aPoInput.isOpen() )
     301             :         {
     302           0 :             printf( "Warning : Can't open %s\n", sPoFileName.getStr() );
     303           0 :             return;
     304             :         }
     305             : 
     306           0 :         OString sLang;
     307             :         //Get language id from path
     308             :         {
     309           0 :             const OString sTransSource("translations/source/");
     310             :             const sal_Int32 nStart =
     311           0 :                 sPoFileName.indexOf(sTransSource)+sTransSource.getLength();
     312             :             const sal_Int32 nCount =
     313           0 :                 sPoFileName.indexOf('/',nStart) - nStart;
     314           0 :             sLang = sPoFileName.copy(nStart,nCount);
     315             :         }
     316           0 :         aLanguageSet.insert( sLang );
     317           0 :         PoEntry aNextPo;
     318           0 :         do
     319             :         {
     320           0 :             if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
     321             :             {
     322           0 :                 bSkipCurrentPOFile = true;
     323           0 :                 break;
     324             :             }
     325           0 :         } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
     326           0 :         while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ) && !bSkipCurrentPOFile )
     327             :         {
     328           0 :             PoEntry aActPo( aNextPo );
     329             : 
     330           0 :             bool bInSameComp = false;
     331           0 :             OString sText;
     332           0 :             OString sQHText;
     333           0 :             OString sTitle;
     334           0 :             OString sExText;
     335           0 :             OString sExQHText;
     336           0 :             OString sExTitle;
     337           0 :             do
     338             :             {
     339           0 :                 if( bInSameComp )
     340           0 :                     aActPo = aNextPo;
     341           0 :                 OString sTemp = aActPo.getMsgStr();
     342           0 :                 if( aActPo.isFuzzy() || sTemp.isEmpty() )
     343           0 :                     sTemp = aActPo.getMsgId();
     344           0 :                 switch( aActPo.getType() )
     345             :                 {
     346             :                     case PoEntry::TTEXT:
     347           0 :                         sText = sTemp;
     348           0 :                         sExText = aActPo.getMsgId();
     349           0 :                         break;
     350             :                     case PoEntry::TQUICKHELPTEXT:
     351           0 :                         sQHText = sTemp;
     352           0 :                         sExQHText = aActPo.getMsgId();
     353           0 :                         break;
     354             :                     case PoEntry::TTITLE:
     355           0 :                         sTitle = sTemp;
     356           0 :                         sExTitle = aActPo.getMsgId();
     357           0 :                         break;
     358             :                 }
     359           0 :                 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
     360             :                 {
     361           0 :                     bSkipCurrentPOFile = true;
     362           0 :                     break;
     363           0 :                 }
     364           0 :             } while( !aPoInput.eof() &&
     365             :                 ( bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo) ) );
     366             : 
     367             :             InsertEntry(
     368             :                 aActPo.getResourceType(), aActPo.getGroupId(),
     369             :                 aActPo.getLocalId(), sLang, sText,
     370             :                 sQHText, sTitle, aActPo.getSourceFile(),
     371           0 :                 bFirstLang, bCaseSensitive );
     372             : 
     373           0 :             if( bFirstLang && bWithQtz &&
     374           0 :                 ( strcmp(getenv("ENABLE_RELEASE_BUILD"),"TRUE") ) )
     375             :             {
     376           0 :                 aLanguageSet.insert("qtz");
     377             :                 InsertEntry(
     378             :                     aActPo.getResourceType(), aActPo.getGroupId(),
     379             :                     aActPo.getLocalId(), "qtz",
     380             :                     sExText, sExQHText,
     381             :                     sExTitle, aActPo.getSourceFile(),
     382           0 :                     false, bCaseSensitive );
     383             :             }
     384           0 :         }
     385           0 :         aPoInput.close();
     386           0 :         aInputStream >> sPoFile;
     387           0 :         bFirstLang = false;
     388           0 :     }
     389          26 :     aInputStream.close();
     390             : }
     391             : 
     392          26 : MergeDataFile::~MergeDataFile()
     393             : {
     394          13 :     for (MergeDataHashMap::iterator aI = aMap.begin(), aEnd = aMap.end(); aI != aEnd; ++aI)
     395           0 :         delete aI->second;
     396          13 : }
     397             : 
     398          13 : std::vector<OString> MergeDataFile::GetLanguages() const
     399             : {
     400          13 :     return std::vector<OString>(aLanguageSet.begin(),aLanguageSet.end());
     401             : }
     402             : 
     403         324 : MergeData *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
     404             : {
     405         324 :     OString sOldG = pResData->sGId;
     406         648 :     OString sOldL = pResData->sId;
     407         648 :     OString sGID = pResData->sGId;
     408         648 :     OString sLID;
     409         324 :     if (sGID.isEmpty())
     410          75 :         sGID = pResData->sId;
     411             :     else
     412         249 :         sLID = pResData->sId;
     413         324 :     pResData->sGId = sGID;
     414         324 :     pResData->sId = sLID;
     415             : 
     416         648 :     OString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
     417             : 
     418         324 :     MergeDataHashMap::const_iterator mit = aMap.find( sKey );
     419         324 :     if(mit != aMap.end())
     420             :     {
     421           0 :         pResData->sGId = sOldG;
     422           0 :         pResData->sId = sOldL;
     423           0 :         return mit->second;
     424             :     }
     425         324 :     pResData->sGId = sOldG;
     426         324 :     pResData->sId = sOldL;
     427         648 :     return NULL;
     428             : }
     429             : 
     430         324 : MergeEntrys *MergeDataFile::GetMergeEntrys( ResData *pResData )
     431             : {
     432             :     // search for requested MergeEntrys
     433         324 :     MergeData *pData = GetMergeData( pResData );
     434         324 :     if ( pData )
     435           0 :         return pData->GetMergeEntries();
     436         324 :     return NULL;
     437             : }
     438             : 
     439           0 : MergeEntrys *MergeDataFile::GetMergeEntrysCaseSensitive( ResData *pResData )
     440             : {
     441             :     // search for requested MergeEntrys
     442           0 :     MergeData *pData = GetMergeData( pResData , true );
     443           0 :     if ( pData )
     444           0 :         return pData->GetMergeEntries();
     445           0 :     return NULL;
     446             : }
     447             : 
     448           0 : void MergeDataFile::InsertEntry(
     449             :     const OString &rTYP, const OString &rGID,
     450             :     const OString &rLID, const OString &nLANG,
     451             :     const OString &rTEXT, const OString &rQHTEXT,
     452             :     const OString &rTITLE, const OString &rInFilename,
     453             :     bool bFirstLang, bool bCaseSensitive )
     454             : {
     455           0 :     MergeData *pData = 0;
     456             : 
     457             :     // search for MergeData
     458           0 :     OString sKey = CreateKey(rTYP , rGID , rLID , rInFilename , bCaseSensitive);
     459             : 
     460           0 :     if( !bFirstLang )
     461             :     {
     462           0 :         MergeDataHashMap::const_iterator mit = aMap.find( sKey );
     463           0 :         if(mit != aMap.end())
     464           0 :             pData = mit->second;
     465             : 
     466             :     }
     467             : 
     468           0 :     if( !pData )
     469             :     {
     470           0 :         pData = new MergeData( rTYP, rGID, rLID, rInFilename );
     471           0 :         aMap.insert( sKey, pData );
     472             :     }
     473             : 
     474             : 
     475             :     // insert the cur string
     476           0 :     MergeEntrys *pMergeEntrys = pData->GetMergeEntries();
     477           0 :     if( nLANG =="qtz" )
     478             :     {
     479           0 :         const OString sTemp = rInFilename + rGID + rLID + rTYP;
     480             :         pMergeEntrys->InsertEntry(
     481             :             nLANG,
     482           0 :             rTEXT.isEmpty()? rTEXT : PoEntry::genKeyId(sTemp + rTEXT) + "||" + rTEXT,
     483           0 :             rQHTEXT.isEmpty()? rQHTEXT : PoEntry::genKeyId(sTemp + rQHTEXT) + "||" + rQHTEXT,
     484           0 :             rTITLE.isEmpty()? rTITLE : PoEntry::genKeyId(sTemp + rTITLE) + "||" + rTITLE );
     485             :     }
     486             :     else
     487             :     {
     488           0 :         pMergeEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
     489           0 :     }
     490           0 : }
     491             : 
     492         324 : OString MergeDataFile::CreateKey(const OString& rTYP, const OString& rGID,
     493             :     const OString& rLID, const OString& rFilename, bool bCaseSensitive)
     494             : {
     495         324 :     static const OString sStroke('-');
     496         324 :     OString sKey( rTYP );
     497         324 :     sKey += sStroke;
     498         324 :     sKey += rGID;
     499         324 :     sKey += sStroke;
     500         324 :     sKey += rLID;
     501         324 :     sKey += sStroke;
     502         324 :     sKey += lcl_NormalizeFilename(rFilename);
     503             :     OSL_TRACE("created key: %s", sKey.getStr());
     504         324 :     if(bCaseSensitive)
     505           0 :         return sKey;         // officecfg case sensitive identifier
     506         324 :     return sKey.toAsciiUpperCase();
     507             : }
     508             : 
     509             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10