Skip to content

Commit 1b67a84

Browse files
committed
support glob patterns
#feat
1 parent 9662f27 commit 1b67a84

File tree

3 files changed

+1447
-18
lines changed

3 files changed

+1447
-18
lines changed

include/mrdocs/Support/Glob.hpp

+292
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
//
2+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
// Copyright (c) 2024 Alan de Freitas ([email protected])
7+
//
8+
// Official repository: https://github.com/cppalliance/mrdocs
9+
//
10+
11+
#ifndef MRDOCS_API_SUPPORT_GLOBPATTERN_HPP
12+
#define MRDOCS_API_SUPPORT_GLOBPATTERN_HPP
13+
14+
#include <mrdocs/Support/Error.hpp>
15+
#include <memory>
16+
#include <optional>
17+
#include <string_view>
18+
19+
namespace clang::mrdocs {
20+
21+
/** A glob pattern matcher
22+
23+
@li "*" matches all characters except delimiters.
24+
@li "**" matches all characters
25+
@li "?" matches any single character.
26+
@li "[<chars>]" matches one character in the bracket.
27+
@li "[<char>-<char>]" matches one character in the bracket range.
28+
@li "[^<chars>]" or "[!<chars>]" matches one character not in the bracket.
29+
@li "{<glob>,...}" matches one of the globs in the list.
30+
@li "\" escapes the next character so it is treated as a literal.
31+
32+
Nested brace expansions "{<glob>,"{<glob>,...}",...}" are not supported.
33+
*/
34+
class GlobPattern {
35+
struct Impl;
36+
std::unique_ptr<Impl> impl_;
37+
public:
38+
/** Constructs a GlobPattern with the given pattern.
39+
40+
@param pattern The glob pattern to use for matching.
41+
*/
42+
static
43+
Expected<GlobPattern>
44+
create(std::string_view pattern, std::optional<std::size_t> maxSubGlobs);
45+
46+
static
47+
Expected<GlobPattern>
48+
create(std::string_view pattern)
49+
{
50+
return create(pattern, std::nullopt);
51+
}
52+
53+
/** Destructor */
54+
~GlobPattern();
55+
56+
/** Construct an empty GlobPattern.
57+
58+
An empty GlobPattern will never match any string.
59+
*/
60+
GlobPattern();
61+
62+
/** Copy constructor */
63+
GlobPattern(GlobPattern const& other);
64+
65+
/** Move constructor */
66+
GlobPattern(GlobPattern&& other) noexcept;
67+
68+
/** Copy assignment */
69+
GlobPattern&
70+
operator=(GlobPattern const& other);
71+
72+
/** Move assignment */
73+
GlobPattern&
74+
operator=(GlobPattern&& other) noexcept;
75+
76+
/** Matches the given string against the glob pattern.
77+
78+
@param str The string to match against the pattern.
79+
@return true if the string matches the pattern, false otherwise.
80+
*/
81+
bool
82+
match(std::string_view str, char delimiter) const;
83+
84+
/** Matches the start of a given string against the glob pattern.
85+
86+
This function determines if the given string with
87+
the specified `prefix` can potentially match
88+
the glob pattern.
89+
90+
If the string matches the start of the pattern without failure, even
91+
if there are characters left in the string or the pattern, the
92+
function returns true.
93+
94+
@param prefix The string to match against the pattern.
95+
@return true if the string prefix matches the pattern, false otherwise.
96+
*/
97+
bool
98+
matchPatternPrefix(std::string_view prefix, char delimiter) const;
99+
100+
/** Returns the glob pattern.
101+
102+
@return The glob pattern as a string view.
103+
*/
104+
std::string_view
105+
pattern() const;
106+
};
107+
108+
/** A glob pattern matcher for paths
109+
110+
A glob pattern matcher where "*" does not match path separators.
111+
The pattern "**" can be used to match any number of path separators.
112+
*/
113+
class PathGlobPattern {
114+
GlobPattern glob_;
115+
public:
116+
/** Constructs a PathGlobPattern with the given pattern.
117+
118+
@param pattern The glob pattern to use for matching.
119+
@param maxSubGlobs The maximum number of subpatterns allowed.
120+
*/
121+
static
122+
Expected<PathGlobPattern>
123+
create(
124+
std::string_view const pattern,
125+
std::optional<std::size_t> maxSubGlobs)
126+
{
127+
MRDOCS_TRY(auto glob, GlobPattern::create(pattern, maxSubGlobs));
128+
return PathGlobPattern{std::move(glob)};
129+
}
130+
131+
/** Constructs a PathGlobPattern with the given pattern.
132+
133+
@param pattern The glob pattern to use for matching.
134+
*/
135+
static
136+
Expected<PathGlobPattern>
137+
create(std::string_view const pattern)
138+
{
139+
MRDOCS_TRY(auto glob, GlobPattern::create(pattern));
140+
return PathGlobPattern{std::move(glob)};
141+
}
142+
143+
/** Construct an empty PathGlobPattern.
144+
145+
An empty PathGlobPattern will never match any string.
146+
*/
147+
PathGlobPattern() = default;
148+
149+
/** Construct an empty PathGlobPattern.
150+
151+
An empty PathGlobPattern will never match any string.
152+
*/
153+
explicit
154+
PathGlobPattern(GlobPattern glob)
155+
: glob_{std::move(glob)}
156+
{};
157+
158+
/** Matches the given string against the glob pattern.
159+
160+
@param str The string to match against the pattern.
161+
@return true if the string matches the pattern, false otherwise.
162+
*/
163+
bool
164+
match(std::string_view const str) const
165+
{
166+
return glob_.match(str, '/');
167+
}
168+
169+
/** Matches the start of a given string against the glob pattern.
170+
171+
This function determines if the given string with
172+
the specified `prefix` can potentially match
173+
the glob pattern.
174+
175+
If the string matches the start of the pattern without failure, even
176+
if there are characters left in the string or the pattern, the
177+
function returns true.
178+
179+
@param prefix The string to match against the pattern.
180+
@return true if the string prefix matches the pattern, false otherwise.
181+
*/
182+
bool
183+
matchPatternPrefix(std::string_view prefix) const
184+
{
185+
return glob_.matchPatternPrefix(prefix, '/');
186+
}
187+
188+
/** Returns the glob pattern.
189+
190+
@return The glob pattern as a string view.
191+
*/
192+
std::string_view
193+
pattern() const
194+
{
195+
return glob_.pattern();
196+
}
197+
};
198+
199+
/** A glob pattern matcher for C++ symbols
200+
201+
A glob pattern matcher where "*" does not match "::".
202+
The pattern "**" can be used to match any number of "::".
203+
*/
204+
class SymbolGlobPattern {
205+
GlobPattern glob_;
206+
public:
207+
/** Constructs a SymbolGlobPattern with the given pattern.
208+
209+
@param pattern The glob pattern to use for matching.
210+
@param maxSubGlobs The maximum number of subpatterns allowed.
211+
*/
212+
static
213+
Expected<SymbolGlobPattern>
214+
create(
215+
std::string_view const pattern,
216+
std::optional<std::size_t> maxSubGlobs)
217+
{
218+
MRDOCS_TRY(auto glob, GlobPattern::create(pattern, maxSubGlobs));
219+
return SymbolGlobPattern{std::move(glob)};
220+
}
221+
222+
/** Constructs a SymbolGlobPattern with the given pattern.
223+
224+
@param pattern The glob pattern to use for matching.
225+
*/
226+
static
227+
Expected<SymbolGlobPattern>
228+
create(std::string_view const pattern)
229+
{
230+
MRDOCS_TRY(auto glob, GlobPattern::create(pattern));
231+
return SymbolGlobPattern{std::move(glob)};
232+
}
233+
234+
/** Construct an empty SymbolGlobPattern.
235+
236+
An empty SymbolGlobPattern will never match any string.
237+
*/
238+
SymbolGlobPattern() = default;
239+
240+
/** Construct an empty SymbolGlobPattern.
241+
242+
An empty SymbolGlobPattern will never match any string.
243+
*/
244+
explicit
245+
SymbolGlobPattern(GlobPattern glob)
246+
: glob_{std::move(glob)}
247+
{};
248+
249+
/** Matches the given string against the glob pattern.
250+
251+
@param str The string to match against the pattern.
252+
@return true if the string matches the pattern, false otherwise.
253+
*/
254+
bool
255+
match(std::string_view const str) const
256+
{
257+
return glob_.match(str, ':');
258+
}
259+
260+
/** Matches the start of a given string against the glob pattern.
261+
262+
This function determines if the given string with
263+
the specified `prefix` can potentially match
264+
the glob pattern.
265+
266+
If the string matches the start of the pattern without failure, even
267+
if there are characters left in the string or the pattern, the
268+
function returns true.
269+
270+
@param prefix The string to match against the pattern.
271+
@return true if the string prefix matches the pattern, false otherwise.
272+
*/
273+
bool
274+
matchPatternPrefix(std::string_view prefix) const
275+
{
276+
return glob_.matchPatternPrefix(prefix, ':');
277+
}
278+
279+
/** Returns the glob pattern.
280+
281+
@return The glob pattern as a string view.
282+
*/
283+
std::string_view
284+
pattern() const
285+
{
286+
return glob_.pattern();
287+
}
288+
};
289+
290+
} // clang::mrdocs
291+
292+
#endif // MRDOCS_API_SUPPORT_GLOBPATTERN_HPP

0 commit comments

Comments
 (0)