HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
glob.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
11#include "path_location.hpp"
13#include "../utility.hpp"
14#include "../type_traits.hpp"
15#include <vector>
16#include <string>
17#include <string_view>
18#include <filesystem>
19#include <variant>
20#include <type_traits>
21
22namespace hi { inline namespace v1 {
23
43public:
44 constexpr glob_pattern() noexcept = default;
45 constexpr glob_pattern(glob_pattern const&) noexcept = default;
46 constexpr glob_pattern(glob_pattern&&) noexcept = default;
47 constexpr glob_pattern& operator=(glob_pattern const&) noexcept = default;
48 constexpr glob_pattern& operator=(glob_pattern&&) noexcept = default;
49
54 glob_pattern(std::u32string_view str) : _tokens(parse(str)) {}
55
60 glob_pattern(std::u32string const& str) : glob_pattern(std::u32string_view{str}) {}
61
66 glob_pattern(char32_t const *str) : glob_pattern(std::u32string_view{str}) {}
67
72 glob_pattern(std::string_view str) : glob_pattern(hi::to_u32string(str)) {}
73
78 glob_pattern(std::string const& str) : glob_pattern(std::string_view{str}) {}
79
85 glob_pattern(char const *str) : glob_pattern(std::string_view{str}) {}
86
91 glob_pattern(std::filesystem::path const& path) : glob_pattern(path.generic_u32string()) {}
92
97 [[nodiscard]] constexpr std::u32string u32string() noexcept
98 {
99 auto r = std::u32string{};
100 for (hilet& token : _tokens) {
101 r += token.u32string();
102 }
103 return r;
104 }
105
110 [[nodiscard]] constexpr std::string string() noexcept
111 {
112 return hi::to_string(u32string());
113 }
114
121 [[nodiscard]] constexpr std::u32string debug_u32string() noexcept
122 {
123 auto r = std::u32string{};
124 for (hilet& token : _tokens) {
125 r += token.debug_u32string();
126 }
127 return r;
128 }
129
136 [[nodiscard]] constexpr std::string debug_string() noexcept
137 {
139 }
140
152 [[nodiscard]] constexpr std::u32string base_u32string() const noexcept
153 {
154 if (_tokens.empty() or not _tokens.front().is_text()) {
155 return {};
156 } else {
157 auto r = _tokens.front().u32string();
158 if (_tokens.size() >= 2 and _tokens[1].is_any_directory()) {
159 // An any_directory_type always includes at least 1 slash.
160 r += U'/';
161 }
162 return r;
163 }
164 }
165
177 [[nodiscard]] constexpr std::string base_string() const noexcept
178 {
179 return to_string(base_u32string());
180 }
181
192 [[nodiscard]] std::filesystem::path base_path() const noexcept
193 {
194 auto text = base_u32string();
195 if (auto i = text.rfind('/'); i == std::u32string::npos) {
196 // If there is no slash then there is no base directory.
197 text.clear();
198 } else {
199 // Include the trailing slash of the base directory.
200 text.resize(i + 1);
201 }
202 return {std::move(text)};
203 }
204
210 [[nodiscard]] constexpr bool matches(std::u32string_view str) const noexcept
211 {
212 auto first = _tokens.cbegin();
213 auto last = _tokens.cend();
214
215 // Strip away the prefix and suffix quickly.
216 if (not matches_strip(first, last, str)) {
217 // The prefix and suffix of the do not match.
218 return false;
219
220 } else if (first == last) {
221 // All tokens matched the prefix and suffix.
222 // If the resulting string is empty than it is a match.
223 return str.empty();
224 }
225
226 // Do more complex matching with the stripped string.
227 return matches(first, last, str);
228 }
229
235 [[nodiscard]] constexpr bool matches(std::u32string const& str) const noexcept
236 {
237 return matches(std::u32string_view{str});
238 }
239
245 [[nodiscard]] constexpr bool matches(char32_t const *str) const noexcept
246 {
247 return matches(std::u32string_view{str});
248 }
249
255 [[nodiscard]] constexpr bool matches(std::string_view str) const noexcept
256 {
257 return matches(to_u32string(str));
258 }
259
265 [[nodiscard]] constexpr bool matches(std::string const& str) const noexcept
266 {
267 return matches(std::string_view{str});
268 }
269
275 [[nodiscard]] constexpr bool matches(char const *str) const noexcept
276 {
277 return matches(std::string_view{str});
278 }
279
285 [[nodiscard]] bool matches(std::filesystem::path const& path) const noexcept
286 {
287 return matches(path.generic_u32string());
288 }
289
290private:
291 enum class match_result_type { fail, success, unchecked };
292
293 class token_type {
294 public:
295 using text_type = std::u32string;
296 using character_class_type = std::vector<std::pair<char32_t, char32_t>>;
297 using alternation_type = std::vector<std::u32string>;
301
302 constexpr token_type(token_type const&) noexcept = default;
303 constexpr token_type(token_type&&) noexcept = default;
304 constexpr token_type& operator=(token_type const&) noexcept = default;
305 constexpr token_type& operator=(token_type&&) noexcept = default;
306
307 constexpr token_type(text_type&& rhs) noexcept : _value(std::move(rhs)) {}
308 constexpr token_type(character_class_type&& rhs) noexcept : _value(std::move(rhs)) {}
309 constexpr token_type(alternation_type&& rhs) noexcept : _value(std::move(rhs)) {}
310 constexpr token_type(any_character_type&& rhs) noexcept : _value(std::move(rhs)) {}
311 constexpr token_type(any_text_type&& rhs) noexcept : _value(std::move(rhs)) {}
312 constexpr token_type(any_directory_type&& rhs) noexcept : _value(std::move(rhs)) {}
313
314 [[nodiscard]] constexpr bool is_text() const noexcept
315 {
316 return std::holds_alternative<text_type>(_value);
317 }
318
319 [[nodiscard]] constexpr bool is_any_directory() const noexcept
320 {
321 return std::holds_alternative<any_directory_type>(_value);
322 }
323
324 template<bool Left>
325 [[nodiscard]] constexpr match_result_type strip(std::u32string_view& str) const noexcept
326 {
327 constexpr bool Right = not Left;
328
329 if (hilet text_ptr = std::get_if<text_type>(&_value)) {
330 if (Left and str.starts_with(*text_ptr)) {
331 str.remove_prefix(text_ptr->size());
332 return match_result_type::success;
333
334 } else if (Right and str.ends_with(*text_ptr)) {
335 str.remove_suffix(text_ptr->size());
336 return match_result_type::success;
337
338 } else {
339 return match_result_type::fail;
340 }
341
342 } else if (hilet character_class_ptr = std::get_if<character_class_type>(&_value)) {
343 if (str.empty()) {
344 return match_result_type::fail;
345 }
346 hilet c = Left ? str.front() : str.back();
347 for (hilet[first_char, last_char] : *character_class_ptr) {
348 if (c >= first_char and c <= last_char) {
349 if constexpr (Left) {
350 str.remove_prefix(1);
351 } else {
352 str.remove_suffix(1);
353 }
354 return match_result_type::success;
355 }
356 }
357 return match_result_type::fail;
358
359 } else if (std::holds_alternative<any_character_type>(_value)) {
360 if (str.empty()) {
361 return match_result_type::fail;
362 }
363 if constexpr (Left) {
364 str.remove_prefix(1);
365 } else {
366 str.remove_suffix(1);
367 }
368 return match_result_type::success;
369
370 } else {
371 return match_result_type::unchecked;
372 }
373 }
374
375 [[nodiscard]] constexpr match_result_type matches(std::u32string_view& str, size_t iteration) const noexcept
376 {
377 if (hilet text_ptr = std::get_if<text_type>(&_value)) {
378 if (iteration != 0) {
379 return match_result_type::fail;
380
381 } else if (str.starts_with(*text_ptr)) {
382 str.remove_prefix(text_ptr->size());
383 return match_result_type::success;
384
385 } else {
386 return match_result_type::fail;
387 }
388
389 } else if (hilet character_class_ptr = std::get_if<character_class_type>(&_value)) {
390 if (iteration != 0 or str.empty()) {
391 return match_result_type::fail;
392 } else {
393 hilet c = str.front();
394 for (hilet[first_char, last_char] : *character_class_ptr) {
395 if (c >= first_char and c <= last_char) {
396 str.remove_prefix(1);
397 return match_result_type::success;
398 }
399 }
400 return match_result_type::fail;
401 }
402
403 } else if (hilet alternation_ptr = std::get_if<alternation_type>(&_value)) {
404 if (iteration >= alternation_ptr->size()) {
405 return match_result_type::fail;
406 } else if (str.starts_with((*alternation_ptr)[iteration])) {
407 str.remove_prefix((*alternation_ptr)[iteration].size());
408 return match_result_type::success;
409 } else {
410 return match_result_type::unchecked;
411 }
412
413 } else if (std::holds_alternative<any_character_type>(_value)) {
414 if (iteration != 0 or str.empty()) {
415 return match_result_type::fail;
416 } else {
417 str.remove_prefix(1);
418 return match_result_type::success;
419 }
420
421 } else if (std::holds_alternative<any_text_type>(_value)) {
422 if (iteration > str.size() or iteration > str.find('/')) {
423 return match_result_type::fail;
424 } else {
425 str.remove_prefix(iteration);
426 return match_result_type::success;
427 }
428
429 } else if (std::holds_alternative<any_directory_type>(_value)) {
430 if (str.empty() or str.front() != '/') {
431 return match_result_type::fail;
432 } else {
433 for (auto i = 0_uz; i != std::u32string_view::npos; i = str.find('/', i + 1)) {
434 if (iteration-- == 0) {
435 str.remove_prefix(i + 1);
436 return match_result_type::success;
437 }
438 }
439 return match_result_type::fail;
440 }
441
442 } else {
444 }
445 }
446
447 [[nodiscard]] constexpr std::u32string u32string() const noexcept
448 {
449 auto r = std::u32string{};
450
451 if (auto text_ptr = std::get_if<text_type>(&_value)) {
452 r = *text_ptr;
453
454 } else if (auto character_class_ptr = std::get_if<character_class_type>(&_value)) {
455 r += U'[';
456 for (hilet[first_char, last_char] : *character_class_ptr) {
457 if (first_char == last_char) {
458 r += first_char;
459 } else {
460 r += first_char;
461 r += U'-';
462 r += last_char;
463 }
464 }
465 r += U']';
466
467 } else if (auto alternation_ptr = std::get_if<alternation_type>(&_value)) {
468 r += U'{';
469 for (hilet& text : *alternation_ptr) {
470 if (r.size() > 1) {
471 r += U',';
472 }
473 r += text;
474 }
475 r += U'}';
476
477 } else if (std::holds_alternative<any_character_type>(_value)) {
478 r += U'?';
479
480 } else if (std::holds_alternative<any_text_type>(_value)) {
481 r += U'*';
482
483 } else if (std::holds_alternative<any_directory_type>(_value)) {
484 r += U"/**/";
485
486 } else {
488 }
489
490 return r;
491 }
492
493 [[nodiscard]] constexpr std::u32string debug_u32string() const noexcept
494 {
495 auto r = std::u32string{};
496
497 if (auto text_ptr = std::get_if<text_type>(&_value)) {
498 r += U'\'';
499 r += *text_ptr;
500 r += U'\'';
501
502 } else if (auto character_class_ptr = std::get_if<character_class_type>(&_value)) {
503 r += U'[';
504 for (hilet[first_char, last_char] : *character_class_ptr) {
505 if (first_char == last_char) {
506 r += first_char;
507 } else {
508 r += first_char;
509 r += U'-';
510 r += last_char;
511 }
512 }
513 r += U']';
514
515 } else if (auto alternation_ptr = std::get_if<alternation_type>(&_value)) {
516 r += U'{';
517 for (hilet& text : *alternation_ptr) {
518 if (r.size() > 1) {
519 r += U',';
520 }
521 r += text;
522 }
523 r += U'}';
524
525 } else if (std::holds_alternative<any_character_type>(_value)) {
526 r += U'?';
527
528 } else if (std::holds_alternative<any_text_type>(_value)) {
529 r += U'*';
530
531 } else if (std::holds_alternative<any_directory_type>(_value)) {
532 r += U"/**/";
533
534 } else {
536 }
537
538 return r;
539 }
540
541 private:
542 using variant_type = std::
543 variant<text_type, character_class_type, alternation_type, any_character_type, any_text_type, any_directory_type>;
544
545 variant_type _value;
546 };
547
548 using tokens_type = std::vector<token_type>;
549 using const_iterator = tokens_type::const_iterator;
550
551 tokens_type _tokens;
552
553 [[nodiscard]] constexpr static token_type make_text(token_type::text_type&& rhs) noexcept
554 {
555 return token_type{std::move(rhs)};
556 }
557
558 [[nodiscard]] constexpr static token_type make_alternation(token_type::alternation_type&& rhs) noexcept
559 {
560 return token_type{std::move(rhs)};
561 }
562
563 [[nodiscard]] constexpr static token_type make_character_class(token_type::character_class_type&& rhs) noexcept
564 {
565 return token_type{std::move(rhs)};
566 }
567
568 [[nodiscard]] constexpr static token_type make_any_character() noexcept
569 {
570 return token_type{token_type::any_character_type{}};
571 }
572
573 [[nodiscard]] constexpr static token_type make_any_text() noexcept
574 {
575 return token_type{token_type::any_text_type{}};
576 }
577
578 [[nodiscard]] constexpr static token_type make_any_directory() noexcept
579 {
580 return token_type{token_type::any_directory_type{}};
581 }
582
583 [[nodiscard]] constexpr static tokens_type parse(auto first, auto last)
584 {
585#define HI_GLOB_APPEND_TEXT() \
586 do { \
587 if (not text.empty()) { \
588 r.emplace_back(make_text(std::move(text))); \
589 text.clear(); \
590 } \
591 } while (false)
592
593 enum class state_type { idle, star, slash, slash_star, slash_star_star, bracket, bracket_range, brace };
594 using enum state_type;
595
596 static_assert(std::is_same_v<std::decay_t<decltype(*first)>, char32_t>);
597
598 auto r = tokens_type{};
599
600 auto state = idle;
601 auto text = token_type::text_type{};
602 auto alternation = token_type::alternation_type{};
603 auto character_class = token_type::character_class_type{};
604
605 auto it = first;
606 while (it != last) {
607 auto c = *it;
608 switch (state) {
609 case idle:
610 switch (c) {
611 case U'/':
612 state = slash;
613 break;
614 case U'?':
615 HI_GLOB_APPEND_TEXT();
616 r.push_back(make_any_character());
617 break;
618 case U'*':
619 state = star;
620 break;
621 case U'[':
622 HI_GLOB_APPEND_TEXT();
623 state = bracket;
624 break;
625 case U'{':
626 HI_GLOB_APPEND_TEXT();
627 state = brace;
628 break;
629 default:
630 text += c;
631 }
632 break;
633
634 case star:
635 if (c == U'*') {
636 throw parse_error("Double ** is only allowed between slashes, like /**/.");
637 } else {
638 HI_GLOB_APPEND_TEXT();
639 r.push_back(make_any_text());
640 text += c;
641 state = idle;
642 }
643 break;
644
645 case slash:
646 if (c == U'*') {
647 state = slash_star;
648 } else {
649 text += U'/';
650 text += c;
651 state = idle;
652 }
653 break;
654
655 case slash_star:
656 if (c == U'*') {
657 state = slash_star_star;
658 } else {
659 text += U'/';
660 HI_GLOB_APPEND_TEXT();
661 r.push_back(make_any_text());
662 text += c;
663 state = idle;
664 }
665 break;
666
667 case slash_star_star:
668 if (c == U'/') {
669 HI_GLOB_APPEND_TEXT();
670 r.push_back(make_any_directory());
671 state = idle;
672 } else {
673 throw parse_error("Double ** is only allowed between slashes, like /**/.");
674 }
675 break;
676
677 case bracket:
678 if (c == U'-') {
679 if (character_class.empty()) {
680 character_class.emplace_back(c, c);
681 } else {
682 state = bracket_range;
683 }
684 } else if (c == U']') {
685 r.push_back(make_character_class(std::move(character_class)));
686 character_class.clear();
687 state = idle;
688 } else {
689 character_class.emplace_back(c, c);
690 }
691 break;
692
693 case bracket_range:
694 if (c == U'-') {
695 throw parse_error("Double '--' is not allowed inside a character class, i.e. between '[' and ']'.");
696 } else if (c == U']') {
697 character_class.emplace_back(U'-', U'-');
698 r.push_back(make_character_class(std::move(character_class)));
699 character_class.clear();
700 state = idle;
701 } else {
702 character_class.back().second = c;
703 state = bracket;
704 }
705 break;
706
707 case brace:
708 if (c == U'}') {
709 if (not text.empty()) {
710 alternation.push_back(std::move(text));
711 text.clear();
712 }
713 r.push_back(make_alternation(std::move(alternation)));
714 alternation.clear();
715 state = idle;
716 } else if (c == U',') {
717 alternation.push_back(std::move(text));
718 text.clear();
719 } else {
720 text += c;
721 }
722 break;
723
724 default:
726 }
727
728 ++it;
729 }
730
731 switch (state) {
732 case idle:
733 HI_GLOB_APPEND_TEXT();
734 break;
735
736 case star:
737 HI_GLOB_APPEND_TEXT();
738 r.push_back(make_any_text());
739 break;
740
741 case slash:
742 text += U'/';
743 HI_GLOB_APPEND_TEXT();
744 break;
745
746 case slash_star:
747 text += U'/';
748 HI_GLOB_APPEND_TEXT();
749 r.push_back(make_any_text());
750 break;
751
752 case slash_star_star:
753 HI_GLOB_APPEND_TEXT();
754 r.push_back(make_any_directory());
755 break;
756
757 case bracket:
758 throw parse_error("Unclosed bracket '[' found in glob pattern.");
759
760 case bracket_range:
761 throw parse_error("Unclosed bracket '[' found in glob pattern.");
762
763 case brace:
764 throw parse_error("Unclosed brace '{' found in glob pattern.");
765 }
766
767 return r;
768
769#undef HI_GLOB_APPEND_TEXT
770 }
771
772 [[nodiscard]] constexpr static tokens_type parse(auto&& range)
773 {
774 return parse(std::ranges::begin(range), std::ranges::end(range));
775 }
776
777 template<bool Left>
778 [[nodiscard]] constexpr static bool
779 matches_strip(const_iterator& first, const_iterator& last, std::u32string_view& str) noexcept
780 {
781 while (first != last) {
782 hilet it = Left ? first : last - 1;
783 switch (it->strip<Left>(str)) {
784 case match_result_type::fail:
785 return false;
786 case match_result_type::unchecked:
787 return true;
788 case match_result_type::success:
789 if constexpr (Left) {
790 ++first;
791 } else {
792 --last;
793 }
794 break;
795 default:
797 }
798 }
799 return str.empty();
800 }
801
802 [[nodiscard]] constexpr static bool
803 matches_strip(const_iterator& first, const_iterator& last, std::u32string_view& str) noexcept
804 {
805 return matches_strip<true>(first, last, str) and matches_strip<false>(first, last, str);
806 }
807
808 [[nodiscard]] constexpr bool matches(const_iterator it, const_iterator last, std::u32string_view original) const noexcept
809 {
810 hi_assert(it != last);
811
812 struct stack_element {
813 std::u32string_view str;
814 size_t iteration;
815 };
816
817 auto stack = std::vector<stack_element>{};
818 stack.reserve(std::distance(it, last));
819
820 stack.emplace_back(original, 0);
821 while (true) {
822 auto [str, iteration] = stack.back();
823
824 switch (it->matches(str, iteration)) {
825 case match_result_type::success:
826 if (it + 1 == last) {
827 if (str.empty()) {
828 // This token fully matches the whole string.
829 return true;
830
831 } else {
832 // This token matches, but this is the last token.
833 // Try the next iteration on this token.
834 ++stack.back().iteration;
835 }
836
837 } else {
838 // This token matches, test the next token.
839 stack.emplace_back(str, 0);
840 ++it;
841 }
842 break;
843
844 case match_result_type::unchecked:
845 // This iteration of the token did not match, try the next iteration.
846 ++stack.back().iteration;
847 break;
848
849 case match_result_type::fail:
850 // None of the token iterations succeeded.
851 if (stack.size() == 1) {
852 // Can't track further back; the complete match failed.
853 return false;
854
855 } else {
856 // Track back and try the next iteration of the previous token.
857 stack.pop_back();
858 ++stack.back().iteration;
859 --it;
860 }
861 break;
862
863 default:
865 }
866 }
867 }
868};
869
876[[nodiscard]] inline generator<std::filesystem::path> glob(glob_pattern pattern)
877{
878 auto path = pattern.base_path();
879
880 hilet first = std::filesystem::recursive_directory_iterator(path);
881 hilet last = std::filesystem::recursive_directory_iterator();
882 for (auto it = first; it != last; ++it) {
883 hilet& iterated_path = it->path();
884 if (pattern.matches(iterated_path)) {
885 co_yield iterated_path;
886 }
887 }
888}
889
896[[nodiscard]] inline generator<std::filesystem::path> glob(std::string_view pattern)
897{
898 return glob(glob_pattern{std::move(pattern)});
899}
900
907[[nodiscard]] inline generator<std::filesystem::path> glob(std::string pattern)
908{
909 return glob(glob_pattern{std::move(pattern)});
910}
911
918[[nodiscard]] inline generator<std::filesystem::path> glob(char const *pattern)
919{
920 return glob(glob_pattern{pattern});
921}
922
929[[nodiscard]] inline generator<std::filesystem::path> glob(std::filesystem::path pattern)
930{
931 return glob(glob_pattern{std::move(pattern)});
932}
933
941[[nodiscard]] inline generator<std::filesystem::path> glob(path_location location, std::filesystem::path ref)
942{
943 for (hilet& directory : get_paths(location)) {
944 for (hilet& path : glob(directory / ref)) {
945 co_yield path;
946 }
947 }
948}
949
957[[nodiscard]] inline generator<std::filesystem::path> glob(path_location location, std::string_view ref)
958{
959 return glob(location, std::filesystem::path{std::move(ref)});
960}
961
969[[nodiscard]] inline generator<std::filesystem::path> glob(path_location location, std::string ref)
970{
971 return glob(location, std::filesystem::path{std::move(ref)});
972}
973
981[[nodiscard]] inline generator<std::filesystem::path> glob(path_location location, char const *ref)
982{
983 return glob(location, std::filesystem::path{ref});
984}
985
986}} // namespace hi::v1
#define hi_assert(expression)
Assert if expression is true.
Definition assert.hpp:86
#define hi_no_default()
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:145
functions to locate files and directories.
Utilities used by the HikoGUI library itself.
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
String conversion functions.
constexpr std::string to_string(std::u32string_view rhs) noexcept
Conversion from UTF-32 to UTF-8.
Definition to_string.hpp:215
constexpr std::u32string to_u32string(std::u32string_view rhs) noexcept
Identity conversion from UTF-32 to UTF-32.
Definition to_string.hpp:23
path_location
File and Directory locations.
Definition path_location.hpp:21
generator< std::filesystem::path > glob(glob_pattern pattern)
Find paths on the filesystem that match the glob pattern.
Definition glob.hpp:876
generator< std::filesystem::path > get_paths(path_location location)
Get a set of paths.
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
A glob pattern.
Definition glob.hpp:42
glob_pattern(char const *str)
Parse a string to a glob-pattern.
Definition glob.hpp:85
constexpr bool matches(std::string const &str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:265
glob_pattern(std::string_view str)
Parse a string to a glob-pattern.
Definition glob.hpp:72
constexpr std::u32string base_u32string() const noexcept
Get the initial fixed part of the pattern.
Definition glob.hpp:152
constexpr std::string debug_string() noexcept
Convert a glob-pattern to a debug-string.
Definition glob.hpp:136
constexpr std::u32string u32string() noexcept
Convert a glob-pattern to a string.
Definition glob.hpp:97
constexpr std::u32string debug_u32string() noexcept
Convert a glob-pattern to a debug-string.
Definition glob.hpp:121
constexpr bool matches(std::u32string const &str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:235
constexpr bool matches(char32_t const *str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:245
glob_pattern(std::string const &str)
Parse a string to a glob-pattern.
Definition glob.hpp:78
constexpr std::string base_string() const noexcept
Get the initial fixed part of the pattern.
Definition glob.hpp:177
glob_pattern(std::u32string_view str)
Parse a string to a glob-pattern.
Definition glob.hpp:54
glob_pattern(char32_t const *str)
Parse a string to a glob-pattern.
Definition glob.hpp:66
constexpr bool matches(std::u32string_view str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:210
glob_pattern(std::filesystem::path const &path)
Parse a path to a glob-pattern.
Definition glob.hpp:91
std::filesystem::path base_path() const noexcept
Get the initial path of the pattern.
Definition glob.hpp:192
glob_pattern(std::u32string const &str)
Parse a string to a glob-pattern.
Definition glob.hpp:60
bool matches(std::filesystem::path const &path) const noexcept
Match the pattern with the given path.
Definition glob.hpp:285
constexpr bool matches(std::string_view str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:255
constexpr std::string string() noexcept
Convert a glob-pattern to a string.
Definition glob.hpp:110
constexpr bool matches(char const *str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:275
T cbegin(T... args)
T distance(T... args)
T empty(T... args)
T cend(T... args)
T front(T... args)
T move(T... args)
T reserve(T... args)
T size(T... args)