LibreOffice Module l10ntools (master) 1
propmerge.cxx
Go to the documentation of this file.
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
10#include <rtl/ustring.hxx>
11#include <o3tl/string_view.hxx>
12
13#include <memory>
14#include <cstdlib>
15#include <cassert>
16#include <iostream>
17#include <iomanip>
18#include <string_view>
19
20#include <export.hxx>
21#include <common.hxx>
22#include <propmerge.hxx>
23#include <utility>
24
25namespace
26{
27 //Find ascii escaped unicode
28 sal_Int32 lcl_IndexOfUnicode(
29 std::string_view rSource, const sal_Int32 nFrom = 0 )
30 {
31 static constexpr std::string_view sHexDigits = "0123456789abcdefABCDEF";
32 size_t nIndex = rSource.find( "\\u", nFrom );
33 if( nIndex == std::string_view::npos )
34 {
35 return -1;
36 }
37 bool bIsUnicode = true;
38 for( short nDist = 2; nDist <= 5; ++nDist )
39 {
40 if( sHexDigits.find( rSource[nIndex + nDist] ) == std::string_view::npos )
41 {
42 bIsUnicode = false;
43 }
44 }
45 return bIsUnicode ? nIndex : -1;
46 }
47
48 //Convert ascii escaped unicode to utf-8
49 OString lcl_ConvertToUTF8( const OString& rText )
50 {
51 OString sResult = rText;
52 sal_Int32 nIndex = lcl_IndexOfUnicode( sResult );
53 while( nIndex != -1 && nIndex < rText.getLength() )
54 {
55 const OString sHex = sResult.copy( nIndex + 2, 4 );
56 const sal_Unicode cDec =
57 static_cast<sal_Unicode>( strtol( sHex.getStr(), nullptr, 16 ) );
58 const OString sNewChar( &cDec, 1, RTL_TEXTENCODING_UTF8 );
59 sResult = sResult.replaceAll( "\\u" + sHex, sNewChar );
60 nIndex = lcl_IndexOfUnicode( sResult, nIndex );
61 }
62 return sResult;
63 }
64
65 //Escape unicode characters
66 void lcl_PrintJavaStyle( std::string_view rText, std::ofstream &rOfstream )
67 {
68 const OUString sTemp =
69 OStringToOUString( rText, RTL_TEXTENCODING_UTF8 );
70 for ( sal_Int32 nIndex = 0; nIndex < sTemp.getLength(); ++nIndex )
71 {
72 sal_Unicode cUniCode = sTemp[nIndex];
73 if( cUniCode < 128 )
74 {
75 rOfstream << static_cast<char>( cUniCode );
76 }
77 else
78 {
79 rOfstream
80 << "\\u"
81 << std::setfill('0') << std::setw(2) << std::uppercase
82 << std::hex << (cUniCode >> 8)
83 << std::setfill('0') << std::setw(2) << std::uppercase
84 << std::hex << (cUniCode & 0xFF);
85 }
86 }
87 }
88}
89
90//Open source file and store its lines
92 OString _sInputFile, OString _sLang,
93 const bool bMergeMode )
94 : m_sSource(std::move( _sInputFile ))
95 , m_sLang(std::move( _sLang ))
96 , m_bIsInitialized( false )
97{
98 std::ifstream aIfstream( m_sSource.getStr() );
99 if( aIfstream.is_open() )
100 {
101 std::string s;
102 std::getline( aIfstream, s );
103 while( !aIfstream.eof() )
104 {
105 OString sLine( s.data(), s.length() );
106 if( bMergeMode ||
107 ( !sLine.startsWith(" *") && !sLine.startsWith("/*") ) )
108 {
109 m_vLines.push_back( sLine );
110 }
111 std::getline( aIfstream, s );
112 }
113 }
114 else
115 {
116 std::cerr
117 << "Propex error: Cannot open source file: "
118 << m_sSource << std::endl;
119 return;
120 }
121 m_bIsInitialized = true;
122}
123
125{
126}
127
128//Extract strings form source file
129void PropParser::Extract( const OString& rPOFile )
130{
131 assert( m_bIsInitialized );
132 PoOfstream aPOStream( rPOFile, PoOfstream::APP );
133 if( !aPOStream.isOpen() )
134 {
135 std::cerr
136 << "Propex error: Cannot open pofile for extract: "
137 << rPOFile << std::endl;
138 return;
139 }
140
141 for( size_t nIndex = 0; nIndex < m_vLines.size(); ++nIndex )
142 {
143 const OString sLine = m_vLines[nIndex];
144 const sal_Int32 nEqualSign = sLine.indexOf('=');
145 if( nEqualSign != -1 )
146 {
147 std::string_view sID = o3tl::trim(sLine.subView( 0, nEqualSign ));
148 OString sText = lcl_ConvertToUTF8( OString(o3tl::trim(sLine.subView( nEqualSign + 1 ))) );
149
151 "Propex", aPOStream, m_sSource, "property",
152 OString(sID), OString(), OString(), sText);
153 }
154 }
155
156 aPOStream.close();
157}
158
159//Merge strings to source file
160void PropParser::Merge( const OString &rMergeSrc, const OString &rDestinationFile )
161{
162 assert( m_bIsInitialized );
163 std::ofstream aDestination(
164 rDestinationFile.getStr(), std::ios_base::out | std::ios_base::trunc );
165 if( !aDestination.is_open() ) {
166 std::cerr
167 << "Propex error: Cannot open source file for merge: "
168 << rDestinationFile << std::endl;
169 return;
170 }
171
172 std::unique_ptr<MergeDataFile> pMergeDataFile;
173 if( m_sLang != "qtz" )
174 {
175 pMergeDataFile.reset( new MergeDataFile( rMergeSrc, m_sSource, false, false ) );
176
177 const std::vector<OString> vLanguages = pMergeDataFile->GetLanguages();
178 if( !vLanguages.empty() && vLanguages[0] != m_sLang )
179 {
180 std::cerr
181 << ("Propex error: given language conflicts with language of"
182 " Mergedata file: ")
183 << m_sLang << " - "
184 << vLanguages[0] << std::endl;
185 return;
186 }
187 }
188
189 for( size_t nIndex = 0; nIndex < m_vLines.size(); ++nIndex )
190 {
191 const OString sLine = m_vLines[nIndex];
192 const sal_Int32 nEqualSign = sLine.indexOf('=');
193 if( !sLine.startsWith(" *") && !sLine.startsWith("/*") &&
194 nEqualSign != -1 )
195 {
196 const OString sID( o3tl::trim(sLine.subView( 0, sLine.indexOf('=') )) );
197 ResData aResData( sID, m_sSource );
198 aResData.sResTyp = "property";
199 OString sNewText;
200 if( m_sLang == "qtz" )
201 {
202 const OString sOriginText = lcl_ConvertToUTF8(OString(o3tl::trim(sLine.subView( nEqualSign + 1 ))));
203 sNewText = MergeEntrys::GetQTZText(aResData, sOriginText);
204 }
205 else if( pMergeDataFile )
206 {
207 MergeEntrys* pEntrys = pMergeDataFile->GetMergeEntrys( &aResData );
208 if( pEntrys )
209 {
210 pEntrys->GetText( sNewText, m_sLang );
211 }
212 }
213 if( !sNewText.isEmpty() )
214 {
215 aDestination << OString(sID + "=");
216 lcl_PrintJavaStyle( sNewText, aDestination );
217 aDestination << std::endl;
218 }
219 else
220 {
221 aDestination << sLine << std::endl;
222 }
223 }
224 else
225 {
226 aDestination << sLine << std::endl;
227 }
228 }
229 aDestination.close();
230}
231
232/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Purpose: holds information of data to merge, read from PO file.
Definition: export.hxx:114
Purpose: holds information of data to merge.
Definition: export.hxx:77
static OString GetQTZText(const ResData &rResData, std::string_view rOrigText)
Generate QTZ string with ResData For executable which works one language and without PO files.
Definition: merge.cxx:109
bool GetText(OString &rReturn, const OString &nLangIndex, bool bDel=false)
Definition: merge.cxx:87
Interface to write po entry to files as output streams.
Definition: po.hxx:101
bool isOpen() const
Definition: po.hxx:116
void close()
Definition: po.cxx:515
@ APP
Definition: po.hxx:109
OString m_sSource
Definition: propmerge.hxx:27
void Merge(const OString &rMergeSrc, const OString &rDestinationFile)
Definition: propmerge.cxx:160
std::vector< OString > m_vLines
Definition: propmerge.hxx:26
PropParser(OString sInputFile, OString sLang, const bool bMergeMode)
Definition: propmerge.cxx:91
OString m_sLang
Definition: propmerge.hxx:28
bool m_bIsInitialized
Definition: propmerge.hxx:29
void Extract(const OString &rPOFile)
Definition: propmerge.cxx:129
Purpose: holds mandatory data to export a single res.
Definition: export.hxx:55
OString sResTyp
Definition: export.hxx:60
sal_Int32 nIndex
void writePoEntry(const OString &rExecutable, PoOfstream &rPoStream, const OString &rSourceFile, std::string_view rResType, const OString &rGroupId, const OString &rLocalId, const OString &rHelpText, const OString &rText, const PoEntry::TYPE eType)
Write out a PoEntry with attention to exceptions.
Definition: common.cxx:110
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
sal_uInt16 sal_Unicode
static bool bMergeMode
Definition: xrmmerge.cxx:37