conduit 0.6.0
Modern C++23 header-only event-dispatching / event-transport library
Loading...
Searching...
No Matches
glob.hpp
Go to the documentation of this file.
1#pragma once
2
10
11#include <cstddef>
12#include <limits>
13#include <string>
14#include <string_view>
15#include <utility>
16
17namespace conduit {
18
19namespace detail {
20
21constexpr bool glob_match_impl(const std::string_view pattern,
22 const std::string_view name) noexcept {
23 const std::size_t plen = pattern.size();
24 const std::size_t nlen = name.size();
25
26 std::size_t pi = 0;
27 std::size_t ni = 0;
28
29 constexpr std::size_t k_no_star = std::numeric_limits<std::size_t>::max();
30 std::size_t star_pi = k_no_star;
31 std::size_t star_ni = 0;
32 bool star_is_dd = false; // true if the last unresolved star was '**'
33
34 while (ni < nlen) {
35 if (pi < plen && pattern[pi] == '*') {
36 const bool is_double = (pi + 1 < plen) && pattern[pi + 1] == '*';
37 star_pi = pi;
39 star_ni = ni;
40 pi += is_double ? 2 : 1;
41 continue;
42 }
43
44 if (pi < plen && pattern[pi] == name[ni]) {
45 ++pi;
46 ++ni;
47 continue;
48 }
49
50 if (star_pi != k_no_star) {
51 // Backtrack to last '*' (or '**'). Single '*' refuses to cross '.'.
52 if (!star_is_dd && name[star_ni] == '.') {
53 return false;
54 }
55 ++star_ni;
56 if (!star_is_dd && star_ni <= nlen && star_ni > 0 && name[star_ni - 1] == '.') {
57 return false;
58 }
59 ni = star_ni;
60 pi = star_pi + (star_is_dd ? 2 : 1);
61 continue;
62 }
63
64 return false;
65 }
66
67 // Consume trailing '*' / '**' in pattern.
68 while (pi < plen && pattern[pi] == '*') {
69 if (pi + 1 < plen && pattern[pi + 1] == '*') {
70 pi += 2;
71 } else {
72 pi += 1;
73 }
74 }
75
76 return pi == plen;
77}
78
79} // namespace detail
80
82class Glob {
83public:
84 explicit Glob(const std::string_view pattern) : storage_(pattern) {}
85 explicit Glob(const char* pattern) : storage_(pattern) {}
86 explicit Glob(std::string pattern) noexcept : storage_(std::move(pattern)) {}
87
88 Glob(const Glob&) = default;
89 Glob(Glob&&) noexcept = default;
90 Glob& operator=(const Glob&) = default;
91 Glob& operator=(Glob&&) noexcept = default;
92 ~Glob() = default;
93
94 [[nodiscard]] bool matches(const std::string_view name) const noexcept {
95 return detail::glob_match_impl(storage_, name);
96 }
97
98 [[nodiscard]] std::string_view pattern() const noexcept {
99 return storage_;
100 }
101
103 [[nodiscard]] static constexpr bool match(const std::string_view pattern,
104 const std::string_view name) noexcept {
105 return detail::glob_match_impl(pattern, name);
106 }
107
108private:
109 std::string storage_;
110};
111
112} // namespace conduit
Event-name glob matcher.
Definition glob.hpp:82
bool matches(const std::string_view name) const noexcept
Definition glob.hpp:94
static constexpr bool match(const std::string_view pattern, const std::string_view name) noexcept
Free function helper for one-shot matching.
Definition glob.hpp:103
std::string_view pattern() const noexcept
Definition glob.hpp:98
Glob(Glob &&) noexcept=default
Glob(const Glob &)=default
Glob(std::string pattern) noexcept
Definition glob.hpp:86
Glob(const std::string_view pattern)
Definition glob.hpp:84
Glob(const char *pattern)
Definition glob.hpp:85
flags::FlagSet collect_default_flags()
Definition event.hpp:86
constexpr bool glob_match_impl(const std::string_view pattern, const std::string_view name) noexcept
Definition glob.hpp:21
Definition builder.hpp:22