[Libreoffice-commits] .: Branch 'feature/killsdf' - l10ntools/inc l10ntools/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Sun Sep 30 08:12:16 PDT 2012


 l10ntools/inc/po.hxx          |   74 +++++++++++-
 l10ntools/source/localize.cxx |   52 +++++---
 l10ntools/source/merge.cxx    |   98 +++++++++++-----
 l10ntools/source/po.cxx       |  246 ++++++++++++++++++++++++++++++++++--------
 l10ntools/source/renewpo.cxx  |   88 +++++++++------
 5 files changed, 426 insertions(+), 132 deletions(-)

New commits:
commit ca12be682f28969b15b30539230ca40de88fc36d
Author: Zolnai Tamás <zolnaitamas2000 at gmail.com>
Date:   Fri Sep 28 17:52:13 2012 +0200

    Make Po classes robuster
    
    -Make PoOfstream\PoIfstream classes for
    checked po input\output
    -Make copyability obvious
    -Handle runtime errors with exceptions
    -Use assertions to define exceptations
    for programmers
    Plus some correction
    -Use simplier indentation
    -In renewpo.cxx, define sdf file as a tempfile
    instead of make it in current location
    -Use constructor to renew poheader
    -Use const where needed
    
    Change-Id: Ic11ce3b9eee9a9fa9fbc4ccda154623160ad9d8a
    Reviewed-on: https://gerrit.libreoffice.org/728
    Reviewed-by: Andras Timar <atimar at suse.com>
    Tested-by: Andras Timar <atimar at suse.com>

diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx
index 686c9f3..76312a4 100644
--- a/l10ntools/inc/po.hxx
+++ b/l10ntools/inc/po.hxx
@@ -12,10 +12,15 @@
 
 #include <fstream>
 #include <rtl/string.hxx>
+#include <boost/noncopyable.hpp>
+
+class PoOfstream;
+class PoIfstream;
 
 class GenPoEntry
 {
 private:
+
     OString    m_sWhiteSpace;
     OString    m_sExtractCom;
     OString    m_sReference;
@@ -27,8 +32,10 @@ private:
     OString    m_sKeyId;
 
 public:
+
                         GenPoEntry();
     virtual             ~GenPoEntry();
+                        //Default copy constructor and copy operator work well
 
     virtual OString     getWhiteSpace() const   { return m_sWhiteSpace; }
     virtual OString     getExtractCom() const   { return m_sExtractCom; }
@@ -49,25 +56,33 @@ public:
     virtual void        setFuzzy(const bool bFuzzy);
     virtual void        genKeyId();
 
-    virtual void        writeToFile(std::ofstream& rOFStream);
+    virtual void        writeToFile(std::ofstream& rOFStream) const;
     virtual void        readFromFile(std::ifstream& rIFStream);
 };
 
 class PoEntry
 {
 private:
+
     GenPoEntry m_aGenPo;
+    bool m_bIsInitialized;
 
 public:
-    enum SDFPARTS { PROJECT, SOURCEFILE, DUMMY, RESOURCETYPE, GROUPID,
+
+    friend class PoOfstream;
+    friend class PoIfstream;
+
+    enum SDFPART { PROJECT, SOURCEFILE, DUMMY, RESOURCETYPE, GROUPID,
                     LOCALID, HELPID, PLATFORM, WIDTH, LANGUAGEID,
                     TEXT, HELPTEXT, QUICKHELPTEXT, TITLE, TIMESTAMP };
     enum TYPE { TTEXT=TEXT, TQUICKHELPTEXT=QUICKHELPTEXT, TTITLE=TITLE };
+    enum Exception { INVALIDSDFLINE };
 
                     PoEntry();
                     PoEntry(const OString& rSDFLine,
                             const TYPE eType = TTEXT);
                     ~PoEntry();
+                    //Default copy constructor and copy operator work well
 
     OString         getSourceFile() const;
     OString         getGroupId() const;
@@ -77,15 +92,11 @@ public:
     OString         getUnTransStr() const;
     OString         getTransStr() const;
     bool            getFuzzy() const;
-    bool            isNull() const;
     OString         getKeyId() const;
     void            setUnTransStr(const OString& rUnTransStr);
     void            setTransStr(const OString& rTransStr);
     void            setFuzzy(const bool bFuzzy);
 
-    void            writeToFile(std::ofstream& rOFStream);
-    void            readFromFile(std::ifstream& rIFStream);
-
     static bool     IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2);
 
 };
