diff options
Diffstat (limited to 'tools/source/fsys/wldcrd.cxx')
-rw-r--r-- | tools/source/fsys/wldcrd.cxx | 105 |
1 files changed, 58 insertions, 47 deletions
diff --git a/tools/source/fsys/wldcrd.cxx b/tools/source/fsys/wldcrd.cxx index 6e0259696aca..e8199975c6e5 100644 --- a/tools/source/fsys/wldcrd.cxx +++ b/tools/source/fsys/wldcrd.cxx @@ -25,85 +25,96 @@ * '?' in pWild mean match exactly one character. * */ -bool WildCard::ImpMatch( const sal_Unicode *pWild, const sal_Unicode *pStr ) +bool WildCard::ImpMatch( std::u16string_view aWild, std::u16string_view aStr ) { - int pos=0; - int flag=0; + const sal_Unicode* pPosAfterAsterisk = nullptr; + const sal_Unicode* pWild = aWild.data(); + const sal_Unicode* pWildEnd = aWild.data() + aWild.size(); + const sal_Unicode* pStr = aStr.data(); + const sal_Unicode* pStrEnd = aStr.data() + aStr.size(); - while ( *pWild || flag ) + while (pWild != pWildEnd) { switch (*pWild) { case '?': - if ( *pStr == '\0' ) + if ( pStr == pStrEnd ) return false; - break; - - default: - if ( (*pWild == '\\') && ((*(pWild+1)=='?') || (*(pWild+1) == '*')) ) + break; // Match -> proceed to the next character + case '\\': // Escaping '?' and '*'; don't we need to escape '\\'? + if ((pWild + 1 != pWildEnd) && ((*(pWild + 1) == '?') || (*(pWild + 1) == '*'))) pWild++; - if ( *pWild != *pStr ) - if ( !pos ) - return false; - else - pWild += pos; - else - break; - // WARNING/TODO: may cause execution of next case in some - // circumstances! + [[fallthrough]]; + default: // No wildcard, literal match + if (pStr == pStrEnd) + return false; + if (*pWild == *pStr) + break; // Match -> proceed to the next character + if (!pPosAfterAsterisk) + return false; + pWild = pPosAfterAsterisk; [[fallthrough]]; case '*': - while ( *pWild == '*' ) + while ( pWild != pWildEnd && *pWild == '*' ) pWild++; - if ( *pWild == '\0' ) + if ( pWild == pWildEnd ) return true; - flag = 1; - pos = 0; - if ( *pStr == '\0' ) - return ( *pWild == '\0' ); - while ( *pStr && *pStr != *pWild ) + // Consider strange things like "**?*?*" + while (*pWild == '?') { - if ( *pWild == '?' ) { + if (pStr == pStrEnd) + return false; + pWild++; + pStr++; + while (pWild != pWildEnd && *pWild == '*') pWild++; - while ( *pWild == '*' ) - pWild++; - } + if (pWild == pWildEnd) + return true; + } + // At this point, we are past wildcards, and a literal match must follow + if ( pStr == pStrEnd ) + return false; + pPosAfterAsterisk = pWild; + if ((*pWild == '\\') && (pWild + 1 != pWildEnd) && ((*(pWild + 1) == '?') || (*(pWild + 1) == '*'))) + pWild++; + while (*pStr != *pWild) + { pStr++; - if ( *pStr == '\0' ) - return ( *pWild == '\0' ); + if ( pStr == pStrEnd ) + return false; } - break; + break; // Match -> proceed to the next character } - if ( *pWild != '\0' ) - pWild++; - if ( *pStr != '\0' ) - pStr++; - else - flag = 0; - if ( flag ) - pos--; + // We arrive here when the current characters in pWild and pStr match + assert(pWild != pWildEnd); + pWild++; + assert(pStr != pStrEnd); + pStr++; + if (pWild == pWildEnd && pPosAfterAsterisk && pStr != pStrEnd) + pWild = pPosAfterAsterisk; // Try again on the rest of pStr } - return ( *pStr == '\0' ) && ( *pWild == '\0' ); + assert(pWild == pWildEnd); + return pStr == pStrEnd; } bool WildCard::Matches( std::u16string_view rString ) const { - OUString aTmpWild = aWildString; + std::u16string_view aTmpWild = aWildString; - sal_Int32 nSepPos; + size_t nSepPos; if ( cSepSymbol != '\0' ) { - while ( (nSepPos = aTmpWild.indexOf(cSepSymbol)) != -1 ) + while ( (nSepPos = aTmpWild.find(cSepSymbol)) != std::u16string_view::npos ) { // Check all split wildcards - if ( ImpMatch( aTmpWild.subView( 0, nSepPos ).data(), rString.data() ) ) + if ( ImpMatch( aTmpWild.substr( 0, nSepPos ), rString ) ) return true; - aTmpWild = aTmpWild.copy(nSepPos + 1); // remove separator + aTmpWild = aTmpWild.substr(nSepPos + 1); // remove separator } } - return ImpMatch( aTmpWild.getStr(), rString.data() ); + return ImpMatch( aTmpWild, rString ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |