LibreOffice Module unotools (master) 1
textsearch.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 * 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 <cstdlib>
23#include <string_view>
24
28#include <com/sun/star/util/TextSearch2.hpp>
29#include <com/sun/star/util/SearchAlgorithms2.hpp>
30#include <com/sun/star/util/SearchFlags.hpp>
34#include <rtl/ustrbuf.hxx>
36#include <mutex>
37
38using namespace ::com::sun::star::util;
39using namespace ::com::sun::star::uno;
40using namespace ::com::sun::star::lang;
41
42namespace utl
43{
44
45SearchParam::SearchParam( const OUString &rText,
46 SearchType eType,
47 bool bCaseSensitive,
48 sal_uInt32 cWildEscChar,
49 bool bWildMatchSel )
50{
51 sSrchStr = rText;
53
54 m_cWildEscChar = cWildEscChar;
55
56 m_bCaseSense = bCaseSensitive;
57 m_bWildMatchSel = bWildMatchSel;
58}
59
61{
62 sSrchStr = rParam.sSrchStr;
63 m_eSrchType = rParam.m_eSrchType;
64
66
69}
70
72
73static bool lcl_Equals( const i18nutil::SearchOptions2& rSO1, const i18nutil::SearchOptions2& rSO2 )
74{
75 return
76 rSO1.AlgorithmType2 == rSO2.AlgorithmType2 &&
78 rSO1.searchFlag == rSO2.searchFlag &&
79 rSO1.searchString == rSO2.searchString &&
80 rSO1.replaceString == rSO2.replaceString &&
81 rSO1.changedChars == rSO2.changedChars &&
82 rSO1.deletedChars == rSO2.deletedChars &&
83 rSO1.insertedChars == rSO2.insertedChars &&
84 rSO1.Locale.Language == rSO2.Locale.Language &&
85 rSO1.Locale.Country == rSO2.Locale.Country &&
86 rSO1.Locale.Variant == rSO2.Locale.Variant &&
88}
89
90namespace
91{
92 struct CachedTextSearch
93 {
96 css::uno::Reference< css::util::XTextSearch2 > xTextSearch;
97 };
98}
99
100Reference<XTextSearch2> TextSearch::getXTextSearch( const i18nutil::SearchOptions2& rPara )
101{
102 static CachedTextSearch theCachedTextSearch;
103
104 std::scoped_lock aGuard(theCachedTextSearch.mutex);
105
106 if ( lcl_Equals(theCachedTextSearch.Options, rPara) )
107 return theCachedTextSearch.xTextSearch;
108
109 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
110 theCachedTextSearch.xTextSearch.set( ::TextSearch2::create(xContext) );
111 theCachedTextSearch.xTextSearch->setOptions2( rPara.toUnoSearchOptions2() );
112 theCachedTextSearch.Options = rPara;
113
114 return theCachedTextSearch.xTextSearch;
115}
116
118{
119 if( LANGUAGE_NONE == eLang )
120 eLang = LANGUAGE_SYSTEM;
121 css::lang::Locale aLocale( LanguageTag::convertToLocale( eLang ) );
122
123 Init( rParam, aLocale);
124}
125
126TextSearch::TextSearch(const SearchParam & rParam, const CharClass& rCClass )
127{
128 Init( rParam, rCClass.getLanguageTag().getLocale() );
129}
130
132{
133 xTextSearch = getXTextSearch( rPara );
134}
135
136void TextSearch::Init( const SearchParam & rParam,
137 const css::lang::Locale& rLocale )
138{
139 // convert SearchParam to the UNO SearchOptions2
141
142 switch( rParam.GetSrchType() )
143 {
145 aSOpt.AlgorithmType2 = SearchAlgorithms2::WILDCARD;
147 if (rParam.IsWildMatchSel())
148 aSOpt.searchFlag |= SearchFlags::WILD_MATCH_SELECTION;
149 break;
150
152 aSOpt.AlgorithmType2 = SearchAlgorithms2::REGEXP;
153 break;
154
156 aSOpt.AlgorithmType2 = SearchAlgorithms2::ABSOLUTE;
157 break;
158
159 default:
160 for (;;) std::abort();
161 }
162 aSOpt.searchString = rParam.GetSrchStr();
163 aSOpt.replaceString = "";
164 aSOpt.Locale = rLocale;
165 aSOpt.transliterateFlags = TransliterationFlags::NONE;
166 if( !rParam.IsCaseSensitive() )
167 {
168 aSOpt.searchFlag |= SearchFlags::ALL_IGNORE_CASE;
169 aSOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
170 }
171
172 xTextSearch = getXTextSearch( aSOpt );
173}
174
176 const css::lang::Locale& rLocale )
177{
178 i18nutil::SearchOptions2 aSOpt( rOptions );
179 aSOpt.Locale = rLocale;
180
181 xTextSearch = getXTextSearch( aSOpt );
182}
183
185{
186}
187
188/*
189 * General search methods. These methods will call the respective
190 * methods, such as ordinary string searching or regular expression
191 * matching, using the method pointer.
192 */
193bool TextSearch::SearchForward( const OUString &rStr,
194 sal_Int32* pStart, sal_Int32* pEnd,
195 css::util::SearchResult* pRes)
196{
197 bool bRet = false;
198 try
199 {
200 if( xTextSearch.is() )
201 {
202 SearchResult aRet( xTextSearch->searchForward( rStr, *pStart, *pEnd ));
203 if( aRet.subRegExpressions > 0 )
204 {
205 bRet = true;
206 // the XTextsearch returns in startOffset the higher position
207 // and the endposition is always exclusive.
208 // The caller of this function will have in startPos the
209 // lower pos. and end
210 *pStart = aRet.startOffset[ 0 ];
211 *pEnd = aRet.endOffset[ 0 ];
212 if( pRes )
213 *pRes = aRet;
214 }
215 }
216 }
217 catch ( Exception& )
218 {
219 TOOLS_WARN_EXCEPTION("unotools.i18n", "" );
220 }
221 return bRet;
222}
223
224bool TextSearch::searchForward( const OUString &rStr )
225{
226 sal_Int32 pStart = 0;
227 sal_Int32 pEnd = rStr.getLength();
228
229 bool bResult = SearchForward(rStr, &pStart, &pEnd);
230
231 return bResult;
232}
233
234bool TextSearch::SearchBackward( const OUString & rStr, sal_Int32* pStart,
235 sal_Int32* pEnd, SearchResult* pRes )
236{
237 bool bRet = false;
238 try
239 {
240 if( xTextSearch.is() )
241 {
242 SearchResult aRet( xTextSearch->searchBackward( rStr, *pStart, *pEnd ));
243 if( aRet.subRegExpressions )
244 {
245 bRet = true;
246 // the XTextsearch returns in startOffset the higher position
247 // and the endposition is always exclusive.
248 // The caller of this function will have in startPos the
249 // lower pos. and end
250 *pEnd = aRet.startOffset[ 0 ];
251 *pStart = aRet.endOffset[ 0 ];
252 if( pRes )
253 *pRes = aRet;
254 }
255 }
256 }
257 catch ( Exception& )
258 {
259 TOOLS_WARN_EXCEPTION("unotools.i18n", "" );
260 }
261 return bRet;
262}
263
264void TextSearch::ReplaceBackReferences( OUString& rReplaceStr, std::u16string_view rStr, const SearchResult& rResult ) const
265{
266 if( rResult.subRegExpressions <= 0 )
267 return;
268
269 sal_Unicode sFndChar;
270 sal_Int32 i;
271 OUStringBuffer sBuff(rReplaceStr.getLength()*4);
272 for(i = 0; i < rReplaceStr.getLength(); i++)
273 {
274 if( rReplaceStr[i] == '&')
275 {
276 sal_Int32 nStart = rResult.startOffset[0];
277 sal_Int32 nLength = rResult.endOffset[0] - rResult.startOffset[0];
278 sBuff.append(rStr.substr(nStart, nLength));
279 }
280 else if((i < rReplaceStr.getLength() - 1) && rReplaceStr[i] == '$')
281 {
282 sFndChar = rReplaceStr[ i + 1 ];
283 switch(sFndChar)
284 { // placeholder for a backward reference?
285 case '0':
286 case '1':
287 case '2':
288 case '3':
289 case '4':
290 case '5':
291 case '6':
292 case '7':
293 case '8':
294 case '9':
295 {
296 int j = sFndChar - '0'; // index
297 if(j < rResult.subRegExpressions)
298 {
299 sal_Int32 nSttReg = rResult.startOffset[j];
300 sal_Int32 nRegLen = rResult.endOffset[j];
301 if (nSttReg < 0 || nRegLen < 0) // A "not found" optional capture
302 {
303 nSttReg = nRegLen = 0; // Copy empty string
304 }
305 else if (nRegLen >= nSttReg)
306 {
307 nRegLen = nRegLen - nSttReg;
308 }
309 else
310 {
311 nRegLen = nSttReg - nRegLen;
312 nSttReg = rResult.endOffset[j];
313 }
314 // Copy reference from found string
315 sBuff.append(rStr.substr(nSttReg, nRegLen));
316 }
317 i += 1;
318 }
319 break;
320 default:
321 sBuff.append(OUStringChar(rReplaceStr[i]) + OUStringChar(rReplaceStr[i+1]));
322 i += 1;
323 break;
324 }
325 }
326 else if((i < rReplaceStr.getLength() - 1) && rReplaceStr[i] == '\\')
327 {
328 sFndChar = rReplaceStr[ i+1 ];
329 switch(sFndChar)
330 {
331 case '\\':
332 case '&':
333 case '$':
334 sBuff.append(sFndChar);
335 i+=1;
336 break;
337 case 't':
338 sBuff.append('\t');
339 i += 1;
340 break;
341 default:
342 sBuff.append(OUStringChar(rReplaceStr[i]) + OUStringChar(rReplaceStr[i+1]));
343 i += 1;
344 break;
345 }
346 }
347 else
348 {
349 sBuff.append(rReplaceStr[i]);
350 }
351 }
352 rReplaceStr = sBuff.makeStringAndClear();
353}
354
355} // namespace utl
356
357/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const LanguageTag & getLanguageTag() const
get current Locale
Definition: charclass.cxx:51
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
sal_Int32 GetWildEscChar() const
Definition: textsearch.hxx:116
sal_uInt32 m_cWildEscChar
Definition: textsearch.hxx:93
OUString sSrchStr
Definition: textsearch.hxx:89
SearchType m_eSrchType
Definition: textsearch.hxx:91
bool IsCaseSensitive() const
Definition: textsearch.hxx:112
SearchType GetSrchType() const
Definition: textsearch.hxx:110
const OUString & GetSrchStr() const
Definition: textsearch.hxx:109
bool IsWildMatchSel() const
Definition: textsearch.hxx:113
SearchParam(const OUString &rText, SearchType eSrchType, bool bCaseSensitive=true, sal_uInt32 cWildEscChar='\\', bool bWildMatchSel=false)
Definition: textsearch.cxx:45
css::uno::Reference< css::util::XTextSearch2 > xTextSearch
Definition: textsearch.hxx:160
bool SearchBackward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
Definition: textsearch.cxx:234
void SetLocale(const i18nutil::SearchOptions2 &rOpt, const css::lang::Locale &rLocale)
Definition: textsearch.cxx:175
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
Definition: textsearch.cxx:193
bool searchForward(const OUString &rStr)
searchForward Search forward beginning from the start to the end of the given text
Definition: textsearch.cxx:224
TextSearch(const SearchParam &rPara, LanguageType nLanguage)
Definition: textsearch.cxx:117
void ReplaceBackReferences(OUString &rReplaceStr, std::u16string_view rStr, const css::util::SearchResult &rResult) const
Definition: textsearch.cxx:264
void Init(const SearchParam &rParam, const css::lang::Locale &rLocale)
Definition: textsearch.cxx:136
static css::uno::Reference< css::util::XTextSearch2 > getXTextSearch(const i18nutil::SearchOptions2 &rPara)
Definition: textsearch.cxx:100
#define TOOLS_WARN_EXCEPTION(area, stream)
DocumentType eType
#define LANGUAGE_SYSTEM
#define LANGUAGE_NONE
@ Exception
int i
static bool lcl_Equals(const i18nutil::SearchOptions2 &rSO1, const i18nutil::SearchOptions2 &rSO2)
Definition: textsearch.cxx:73
css::util::SearchOptions2 toUnoSearchOptions2() const
TransliterationFlags transliterateFlags
css::lang::Locale Locale
sal_Int32 WildcardEscapeCharacter
std::mutex mutex
Definition: textsearch.cxx:94
css::uno::Reference< css::util::XTextSearch2 > xTextSearch
Definition: textsearch.cxx:96
sal_uInt16 sal_Unicode
sal_Int32 nLength