@@ -93,16 +104,63 @@ public:
 class PoHeader
 {
 private:
+
     GenPoEntry m_aGenPo;
+    bool m_bIsInitialized;
 
 public:
+
+    friend class PoOfstream;
+    friend class PoIfstream;
+
                     PoHeader();
                     PoHeader( const OString& rExtSrc );
+                    PoHeader( std::ifstream& rOldPo );
                     ~PoHeader();
+                    //Default copy constructor and copy operator work well
 
     OString         getLanguage() const;
-    void            writeToFile(std::ofstream& rOFStream);
-    void            readFromFile(std::ifstream& rIFStream);
+};
+
+class PoOfstream: private boost::noncopyable
+{
+private:
+
+    std::ofstream   m_aOutPut;
+    bool            m_bIsAfterHeader;
+
+public:
+            PoOfstream();
+            ~PoOfstream();
+    bool    isOpen() const  { return m_aOutPut.is_open(); }
+
+    void    open(const OString& rFileName);
+    void    close();
+    void    writeHeader(const PoHeader& rHeader);
+    void    writeEntry(const PoEntry& rPo);
+};
+
+class PoIfstream: private boost::noncopyable
+{
+private:
+
+    std::ifstream   m_aInPut;
+    bool            m_bIsAfterHeader;
+    bool            m_bEof;
+
+public:
+
+    enum Exception { INVALIDENTRY, INVALIDHEADER };
+
+            PoIfstream();
+            ~PoIfstream();
+    bool    isOpen() const  { return m_aInPut.is_open(); }
+    bool    eof() const     { return m_bEof; }
+
+    void    open(const OString& rFileName);
+    void    close();
+    void    readHeader(PoHeader& rHeader);
+    void    readEntry(PoEntry& rPo);
 };
 
 #endif // _PO_INCLUDED
diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx
index a9a20c8..87ee83b 100644
--- a/l10ntools/source/localize.cxx
+++ b/l10ntools/source/localize.cxx
@@ -170,7 +170,7 @@ bool passesPositiveList(rtl::OUString const & url) {
 void handleCommand(
     rtl::OUString const & project, rtl::OUString const & projectRoot,
     rtl::OUString const & url, rtl::OUString const & actualDir,
-    std::ofstream & outPut, rtl::OUString const & executable, bool positive)
+    PoOfstream & rPoOutPut, rtl::OUString const & executable, bool positive)
 {
     if (positive ? passesPositiveList(url) : passesNegativeList(url)) {
         rtl::OUString inPath;
@@ -241,7 +241,7 @@ void handleCommand(
 
         std::string s;
         std::getline(in, s);
-        if (!in.eof() && !outPut.is_open())
+        if (!in.eof() && !rPoOutPut.isOpen())
         {
             rtl::OUString outDirUrl;
             if (osl::FileBase::getFileURLFromSystemPath(actualDir.
@@ -263,8 +263,14 @@ void handleCommand(
                 std::cerr << "Error: Cannot convert pathname from UTF-16\n";
                 throw false; //TODO
             }
-            outPut.open(outFilePath.getStr(),
-                        std::ios_base::out | std::ios_base::trunc);
+            rPoOutPut.open(outFilePath.getStr());
+            if (!rPoOutPut.isOpen())
+            {
+                std::cerr
+                    << "Error: Cannot open po file "
+                    << outFilePath.getStr() << "\n";
+                throw false; //TODO
+            }
             rtl::OString relativPath;
             if (!inPath.copy(inPath.indexOf(project),
                 inPath.lastIndexOf('/')-inPath.indexOf(project)).
@@ -275,18 +281,28 @@ void handleCommand(
                 std::cerr << "Error: Cannot convert pathname from UTF-16\n";
                 throw false; //TODO
             }
-            PoHeader(relativPath).writeToFile(outPut);
+            rPoOutPut.writeHeader(PoHeader(relativPath));
         }
         while (!in.eof())
         {
             OString sLine = OString(s.data(),s.length());
-
-            if (!sLine.getToken(PoEntry::TEXT,'\t').isEmpty())
-                PoEntry(sLine).writeToFile(outPut);
-            if (!sLine.getToken(PoEntry::QUICKHELPTEXT,'\t').isEmpty())
-                PoEntry(sLine,PoEntry::TQUICKHELPTEXT).writeToFile(outPut);
-            if (!sLine.getToken(PoEntry::TITLE,'\t').isEmpty())
-                PoEntry(sLine,PoEntry::TTITLE).writeToFile(outPut);
+            try
+            {
+                if (!sLine.getToken(PoEntry::TEXT,'\t').isEmpty())
+                    rPoOutPut.writeEntry(PoEntry(sLine));
+                if (!sLine.getToken(PoEntry::QUICKHELPTEXT,'\t').isEmpty())
+                    rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TQUICKHELPTEXT));
+                if (!sLine.getToken(PoEntry::TITLE,'\t').isEmpty())
+                    rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TTITLE));
+            }
+            catch(PoEntry::Exception& aException)
+            {
+                if(aException == PoEntry::INVALIDSDFLINE)
+                {
+                    std::cerr << executable << "'s input is invalid\n";
+                    throw false; //TODO
+                }
+            }
             std::getline(in, s);
         };
         in.close();
@@ -296,7 +312,7 @@ void handleCommand(
 void handleFile(
     rtl::OUString const & project, rtl::OUString const & projectRoot,
     rtl::OUString const & url, rtl::OUString const & actualDir,
-    std::ofstream &  outPut)
+    PoOfstream & rPoOutPut)
 {
     struct Command {
         char const * extension;
@@ -319,7 +335,7 @@ void handleFile(
                 commands[i].extension, commands[i].extensionLength))
         {
             handleCommand(
-                project, projectRoot, url, actualDir, outPut,
+                project, projectRoot, url, actualDir, rPoOutPut,
                 rtl::OUString::createFromAscii(commands[i].executable),
                 commands[i].positive);
             break;
@@ -430,7 +446,7 @@ void handleDirectory(
     rtl::OUString const & url, int level, rtl::OUString const & project,
     rtl::OUString const & projectRoot, rtl::OUString const & actualDir)
 {
-    std::ofstream output;
+    PoOfstream aPoOutPut;
     osl::Directory dir(url);
     if (dir.open() != osl::FileBase::E_None) {
         std::cerr
@@ -494,13 +510,13 @@ void handleDirectory(
                 }
             } else {
                 handleFile(project, projectRoot,
-                           stat.getFileURL(), actualDir, output);
+                           stat.getFileURL(), actualDir, aPoOutPut);
             }
             break;
         }
     }
-    if (output.is_open())
-        output.close();
+    if (aPoOutPut.isOpen())
+        aPoOutPut.close();
     if (dir.close() != osl::FileBase::E_None) {
         std::cerr << "Error: Cannot close directory\n";
         throw false; //TODO
diff --git a/l10ntools/source/merge.cxx b/l10ntools/source/merge.cxx
index b87024a..7e6c595 100644
--- a/l10ntools/source/merge.cxx
+++ b/l10ntools/source/merge.cxx
@@ -45,6 +45,27 @@ namespace
                 rFilename.lastIndexOf( '\\' ),
                 rFilename.lastIndexOf( '/' ))+1);
     };
+
+    static bool lcl_ReadPoChecked(
+        PoEntry& o_rPoEntry, PoIfstream& rPoFile,
+        const std::string& rFileName)
+    {
+        try
+        {
+            rPoFile.readEntry( o_rPoEntry );
+        }
+        catch( PoIfstream::Exception& aException )
+        {
+            if( aException == PoIfstream::INVALIDENTRY )
+            {
+                printf(
+                    "Warning : %s contains invalid entry\n",
+                    rFileName.c_str() );
+                return false;
+            }
+        }
+        return true;
+    }
 }
 
 //
@@ -142,8 +163,8 @@ MergeDataFile::MergeDataFile(
     const rtl::OString &rFile,
     bool bCaseSensitive)
 {
-    std::ifstream aInputStream(rFileName.getStr());
-    if (!aInputStream.is_open())
+    std::ifstream aInputStream( rFileName.getStr() );
+    if ( !aInputStream.is_open() )
     {
         printf("Warning : Can't open po path container file");
         return;
@@ -151,30 +172,45 @@ MergeDataFile::MergeDataFile(
     std::string sPoFileName;
     aInputStream >> sPoFileName;
     bool bFirstLang = true;
-    while(!aInputStream.eof())
+    while( !aInputStream.eof() )
     {
-        std::ifstream aPoFile(sPoFileName.c_str());
         const OString sHACK("HACK");
-        const OString sFileName(lcl_NormalizeFilename(rFile));
-
-        if (!aPoFile.is_open())
+        const OString sFileName( lcl_NormalizeFilename(rFile) );
+        PoIfstream aPoInput;
+        aPoInput.open( OString(sPoFileName.data(), sPoFileName.length()) );
+        if ( !aPoInput.isOpen() )
         {
-            printf("Warning : Can't open %s\n", sPoFileName.c_str());
+            printf( "Warning : Can't open %s\n", sPoFileName.c_str() );
             return;
         }
-
         PoHeader aPoHeader;
-        aPoHeader.readFromFile(aPoFile);
+        try
+        {
+            aPoInput.readHeader( aPoHeader );
+        }
+        catch( PoIfstream::Exception& aException )
+        {
+            if( aException == PoIfstream::INVALIDHEADER )
+            {
+                printf(
+                    "Warning : %s has invalid header\n",
+                    sPoFileName.c_str() );
+                return;
+            }
+        }
         const OString nLANG = aPoHeader.getLanguage();
-        aLanguageSet.insert(nLANG);
+        aLanguageSet.insert( nLANG );
         PoEntry aNextPo;
         do
         {
-            aNextPo.readFromFile(aPoFile);
-        } while( !aNextPo.isNull() && aNextPo.getSourceFile() != sFileName );
-        while( !aNextPo.isNull() && aNextPo.getSourceFile() == sFileName )
+            if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
+            {
+                return;
+            }
+        } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName );
+        while( !aPoInput.eof() && aNextPo.getSourceFile() == sFileName )
         {
-            PoEntry aActPo(aNextPo);
+            PoEntry aActPo( aNextPo );
 
             bool bInSameComp = false;
             OString sText;
@@ -189,7 +225,7 @@ MergeDataFile::MergeDataFile(
             do
             {
                 if( bInSameComp )
-                    aActPo = PoEntry(aNextPo);
+                    aActPo = aNextPo;
                 OString sTemp = aActPo.getTransStr();
                 if( aActPo.getFuzzy() || sTemp.isEmpty() )
                     sTemp = aActPo.getUnTransStr();
@@ -211,25 +247,29 @@ MergeDataFile::MergeDataFile(
                         sQTZTitle = aActPo.getKeyId();
                         break;
                 }
-                aNextPo.readFromFile(aPoFile);
-            } while(!aNextPo.isNull() &&
-                    (bInSameComp = PoEntry::IsInSameComp(aActPo,aNextPo)));
+                if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
+                {
+                    return;
+                }
+            } while( !aPoInput.eof() &&
+                ( bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo) ) );
+
+            InsertEntry(
+                aActPo.getResourceType(), aActPo.getGroupId(),
+                aActPo.getLocalId(), sHACK, nLANG, sText,
+                sQHText, sTitle, sFileName, bCaseSensitive );
 
-            InsertEntry( aActPo.getResourceType(), aActPo.getGroupId(),
-                         aActPo.getLocalId(), sHACK, nLANG, sText,
-                         sQHText, sTitle, sFileName, bCaseSensitive );
             if( bFirstLang )
             {
                 aLanguageSet.insert("qtz");
-                InsertEntry( aActPo.getResourceType(), aActPo.getGroupId(),
-                             aActPo.getLocalId(), sHACK, "qtz",
-                             sQTZText + "‖" + sExText,
-                             sQTZQHText + "‖" + sExQHText,
-                             sQTZTitle + "‖" + sExTitle,
-                             sFileName, bCaseSensitive );
+                InsertEntry(
+                    aActPo.getResourceType(), aActPo.getGroupId(),
+                    aActPo.getLocalId(), sHACK, "qtz",
+                    sQTZText + "‖" + sExText, sQTZQHText + "‖" + sExQHText,
+                    sQTZTitle + "‖" + sExTitle, sFileName, bCaseSensitive );
             }
         }
-        aPoFile.close();
+        aPoInput.close();
         aInputStream >> sPoFileName;
         bFirstLang = false;
     }
