blob: e8199975c6e5d80e3e1c821d8c6346588bffce09 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <tools/wldcrd.hxx>
/** Tests, whether a wildcard in pWild will match for pStr.
*
* '*' in pWild means n chars for n > 0.
* '?' in pWild mean match exactly one character.
*
*/
bool WildCard::ImpMatch( std::u16string_view aWild, std::u16string_view aStr )
{
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 != pWildEnd)
{
switch (*pWild)
{
case '?':
if ( pStr == pStrEnd )
return false;
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++;
[[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 != pWildEnd && *pWild == '*' )
pWild++;
if ( pWild == pWildEnd )
return true;
// Consider strange things like "**?*?*"
while (*pWild == '?')
{
if (pStr == pStrEnd)
return false;
pWild++;
pStr++;
while (pWild != pWildEnd && *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 == pStrEnd )
return false;
}
break; // Match -> proceed to the next character
}
// 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
}
assert(pWild == pWildEnd);
return pStr == pStrEnd;
}
bool WildCard::Matches( std::u16string_view rString ) const
{
std::u16string_view aTmpWild = aWildString;
size_t nSepPos;
if ( cSepSymbol != '\0' )
{
while ( (nSepPos = aTmpWild.find(cSepSymbol)) != std::u16string_view::npos )
{
// Check all split wildcards
if ( ImpMatch( aTmpWild.substr( 0, nSepPos ), rString ) )
return true;
aTmpWild = aTmpWild.substr(nSepPos + 1); // remove separator
}
}
return ImpMatch( aTmpWild, rString );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|