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