diff --git a/l10ntools/source/po.cxx b/l10ntools/source/po.cxx
index b2082a7..cf0b963 100644
--- a/l10ntools/source/po.cxx
+++ b/l10ntools/source/po.cxx
@@ -13,10 +13,13 @@
 #include <regexp/reclass.hxx>
 #include <rtl/ustring.hxx>
 
-#include <string>
 #include <cstring>
 #include <ctime>
+#include <cassert>
+
 #include <vector>
+#include <string>
+
 #include <boost/crc.hpp>
 
 #include "po.hxx"
@@ -49,7 +52,7 @@ OString ImplEscapeText(const OString& rText,
                        const OString& rUnEscaped= POUNESCAPED,
                        const OString& rEscaped = POESCAPED)
 {
-    if(rEscaped.getLength()!=2*rUnEscaped.getLength()) throw;
+    assert( rEscaped.getLength() == 2*rUnEscaped.getLength() );
     OString sResult = rText;
     int nCount = 0;
     for(sal_Int32 nIndex=0; nIndex<rText.getLength(); ++nIndex)
@@ -67,7 +70,7 @@ OString ImplUnEscapeText(const OString& rText,
                          const OString& rEscaped = POESCAPED,
                          const OString& rUnEscaped = POUNESCAPED)
 {
-    if(rEscaped.getLength()!=2*rUnEscaped.getLength()) throw;
+    assert( rEscaped.getLength() == 2*rUnEscaped.getLength() );
     OString sResult = rText;
     int nCount = 0;
     for(sal_Int32 nIndex=0; nIndex<rText.getLength()-1; ++nIndex)
@@ -171,11 +174,11 @@ void GenPoEntry::setFuzzy(const bool bFuzzy)
 //Set keyid
 void GenPoEntry::genKeyId()
 {
-    m_sKeyId = ImplGenKeyId(m_sReference + m_sContext + m_sUnTransStr);
+    m_sKeyId = ImplGenKeyId( m_sReference + m_sContext + m_sUnTransStr );
 }
 
 //Write to file
-void GenPoEntry::writeToFile(std::ofstream& rOFStream)
+void GenPoEntry::writeToFile(std::ofstream& rOFStream) const
 {
     if ( !m_sWhiteSpace.isEmpty() )
         rOFStream << m_sWhiteSpace.getStr();
@@ -250,7 +253,7 @@ void GenPoEntry::readFromFile(std::ifstream& rIFStream)
             break;
         getline(rIFStream,sTemp);
     }
-    if (m_sKeyId.isEmpty())
+    if( m_sKeyId.isEmpty() && !m_sUnTransStr.isEmpty() )
         genKeyId();
  }
 
@@ -384,23 +387,33 @@ OString ImplEscapeSDFText(const OString& rText,const bool bHelpText = false)
 //Default constructor
 PoEntry::PoEntry()
     : m_aGenPo( GenPoEntry() )
+    , m_bIsInitialized( false )
 {
 }
 
 //Construct PoEntry from sdfline
 PoEntry::PoEntry(const OString& rSDFLine, const TYPE eType)
     : m_aGenPo( GenPoEntry() )
+    , m_bIsInitialized( false )
 {
     std::vector<OString> vParts;
     ImplSplitAt(rSDFLine,'\t',vParts);
-    if(vParts.size()!=15) throw;
+    if( vParts.size()!=15 ||
+        vParts[SOURCEFILE].isEmpty() ||
+        vParts[GROUPID].isEmpty() ||
+        vParts[RESOURCETYPE].isEmpty() ||
+        vParts[eType].isEmpty() )
+    {
+        throw INVALIDSDFLINE;
+    }
     m_aGenPo.setWhiteSpace("\n");
 
     m_aGenPo.setReference(vParts[SOURCEFILE].
         copy(vParts[SOURCEFILE].lastIndexOf("\\")+1));
 
     m_aGenPo.setExtractCom(vParts[HELPTEXT]);
-    OString sContext = vParts[GROUPID] + "\n" +
+    OString sContext =
+        vParts[GROUPID] + "\n" +
         (vParts[LOCALID].isEmpty() ? "" : vParts[LOCALID] + "\n") +
         vParts[RESOURCETYPE];
     switch(eType){
@@ -410,12 +423,13 @@ PoEntry::PoEntry(const OString& rSDFLine, const TYPE eType)
         sContext += ".quickhelptext"; break;
     case TTITLE:
         sContext += ".title"; break;
-    default:
-        throw; break;
+    /*Default case is unneeded because the type of eType has
+      only three element*/
     }
     m_aGenPo.setContext(sContext);
     setUnTransStr(vParts[eType]);
     m_aGenPo.genKeyId();
+    m_bIsInitialized = true;
 }
 
 //Destructor
@@ -426,18 +440,21 @@ PoEntry::~PoEntry()
 //Get name of file from which entry is extracted
 OString PoEntry::getSourceFile() const
 {
+    assert( m_bIsInitialized );
     return m_aGenPo.getReference();
 }
 
 //Get groupid
 OString PoEntry::getGroupId() const
 {
+    assert( m_bIsInitialized );
     return m_aGenPo.getContext().getToken(0,'\n');
 }
 
 //Get localid
 OString PoEntry::getLocalId() const
 {
+    assert( m_bIsInitialized );
     const OString sContext = m_aGenPo.getContext();
     if (sContext.indexOf('\n')==sContext.lastIndexOf('\n'))
         return OString();
@@ -448,6 +465,7 @@ OString PoEntry::getLocalId() const
 //Get the type of component from which entry is extracted
 OString PoEntry::getResourceType() const
 {
+    assert( m_bIsInitialized );
     const OString sContext = m_aGenPo.getContext();
     if (sContext.indexOf('\n')==sContext.lastIndexOf('\n'))
         return sContext.getToken(1,'\n').getToken(0,'.');
@@ -459,30 +477,28 @@ OString PoEntry::getResourceType() const
 PoEntry::TYPE PoEntry::getType() const
 {
     const OString sContext = m_aGenPo.getContext();
-    if (sContext.endsWith(".text"))
+    const OString sType = sContext.copy( sContext.indexOf('.') + 1 );
+    assert( m_bIsInitialized &&
+        (sType == "text" || sType == "quickhelptext" || sType == "title") );
+    if ( sType == "text" )
         return TTEXT;
-    else if (sContext.endsWith(".quickhelptext"))
+    else if ( sType == "quickhelptext" )
         return TQUICKHELPTEXT;
-    else if (sContext.endsWith(".title"))
+    else
         return TTITLE;
-    else throw;
 }
 
 //Check wheather entry is fuzzy
 bool PoEntry::getFuzzy() const
 {
+    assert( m_bIsInitialized );
     return m_aGenPo.getFuzzy();
 }
 
-//Check wheather entry is null
-bool PoEntry::isNull() const
-{
-    return m_aGenPo.isNull();
-}
-
 //Get keyid
 OString PoEntry::getKeyId() const
 {
+    assert( m_bIsInitialized );
     return m_aGenPo.getKeyId();
 }
 
@@ -490,15 +506,19 @@ OString PoEntry::getKeyId() const
 //Get translation string in sdf/merge format
 OString PoEntry::getUnTransStr() const
 {
-    return ImplEscapeSDFText(m_aGenPo.getUnTransStr(),
-                             getSourceFile().endsWith(".xhp"));
+    assert( m_bIsInitialized );
+    return
+        ImplEscapeSDFText(
+            m_aGenPo.getUnTransStr(), getSourceFile().endsWith(".xhp") );
 }
 
 //Get translated string in sdf/merge format
 OString PoEntry::getTransStr() const
 {
-    return ImplEscapeSDFText(m_aGenPo.getTransStr(),
-                             getSourceFile().endsWith(".xhp"));
+    assert( m_bIsInitialized );
+    return
+        ImplEscapeSDFText(
+            m_aGenPo.getTransStr(), getSourceFile().endsWith(".xhp") );
 
 }
 
@@ -524,20 +544,6 @@ void PoEntry::setFuzzy(const bool bFuzzy)
     m_aGenPo.setFuzzy(bFuzzy);
 }
 
-//Write to file
-void PoEntry::writeToFile(std::ofstream& rOFStream)
-{
-    m_aGenPo.writeToFile(rOFStream);
-}
-
-
-//Read from file
-void PoEntry::readFromFile(std::ifstream& rIFStream)
-{
-    *this = PoEntry();
-    m_aGenPo.readFromFile(rIFStream);
-}
-
 //Check whether po-s belong to the same localization component
 bool PoEntry::IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2)
 {
@@ -559,15 +565,26 @@ OString ImplGetTime()
     return pBuff;
 }
 
+OString ImplReplaceAttribute(
+    const OString& rSource, const OString& rOld, const OString& rNew )
+{
+    const sal_Int32 nFirstIndex = rSource.indexOf( rOld ) + rOld.getLength()+2;
+    const sal_Int32 nCount =
+        rSource.indexOf( "\n", nFirstIndex ) - nFirstIndex;
+    return rSource.replaceFirst( rSource.copy(nFirstIndex, nCount), rNew );
+}
+
 //Default Constructor
 PoHeader::PoHeader()
     : m_aGenPo( GenPoEntry() )
+    , m_bIsInitialized( false )
 {
 }
 
 //Template Constructor
 PoHeader::PoHeader( const OString& rExtSrc )
     : m_aGenPo( GenPoEntry() )
+    , m_bIsInitialized( false )
 {
     m_aGenPo.setExtractCom("extracted from " + rExtSrc);
     m_aGenPo.setTransStr(
@@ -583,6 +600,34 @@ PoHeader::PoHeader( const OString& rExtSrc )
         "Content-Transfer-Encoding: 8bit\n"
         "X-Genarator: LibreOffice\n"
         "X-Accelerator_Marker: ~\n"));
+    m_bIsInitialized = true;
+}
+
+
+//Constructor for old headers to renew po files
+PoHeader::PoHeader(  std::ifstream& rOldPo )
+    : m_aGenPo( GenPoEntry() )
+    , m_bIsInitialized( false )
+{
+    assert( rOldPo.is_open() );
+    m_aGenPo.readFromFile( rOldPo );
+
+    m_aGenPo.setWhiteSpace( OString() );
+    const OString sExtractCom = m_aGenPo.getExtractCom();
+    m_aGenPo.setExtractCom(
+        sExtractCom.copy( 0, sExtractCom.getLength() - 3 ) );
+
+    OString sTransStr = m_aGenPo.getTransStr();
+    sTransStr =
+        ImplReplaceAttribute( sTransStr, "Report-Msgid-Bugs-To",
+            "https://bugs.freedesktop.org/enter_bug.cgi?product="
+            "LibreOffice&bug_status=UNCONFIRMED&component=UI" );
+    sTransStr =
+        ImplReplaceAttribute( sTransStr, "X-Generator", "LibreOffice" );
+    sTransStr =
+        ImplReplaceAttribute( sTransStr, "X-Accelerator-Marker", "~" );
+    m_aGenPo.setTransStr( sTransStr );
+    m_bIsInitialized = true;
 }
 
 PoHeader::~PoHeader()
