diff options
author | Zolnai Tamás <zolnaitamas2000@gmail.com> | 2012-09-28 17:52:13 +0200 |
---|---|---|
committer | Andras Timar <atimar@suse.com> | 2012-09-30 15:11:53 +0000 |
commit | ca12be682f28969b15b30539230ca40de88fc36d (patch) | |
tree | e1c29003a45c62651e11a65d3269e1a5a9f96518 /l10ntools | |
parent | 9baaced8b636e23045495c9a018d0859a9df8e76 (diff) |
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@suse.com>
Tested-by: Andras Timar <atimar@suse.com>
Diffstat (limited to 'l10ntools')
-rw-r--r-- | l10ntools/inc/po.hxx | 74 | ||||
-rw-r--r-- | l10ntools/source/localize.cxx | 52 | ||||
-rw-r--r-- | l10ntools/source/merge.cxx | 98 | ||||
-rw-r--r-- | l10ntools/source/po.cxx | 246 | ||||
-rw-r--r-- | l10ntools/source/renewpo.cxx | 88 |
5 files changed, 426 insertions, 132 deletions
diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx index 686c9f393468..76312a4a59e5 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 a9a20c8b13da..87ee83bc1c58 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 b87024a22dec..7e6c59598c95 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 b2082a7ee80b..cf0b9632d854 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 39152a7945fa..83b3051134a9 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'; + } } |