document glob matching
parent
8b2fb4a627
commit
6b66e6ea69
|
@ -111,7 +111,7 @@ namespace detail {
|
|||
inline typename filesystem::path::value_type const *glob_match_brackets(
|
||||
typename filesystem::path::value_type match,
|
||||
typename filesystem::path::value_type const *wp
|
||||
) {
|
||||
) noexcept {
|
||||
bool neg = (*wp == '!');
|
||||
if (neg) {
|
||||
++wp;
|
||||
|
@ -160,7 +160,7 @@ namespace detail {
|
|||
inline bool glob_match_filename_impl(
|
||||
typename filesystem::path::value_type const *fname,
|
||||
typename filesystem::path::value_type const *wname
|
||||
) {
|
||||
) noexcept {
|
||||
/* skip any matching prefix if present */
|
||||
while (*wname && (*wname != '*')) {
|
||||
if (!*wname || (*wname == '*')) {
|
||||
|
@ -221,9 +221,40 @@ namespace detail {
|
|||
}
|
||||
} /* namespace detail */
|
||||
|
||||
/** @brief Checks if the given path matches the given glob pattern.
|
||||
*
|
||||
* This matches the given filename against POSIX-style glob patterns.
|
||||
* The following patterns are supported:
|
||||
*
|
||||
* | Pattern | Description |
|
||||
* |---------|----------------------------------------------------|
|
||||
* | * | 0 or more characters |
|
||||
* | ? | any single character |
|
||||
* | [abc] | one character in the brackets |
|
||||
* | [a-z] | one character within the range in the brackets |
|
||||
* | [!abc] | one character not in the brackets |
|
||||
* | [!a-z] | one character not within the range in the brackets |
|
||||
*
|
||||
* The behavior is the same as in POSIX. You can combine ranges and
|
||||
* individual characters in the `[]` pattern together as well as define
|
||||
* multiple ranges in one (e.g. `[a-zA-Z_?]` matching alphabetics,
|
||||
* an underscore and a question mark). The behavior of the range varies
|
||||
* by locale. If the second character in the range is lower in value
|
||||
* than the first one, a match will never happen. To match the `]`
|
||||
* character in the brackets, make it the first one. To match the
|
||||
* dash character, make it the first or the last.
|
||||
*
|
||||
* You can also use the brackets to escape metacharacters. So to
|
||||
* match a literal `*`, use `[*]`.
|
||||
*
|
||||
* Keep in mind that an invalid bracket syntax (unterminated) will
|
||||
* always cause this to return `false`.
|
||||
*
|
||||
* This function is used in ostd::glob_match().
|
||||
*/
|
||||
inline bool glob_match_filename(
|
||||
filesystem::path const &filename, filesystem::path const &pattern
|
||||
) {
|
||||
) noexcept {
|
||||
return detail::glob_match_filename_impl(filename.c_str(), pattern.c_str());
|
||||
}
|
||||
|
||||
|
@ -300,11 +331,39 @@ namespace detail {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename OR>
|
||||
inline OR &&glob_match(OR &&out, filesystem::path const &path) {
|
||||
/** @brief Expands a path with glob patterns.
|
||||
*
|
||||
* Individual expanded paths are put in `out` and are of the standard
|
||||
* std::filesystem::path type. It supports standard patterns as defined
|
||||
* in ostd::glob_match_filename().
|
||||
*
|
||||
* So for example, `*.cc` will expand to `one.cc`, `two.cc` and so on.
|
||||
* A pattern like `foo/[cb]at.txt` will match `foo/cat.txt` and `foo/bat.txt`
|
||||
* but not `foo/Cat.txt`. The `foo/?at.txt` will match `foo/cat.txt`,
|
||||
* `foo/Cat.txt`, `foo/pat.txt`, `foo/vat.txt` or any other character
|
||||
* in the place.
|
||||
*
|
||||
* Additionally, a special `**` pattern is also supported which is not
|
||||
* matched by ostd::glob_match_filename(). It's only allowed if the entire
|
||||
* filename or directory name is `**`. When used as a directory name, it
|
||||
* will expand to all directories in the location and all subdirectories
|
||||
* of those directories. If used as a filename (at the end of the path),
|
||||
* then it expands to directories and subdirectories aswell as all files
|
||||
* in the location and in the directories or subdirectories. Keep in mind
|
||||
* that it is not a regular pattern and a `**` when found in a regular
|
||||
* context (i.e. not as entire filename/directory name) will be treated
|
||||
* as two regular `*` patterns.
|
||||
*
|
||||
* @throws std::filesystem_error if a filesystem error occurs.
|
||||
* @returns The forwarded `out`.
|
||||
*/
|
||||
template<typename OutputRange>
|
||||
inline OutputRange &&glob_match(
|
||||
OutputRange &&out, filesystem::path const &path
|
||||
) {
|
||||
auto pend = path.end();
|
||||
detail::glob_match_impl(out, path.begin(), pend, filesystem::path{});
|
||||
return std::forward<OR>(out);
|
||||
return std::forward<OutputRange>(out);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
Loading…
Reference in New Issue