@@ -592,6 +637,7 @@ PoHeader::~PoHeader()
 //Get the language of header
 OString PoHeader::getLanguage() const
 {
+    assert( m_bIsInitialized );
     const OString sLang = "Language: ";
     const OString sTransStr = m_aGenPo.getTransStr();
     const sal_Int32 nFirstIndex = sTransStr.indexOf(sLang)+sLang.getLength();
@@ -599,18 +645,128 @@ OString PoHeader::getLanguage() const
     return sTransStr.copy(nFirstIndex,nCount);
 }
 
-//Write out to file
-void PoHeader::writeToFile(std::ofstream& rOFStream)
+//Class PoOfstream
+
+PoOfstream::PoOfstream()
+    : m_aOutPut()
+    , m_bIsAfterHeader( false )
+{
+}
+
+PoOfstream::~PoOfstream()
+{
+    if( isOpen() )
+    {
+       close();
+    }
+}
+
+void PoOfstream::open(const OString& rFileName)
 {
-    m_aGenPo.writeToFile(rOFStream);
+    assert( !isOpen() );
+    m_aOutPut.open( rFileName.getStr(),
+        std::ios_base::out | std::ios_base::trunc );
+    m_bIsAfterHeader = false;
 }
 
-//Read from file
-void PoHeader::readFromFile(std::ifstream& rIFStream)
+void PoOfstream::close()
+{
+    assert( isOpen() );
+    m_aOutPut.close();
+}
+
+void PoOfstream::writeHeader(const PoHeader& rPoHeader)
+{
+    assert( isOpen() && !m_bIsAfterHeader && rPoHeader.m_bIsInitialized );
+    rPoHeader.m_aGenPo.writeToFile( m_aOutPut );
+    m_bIsAfterHeader = true;
+}
+
+void PoOfstream::writeEntry( const PoEntry& rPoEntry )
+{
+    assert( isOpen() && m_bIsAfterHeader && rPoEntry.m_bIsInitialized );
+    rPoEntry.m_aGenPo.writeToFile( m_aOutPut );
+}
+
+//Class PoIfstream
+
+PoIfstream::PoIfstream()
+    : m_aInPut()
+    , m_bIsAfterHeader( false )
+    , m_bEof( false )
+{
+}
+
+PoIfstream::~PoIfstream()
+{
+    if( isOpen() )
+    {
+       close();
+    }
+}
+
+void PoIfstream::open( const OString& rFileName )
+{
+    assert( !isOpen() );
+    m_aInPut.open( rFileName.getStr(), std::ios_base::in );
+    m_bIsAfterHeader = false;
+    m_bEof = false;
+}
+
+void PoIfstream::close()
 {
-    *this = PoHeader();
-    m_aGenPo.readFromFile(rIFStream);
+    assert( isOpen() );
+    m_aInPut.close();
 }
 
