tdf#135538 tdf#132870 tdf#145774 regex: accept zero-length matches
In Find and Replace, you can search using regular expressions.
Some regex's don't match to a character, only a position.
OOo restricted the ability to find these zero-length matches.
LO allowed it only for the very end position (for matching '$')
in 4.0.3 with commit ccc349d3ab
Author: Eike Rathke on Sat Mar 9 18:50:33 2013 +0100
regex: don't loop 10000 identical matches to find a single $ anchor
I don't see any justification for what OOo did,
and I don't see any reason why not to accept every match/position.
AFAICS this only affects three modules:
-Calc: no significant downsides noticed (unless already true for '$').
Replace gets stuck. Need to replace/find next/replace/find next...
ReplaceAll, Find, and FindAll work nicely.
Find-Backwards doesn't work - a general regex problem.
-macro editor: gets 'stuck' finding same position every time
(but that also happened already with '$').
There is no 'Find All' (so nothing bad can happen there)
and 'Replace All' works nicely. No practical downside.
-Writer: Always reports bZeroMatch as 'false'
except for special code handling '$'.
So for Writer it has no effect at all
(except for returning more unused bZeroMatch).
So in the end this patch primarily benefits Calc
(although it opens the door for Writer to try to handle bZeroMatch
and it does solve the macro-editor complaint in tdf#132870).
Calc can now find the start of all cells ('^')
or employ look-ahead queries like '(?<=ab).
Change-Id: I2d69ca2032682f17bdff3412a8d9efd113b366e9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209080
Reviewed-by: Justin Luth <jluth@mail.com>
Tested-by: Jenkins
This commit is contained in:
@@ -970,26 +970,8 @@ SearchResult TextSearch::RESrchFrwrd( std::unique_lock<std::mutex>& /*rGuard*/,
|
||||
const icu::UnicodeString aSearchTargetStr(false, reinterpret_cast<const UChar*>(searchStr.getStr()),
|
||||
searchStr.getLength());
|
||||
pRegexMatcher->reset( aSearchTargetStr);
|
||||
// search until there is a valid match
|
||||
for(;;)
|
||||
{
|
||||
if (!lcl_findRegex( pRegexMatcher, startPos, endPos, nIcuErr))
|
||||
return aRet;
|
||||
|
||||
// #i118887# ignore zero-length matches e.g. "a*" in "bc"
|
||||
int nStartOfs = pRegexMatcher->start( nIcuErr);
|
||||
int nEndOfs = pRegexMatcher->end( nIcuErr);
|
||||
if( nStartOfs < nEndOfs)
|
||||
break;
|
||||
// If the zero-length match is behind the string, do not match it again
|
||||
// and again until startPos reaches there. A match behind the string is
|
||||
// a "$" anchor.
|
||||
if (nStartOfs == endPos)
|
||||
break;
|
||||
// try at next position if there was a zero-length match
|
||||
if( ++startPos >= endPos)
|
||||
return aRet;
|
||||
}
|
||||
if (!lcl_findRegex( pRegexMatcher, startPos, endPos, nIcuErr))
|
||||
return aRet;
|
||||
|
||||
// extract the result of the search
|
||||
const int nGroupCount = pRegexMatcher->groupCount();
|
||||
|
||||
Reference in New Issue
Block a user