+void PoIfstream::readHeader( PoHeader& rPoHeader )
+{
+    assert( isOpen() && !eof() && !m_bIsAfterHeader );
+    GenPoEntry aGenPo;
+    aGenPo.readFromFile( m_aInPut );
+    if( !aGenPo.getExtractCom().isEmpty() &&
+        aGenPo.getUnTransStr().isEmpty() &&
+        !aGenPo.getTransStr().isEmpty() )
+    {
+        rPoHeader.m_aGenPo = aGenPo;
+        rPoHeader.m_bIsInitialized = true;
+        m_bIsAfterHeader = true;
+    }
+    else
+    {
+        throw INVALIDHEADER;
+    }
+}
+
+void PoIfstream::readEntry( PoEntry& rPoEntry )
+{
+    assert( isOpen() && !eof() && m_bIsAfterHeader );
+    GenPoEntry aGenPo;
+    aGenPo.readFromFile( m_aInPut );
+    if( aGenPo.isNull() )
+    {
+        m_bEof = true;
+        rPoEntry = PoEntry();
+    }
+    else
+    {
+        const OString sContext = aGenPo.getContext();
+        const sal_Int32 nLastDot = sContext.lastIndexOf('.');
+        const OString sType = sContext.copy( nLastDot + 1 );
+        if( !aGenPo.getReference().isEmpty() &&
+            sContext.indexOf('\n') > 0 &&
+            (sType == "text" || sType == "quickhelptext" || sType == "title") &&
+            nLastDot - sContext.lastIndexOf('\n') > 0 &&
+            !aGenPo.getUnTransStr().isEmpty() )
+        {
+            rPoEntry.m_aGenPo = aGenPo;
+            rPoEntry.m_bIsInitialized = true;
+        }
+        else
+        {
+            throw INVALIDENTRY;
+        }
+    }
+}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/renewpo.cxx b/l10ntools/source/renewpo.cxx
index 39152a7..83b3051 100644
--- a/l10ntools/source/renewpo.cxx
+++ b/l10ntools/source/renewpo.cxx
@@ -12,7 +12,10 @@
 #include <dirent.h>
 #include <string>
 #include <vector>
+
+#include <osl/file.hxx>
 #include <rtl/string.hxx>
+
 #include "po.hxx"
 
 using namespace std;
@@ -58,10 +61,27 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
                     const OString& rpo2loPath, const OString& rSDFPath)
 {
     const OString LangEntryName = pLangEntry->d_name;
-    const OString SDFFileName = LangEntryName + ".sdf";
 
     //Generate and open sdf
     cout << "Process start with language: " <<  LangEntryName.getStr() << endl;
+    OUString aTempUrl;
+    if (osl::FileBase::createTempFile(0, 0, &aTempUrl)
+        != osl::FileBase::E_None)
+    {
+        cerr << "osl::FileBase::createTempFile() failed\n";
+        return;
+    }
+    OUString aTempPath;
+    if (osl::FileBase::getSystemPathFromFileURL(aTempUrl, aTempPath)
+        != osl::FileBase::E_None)
+    {
+        cerr
+            << "osl::FileBase::getSystemPathFromFileURL(" << aTempUrl
+            << ") failed\n";
+        return;
+    }
+    const OString SDFFileName =
+        OUStringToOString(aTempPath, RTL_TEXTENCODING_UTF8);
     system( (rpo2loPath +
             " -i " + rPath + "/" + LangEntryName +
             " -o " + SDFFileName +
@@ -69,7 +89,7 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
             " -t " + rSDFPath).getStr());
     cout << "Language sdf is ready!" << endl;
 
-    ofstream aOutPut;
+    PoOfstream aNewPo;
     ifstream aSDFInput(SDFFileName.getStr());
     string s;
     getline(aSDFInput,s);
@@ -77,40 +97,41 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
     while(!aSDFInput.eof())
     {
         OString sActUnTrans = sLine;
-        OString sPath = rPath + "/"+ LangEntryName;
-        OString sActSourcePath = GetPath(sPath,sActUnTrans);
-        //Make new po file, copy header with some changes
-        if (!aOutPut.is_open())
+        const OString sPath = rPath + "/"+ LangEntryName;
+        const OString sActSourcePath = GetPath(sPath,sActUnTrans);
+        //Make new po file and add header
+        if (!aNewPo.isOpen())
         {
-            aOutPut.open((sActSourcePath + ".po_tmp").getStr(),
-                         std::ios_base::out | std::ios_base::trunc);
-            ifstream aPOInput((sActSourcePath + ".po").getStr());
-            getline(aPOInput,s);
-            while(s!="")
+            const OString sNewPoFileName = sActSourcePath + ".po_tmp";
+            aNewPo.open(sNewPoFileName);
+            if (!aNewPo.isOpen())
             {
-                if (s.find("#. extracted from")!=string::npos)
-                    s = string(s,0,s.length()-3);
-                if (s.find("Report-Msgid-Bugs-To")!=string::npos)
-                    s = string("\"Report-Msgid-Bugs-To: ") +
-                        "https://bugs.freedesktop.org/enter_bug.cgi?product=" +
-                        "LibreOffice&bug_status=UNCONFIRMED&component=UI\\n\"";
-                if (s.find("X-Generator")!=string::npos)
-                    s = "\"X-Generator: LibreOffice\\n\"";
-                aOutPut << s << endl;
-                getline(aPOInput,s);
-            };
-            aPOInput.close();
+                cerr
+                    << "Cannot open temp file for new po: "
+                    << sNewPoFileName.getStr() << endl;
+                return;
+            }
+            const OString sOldPoFileName = sActSourcePath + ".po";
+            ifstream aOldPo(sOldPoFileName.getStr());
+            if (!aOldPo.is_open())
+            {
+                cerr
+                    << "Cannot open old po file: "
+                    << sOldPoFileName.getStr() << endl;
+                return;
+            }
+            aNewPo.writeHeader(PoHeader(aOldPo));
+            aOldPo.close();
         }
 
         //Set PoEntry and write out
         getline(aSDFInput,s);
-        sLine = OString(s.data(),s.length());
         OString sActTrans;
-        if (!aSDFInput.eof() && IsSameEntry(sActUnTrans,sLine))
+        if (!aSDFInput.eof() &&
+            IsSameEntry(sActUnTrans,sLine = OString(s.data(),s.length())))
         {
             sActTrans = sLine;
             getline(aSDFInput,s);
-            sLine = OString(s.data(),s.length());
         }
         else
         {
@@ -121,7 +142,7 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
         const vector<PoEntry::TYPE> vTypes( vInitializer,
             vInitializer + sizeof(vInitializer) / sizeof(vInitializer[0]) );
         unsigned short nDummyBit = 0;
-        for( unsigned nIndex=0; nIndex<vTypes.size(); ++nIndex)
+        for( unsigned short nIndex=0; nIndex<vTypes.size(); ++nIndex )
         {
             if (!sActUnTrans.getToken(vTypes[nIndex],'\t').isEmpty())
             {
@@ -141,15 +162,15 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
                 aPE.setFuzzy( sActStr.isEmpty() ? false :
                     static_cast<bool>(sActTrans.getToken(PoEntry::DUMMY,'\t').
                         copy(nDummyBit++,1).toBoolean()));
-                aPE.writeToFile(aOutPut);
+                aNewPo.writeEntry(aPE);
             }
         }
         //Check wheather next entry is in the same po file
-        OString sNextSourcePath =
-            !aSDFInput.eof() ? GetPath(sPath,sLine) : "";
+        OString sNextSourcePath = aSDFInput.eof() ? "" :
+            GetPath(sPath,sLine = OString(s.data(),s.length()));
         if (sNextSourcePath!=sActSourcePath)
         {
-            aOutPut.close();
+            aNewPo.close();
             system(("rm " + sActSourcePath +".po").getStr());
             system(("mv "+ sActSourcePath +".po_tmp " +
                     sActSourcePath +".po").getStr());
@@ -158,7 +179,10 @@ void HandleLanguage(struct dirent* pLangEntry, const OString& rPath,
 
     //Close and remove sdf file
     aSDFInput.close();
-    system(("rm " + SDFFileName).getStr());
+    if (osl::File::remove(aTempUrl) != osl::FileBase::E_None)
+    {
+        cerr << "Warning: failure removing temporary " << aTempUrl << '\n';
+    }
 }
 
 


More information about the Libreoffice-commits mailing list