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
7#include "path_location.hpp"
8#include "../char_maps/char_maps.hpp"
9#include "../utility/utility.hpp"
10#include "../macros.hpp"
11#include <vector>
12#include <string>
13#include <string_view>
14#include <filesystem>
15#include <variant>
16#include <type_traits>
17#include <coroutine>
18
22hi_export_module(hikogui.path.glob);
23
24hi_export namespace hi { inline namespace v1 {
25
44hi_export class glob_pattern {
45public:
46 constexpr glob_pattern() noexcept = default;
47 constexpr glob_pattern(glob_pattern const&) noexcept = default;
48 constexpr glob_pattern(glob_pattern&&) noexcept = default;
49 constexpr glob_pattern& operator=(glob_pattern const&) noexcept = default;
50 constexpr glob_pattern& operator=(glob_pattern&&) noexcept = default;
51
56 constexpr glob_pattern(std::u32string_view str) : _tokens(parse(str)) {}
57
62 constexpr glob_pattern(std::u32string const& str) : glob_pattern(std::u32string_view{str}) {}
63
68 constexpr glob_pattern(char32_t const *str) : glob_pattern(std::u32string_view{str}) {}
69
74 constexpr glob_pattern(std::string_view str) : glob_pattern(hi::to_u32string(str)) {}
75
80 constexpr glob_pattern(std::string const& str) : glob_pattern(std::string_view{str}) {}
81
87 constexpr glob_pattern(char const *str) : glob_pattern(std::string_view{str}) {}
88
93 glob_pattern(std::filesystem::path const& path) : glob_pattern(path.generic_u32string()) {}
94
99 [[nodiscard]] constexpr std::u32string u32string() noexcept
100 {
101 auto r = std::u32string{};
102 for (auto const& token : _tokens) {
103 r += token.u32string();
104 }
105 return r;
106 }
107
112 [[nodiscard]] constexpr std::string string() noexcept
113 {
114 return hi::to_string(u32string());
115 }
116
123 [[nodiscard]] constexpr std::u32string debug_u32string() noexcept
124 {
125 auto r = std::u32string{};
126 for (auto const& token : _tokens) {
127 r += token.debug_u32string();
128 }
129 return r;
130 }
131
138 [[nodiscard]] constexpr std::string debug_string() noexcept
139 {
140 return hi::to_string(debug_u32string());
141 }
142
154 [[nodiscard]] constexpr std::u32string base_u32string() const noexcept
155 {
156 if (_tokens.empty() or not _tokens.front().is_text()) {
157 return {};
158 } else {
159 auto r = _tokens.front().u32string();
160 if (_tokens.size() >= 2 and _tokens[1].is_any_directory()) {
161 // An any_directory_type always includes at least 1 slash.
162 r += U'/';
163 }
164 return r;
165 }
166 }
167
179 [[nodiscard]] constexpr std::string base_string() const noexcept
180 {
181 return to_string(base_u32string());
182 }
183
194 [[nodiscard]] std::filesystem::path base_path() const noexcept
195 {
196 auto text = base_u32string();
197 if (auto i = text.rfind('/'); i == std::u32string::npos) {
198 // If there is no slash then there is no base directory.
199 text.clear();
200 } else {
201 // Include the trailing slash of the base directory.
202 text.resize(i + 1);
203 }
204 auto path = std::filesystem::path{std::move(text)};
205 path.make_preferred(); // returns a reference to *this.
206 return path;
207 }
208
214 [[nodiscard]] constexpr bool matches(std::u32string_view str) const noexcept
215 {
216 auto first = _tokens.cbegin();
217 auto last = _tokens.cend();
218
219 // Strip away the prefix and suffix quickly.
220 if (not matches_strip(first, last, str)) {
221 // The prefix and suffix of the do not match.
222 return false;
223
224 } else if (first == last) {
225 // All tokens matched the prefix and suffix.
226 // If the resulting string is empty than it is a match.
227 return str.empty();
228 }
229
230 // Do more complex matching with the stripped string.
231 return matches(first, last, str);
232 }
233
239 [[nodiscard]] constexpr bool matches(std::u32string const& str) const noexcept
240 {
241 return matches(std::u32string_view{str});
242 }
243
249 [[nodiscard]] constexpr bool matches(char32_t const *str) const noexcept
250 {
251 return matches(std::u32string_view{str});
252 }
253
259 [[nodiscard]] constexpr bool matches(std::string_view str) const noexcept
260 {
261 return matches(to_u32string(str));
262 }
263
269 [[nodiscard]] constexpr bool matches(std::string const& str) const noexcept
270 {
271 return matches(std::string_view{str});
272 }
273
279 [[nodiscard]] constexpr bool matches(char const *str) const noexcept
280 {
281 return matches(std::string_view{str});
282 }
283
289 [[nodiscard]] bool matches(std::filesystem::path const& path) const noexcept
290 {
291 return matches(path.generic_u32string());
292 }
293
294private:
295 enum class match_result_type { fail, success, unchecked };
296
297 class token_type {
298 public:
299 using text_type = std::u32string;
300 using character_class_type = std::vector<std::pair<char32_t, char32_t>>;
301 using alternation_type = std::vector<std::u32string>;
305
306 constexpr token_type(token_type const&) noexcept = default;
307 constexpr token_type(token_type&&) noexcept = default;
308 constexpr token_type& operator=(token_type const&) noexcept = default;
309 constexpr token_type& operator=(token_type&&) noexcept = default;
310
311 constexpr token_type(text_type&& rhs) noexcept : _value(std::move(rhs)) {}
312 constexpr token_type(character_class_type&& rhs) noexcept : _value(std::move(rhs)) {}
313 constexpr token_type(alternation_type&& rhs) noexcept : _value(std::move(rhs)) {}
314 constexpr token_type(any_character_type&& rhs) noexcept : _value(std::move(rhs)) {}
315 constexpr token_type(any_text_type&& rhs) noexcept : _value(std::move(rhs)) {}
316 constexpr token_type(any_directory_type&& rhs) noexcept : _value(std::move(rhs)) {}
317
318 [[nodiscard]] constexpr bool is_text() const noexcept
319 {
320 return std::holds_alternative<text_type>(_value);
321 }
322
323 [[nodiscard]] constexpr bool is_any_directory() const noexcept
324 {
325 return std::holds_alternative<any_directory_type>(_value);
326 }
327
328 template<bool Left>
329 [[nodiscard]] constexpr match_result_type strip(std::u32string_view& str) const noexcept
330 {
331 constexpr bool Right = not Left;
332
333 if (auto const text_ptr = std::get_if<text_type>(&_value)) {
334 if (Left and str.starts_with(*text_ptr)) {
335 str.remove_prefix(text_ptr->size());
336 return match_result_type::success;
337
338 } else if (Right and str.ends_with(*text_ptr)) {
339 str.remove_suffix(text_ptr->size());
340 return match_result_type::success;
341
342 } else {
343 return match_result_type::fail;
344 }
345
346 } else if (auto const character_class_ptr = std::get_if<character_class_type>(&_value)) {
347 if (str.empty()) {
348 return match_result_type::fail;
349 }
350 auto const c = Left ? str.front() : str.back();
351 for (auto const[first_char, last_char] : *character_class_ptr) {
352 if (c >= first_char and c <= last_char) {
353 if constexpr (Left) {
354 str.remove_prefix(1);
355 } else {
356 str.remove_suffix(1);
357 }
358 return match_result_type::success;
359 }
360 }
361 return match_result_type::fail;
362
363 } else if (std::holds_alternative<any_character_type>(_value)) {
364 if (str.empty()) {
365 return match_result_type::fail;
366 }
367 if constexpr (Left) {
368 str.remove_prefix(1);
369 } else {
370 str.remove_suffix(1);
371 }
372 return match_result_type::success;
373
374 } else {
375 return match_result_type::unchecked;
376 }
377 }
378
379 [[nodiscard]] constexpr match_result_type matches(std::u32string_view& str, size_t iteration) const noexcept
380 {
381 if (auto const text_ptr = std::get_if<text_type>(&_value)) {
382 if (iteration != 0) {
383 return match_result_type::fail;
384
385 } else if (str.starts_with(*text_ptr)) {
386 str.remove_prefix(text_ptr->size());
387 return match_result_type::success;
388
389 } else {
390 return match_result_type::fail;
391 }
392
393 } else if (auto const character_class_ptr = std::get_if<character_class_type>(&_value)) {
394 if (iteration != 0 or str.empty()) {
395 return match_result_type::fail;
396 } else {
397 auto const c = str.front();
398 for (auto const[first_char, last_char] : *character_class_ptr) {
399 if (c >= first_char and c <= last_char) {
400 str.remove_prefix(1);
401 return match_result_type::success;
402 }
403 }
404 return match_result_type::fail;
405 }
406
407 } else if (auto const alternation_ptr = std::get_if<alternation_type>(&_value)) {
408 if (iteration >= alternation_ptr->size()) {
409 return match_result_type::fail;
410 } else if (str.starts_with((*alternation_ptr)[iteration])) {
411 str.remove_prefix((*alternation_ptr)[iteration].size());
412 return match_result_type::success;
413 } else {
414 return match_result_type::unchecked;
415 }
416
417 } else if (std::holds_alternative<any_character_type>(_value)) {
418 if (iteration != 0 or str.empty()) {
419 return match_result_type::fail;
420 } else {
421 str.remove_prefix(1);
422 return match_result_type::success;
423 }
424
425 } else if (std::holds_alternative<any_text_type>(_value)) {
426 if (iteration > str.size() or iteration > str.find('/')) {
427 return match_result_type::fail;
428 } else {
429 str.remove_prefix(iteration);
430 return match_result_type::success;
431 }
432
433 } else if (std::holds_alternative<any_directory_type>(_value)) {
434 if (str.empty() or str.front() != '/') {
435 return match_result_type::fail;
436 } else {
437 for (auto i = 0_uz; i != std::u32string_view::npos; i = str.find('/', i + 1)) {
438 if (iteration-- == 0) {
439 str.remove_prefix(i + 1);
440 return match_result_type::success;
441 }
442 }
443 return match_result_type::fail;
444 }
445
446 } else {
447 hi_no_default();
448 }
449 }
450
451 [[nodiscard]] constexpr std::u32string u32string() const noexcept
452 {
453 auto r = std::u32string{};
454
455 if (auto text_ptr = std::get_if<text_type>(&_value)) {
456 r = *text_ptr;
457
458 } else if (auto character_class_ptr = std::get_if<character_class_type>(&_value)) {
459 r += U'[';
460 for (auto const[first_char, last_char] : *character_class_ptr) {
461 if (first_char == last_char) {
462 r += first_char;
463 } else {
464 r += first_char;
465 r += U'-';
466 r += last_char;
467 }
468 }
469 r += U']';
470
471 } else if (auto alternation_ptr = std::get_if<alternation_type>(&_value)) {
472 r += U'{';
473 for (auto const& text : *alternation_ptr) {
474 if (r.size() > 1) {
475 r += U',';
476 }
477 r += text;
478 }
479 r += U'}';
480
481 } else if (std::holds_alternative<any_character_type>(_value)) {
482 r += U'?';
483
484 } else if (std::holds_alternative<any_text_type>(_value)) {
485 r += U'*';
486
487 } else if (std::holds_alternative<any_directory_type>(_value)) {
488 r += U"/**/";
489
490 } else {
491 hi_no_default();
492 }
493
494 return r;
495 }
496
497 [[nodiscard]] constexpr std::u32string debug_u32string() const noexcept
498 {
499 auto r = std::u32string{};
500
501 if (auto text_ptr = std::get_if<text_type>(&_value)) {
502 r += U'\'';
503 r += *text_ptr;
504 r += U'\'';
505
506 } else if (auto character_class_ptr = std::get_if<character_class_type>(&_value)) {
507 r += U'[';
508 for (auto const[first_char, last_char] : *character_class_ptr) {
509 if (first_char == last_char) {
510 r += first_char;
511 } else {
512 r += first_char;
513 r += U'-';
514 r += last_char;
515 }
516 }
517 r += U']';
518
519 } else if (auto alternation_ptr = std::get_if<alternation_type>(&_value)) {
520 r += U'{';
521 for (auto const& text : *alternation_ptr) {
522 if (r.size() > 1) {
523 r += U',';
524 }
525 r += text;
526 }
527 r += U'}';
528
529 } else if (std::holds_alternative<any_character_type>(_value)) {
530 r += U'?';
531
532 } else if (std::holds_alternative<any_text_type>(_value)) {
533 r += U'*';
534
535 } else if (std::holds_alternative<any_directory_type>(_value)) {
536 r += U"/**/";
537
538 } else {
539 hi_no_default();
540 }
541
542 return r;
543 }
544
545 private:
546 using variant_type = std::
547 variant<text_type, character_class_type, alternation_type, any_character_type, any_text_type, any_directory_type>;
548
549 variant_type _value;
550 };
551
552 using tokens_type = std::vector<token_type>;
553 using const_iterator = tokens_type::const_iterator;
554
555 tokens_type _tokens;
556
557 [[nodiscard]] constexpr static token_type make_text(token_type::text_type&& rhs) noexcept
558 {
559 return token_type{std::move(rhs)};
560 }
561
562 [[nodiscard]] constexpr static token_type make_alternation(token_type::alternation_type&& rhs) noexcept
563 {
564 return token_type{std::move(rhs)};
565 }
566
567 [[nodiscard]] constexpr static token_type make_character_class(token_type::character_class_type&& rhs) noexcept
568 {
569 return token_type{std::move(rhs)};
570 }
571
572 [[nodiscard]] constexpr static token_type make_any_character() noexcept
573 {
574 return token_type{token_type::any_character_type{}};
575 }
576
577 [[nodiscard]] constexpr static token_type make_any_text() noexcept
578 {
579 return token_type{token_type::any_text_type{}};
580 }
581
582 [[nodiscard]] constexpr static token_type make_any_directory() noexcept
583 {
584 return token_type{token_type::any_directory_type{}};
585 }
586
587 [[nodiscard]] constexpr static tokens_type parse(auto first, auto last)
588 {
589#define HI_GLOB_APPEND_TEXT() \
590 do { \
591 if (not text.empty()) { \
592 r.emplace_back(make_text(std::move(text))); \
593 text.clear(); \
594 } \
595 } while (false)
596
597 enum class state_type { idle, star, slash, slash_star, slash_star_star, bracket, bracket_range, brace };
598 using enum state_type;
599
600 static_assert(std::is_same_v<std::decay_t<decltype(*first)>, char32_t>);
601
602 auto r = tokens_type{};
603
604 auto state = idle;
605 auto text = token_type::text_type{};
606 auto alternation = token_type::alternation_type{};
607 auto character_class = token_type::character_class_type{};
608
609 auto it = first;
610 while (it != last) {
611 auto c = *it;
612 switch (state) {
613 case idle:
614 switch (c) {
615 case U'/':
616 state = slash;
617 break;
618 case U'?':
619 HI_GLOB_APPEND_TEXT();
620 r.push_back(make_any_character());
621 break;
622 case U'*':
623 state = star;
624 break;
625 case U'[':
626 HI_GLOB_APPEND_TEXT();
627 state = bracket;
628 break;
629 case U'{':
630 HI_GLOB_APPEND_TEXT();
631 state = brace;
632 break;
633 default:
634 text += c;
635 }
636 break;
637
638 case star:
639 if (c == U'*') {
640 throw parse_error("Double ** is only allowed between slashes, like /**/.");
641 } else {
642 HI_GLOB_APPEND_TEXT();
643 r.push_back(make_any_text());
644 text += c;
645 state = idle;
646 }
647 break;
648
649 case slash:
650 if (c == U'*') {
651 state = slash_star;
652 } else {
653 text += U'/';
654 text += c;
655 state = idle;
656 }
657 break;
658
659 case slash_star:
660 if (c == U'*') {
661 state = slash_star_star;
662 } else {
663 text += U'/';
664 HI_GLOB_APPEND_TEXT();
665 r.push_back(make_any_text());
666 text += c;
667 state = idle;
668 }
669 break;
670
671 case slash_star_star:
672 if (c == U'/') {
673 HI_GLOB_APPEND_TEXT();
674 r.push_back(make_any_directory());
675 state = idle;
676 } else {
677 throw parse_error("Double ** is only allowed between slashes, like /**/.");
678 }
679 break;
680
681 case bracket:
682 if (c == U'-') {
683 if (character_class.empty()) {
684 character_class.emplace_back(c, c);
685 } else {
686 state = bracket_range;
687 }
688 } else if (c == U']') {
689 r.push_back(make_character_class(std::move(character_class)));
690 character_class.clear();
691 state = idle;
692 } else {
693 character_class.emplace_back(c, c);
694 }
695 break;
696
697 case bracket_range:
698 if (c == U'-') {
699 throw parse_error("Double '--' is not allowed inside a character class, i.e. between '[' and ']'.");
700 } else if (c == U']') {
701 character_class.emplace_back(U'-', U'-');
702 r.push_back(make_character_class(std::move(character_class)));
703 character_class.clear();
704 state = idle;
705 } else {
706 character_class.back().second = c;
707 state = bracket;
708 }
709 break;
710
711 case brace:
712 if (c == U'}') {
713 if (not text.empty()) {
714 alternation.push_back(std::move(text));
715 text.clear();
716 }
717 r.push_back(make_alternation(std::move(alternation)));
718 alternation.clear();
719 state = idle;
720 } else if (c == U',') {
721 alternation.push_back(std::move(text));
722 text.clear();
723 } else {
724 text += c;
725 }
726 break;
727
728 default:
729 hi_no_default();
730 }
731
732 ++it;
733 }
734
735 switch (state) {
736 case idle:
737 HI_GLOB_APPEND_TEXT();
738 break;
739
740 case star:
741 HI_GLOB_APPEND_TEXT();
742 r.push_back(make_any_text());
743 break;
744
745 case slash:
746 text += U'/';
747 HI_GLOB_APPEND_TEXT();
748 break;
749
750 case slash_star:
751 text += U'/';
752 HI_GLOB_APPEND_TEXT();
753 r.push_back(make_any_text());
754 break;
755
756 case slash_star_star:
757 HI_GLOB_APPEND_TEXT();
758 r.push_back(make_any_directory());
759 break;
760
761 case bracket:
762 throw parse_error("Unclosed bracket '[' found in glob pattern.");
763
764 case bracket_range:
765 throw parse_error("Unclosed bracket '[' found in glob pattern.");
766
767 case brace:
768 throw parse_error("Unclosed brace '{' found in glob pattern.");
769 }
770
771 return r;
772
773#undef HI_GLOB_APPEND_TEXT
774 }
775
776 [[nodiscard]] constexpr static tokens_type parse(auto&& range)
777 {
778 return parse(std::ranges::begin(range), std::ranges::end(range));
779 }
780
781 template<bool Left>
782 [[nodiscard]] constexpr static bool
783 matches_strip(const_iterator& first, const_iterator& last, std::u32string_view& str) noexcept
784 {
785 while (first != last) {
786 auto const it = Left ? first : last - 1;
787 switch (it->strip<Left>(str)) {
788 case match_result_type::fail:
789 return false;
790 case match_result_type::unchecked:
791 return true;
792 case match_result_type::success:
793 if constexpr (Left) {
794 ++first;
795 } else {
796 --last;
797 }
798 break;
799 default:
800 hi_no_default();
801 }
802 }
803 return str.empty();
804 }
805
806 [[nodiscard]] constexpr static bool
807 matches_strip(const_iterator& first, const_iterator& last, std::u32string_view& str) noexcept
808 {
809 return matches_strip<true>(first, last, str) and matches_strip<false>(first, last, str);
810 }
811
812 [[nodiscard]] constexpr bool matches(const_iterator it, const_iterator last, std::u32string_view original) const noexcept
813 {
814 hi_assert(it != last);
815
816 struct stack_element {
817 std::u32string_view str;
818 size_t iteration;
819 };
820
821 auto stack = std::vector<stack_element>{};
822 stack.reserve(std::distance(it, last));
823
824 stack.emplace_back(original, 0);
825 while (true) {
826 auto [str, iteration] = stack.back();
827
828 switch (it->matches(str, iteration)) {
829 case match_result_type::success:
830 if (it + 1 == last) {
831 if (str.empty()) {
832 // This token fully matches the whole string.
833 return true;
834
835 } else {
836 // This token matches, but this is the last token.
837 // Try the next iteration on this token.
838 ++stack.back().iteration;
839 }
840
841 } else {
842 // This token matches, test the next token.
843 stack.emplace_back(str, 0);
844 ++it;
845 }
846 break;
847
848 case match_result_type::unchecked:
849 // This iteration of the token did not match, try the next iteration.
850 ++stack.back().iteration;
851 break;
852
853 case match_result_type::fail:
854 // None of the token iterations succeeded.
855 if (stack.size() == 1) {
856 // Can't track further back; the complete match failed.
857 return false;
858
859 } else {
860 // Track back and try the next iteration of the previous token.
861 stack.pop_back();
862 ++stack.back().iteration;
863 --it;
864 }
865 break;
866
867 default:
868 hi_no_default();
869 }
870 }
871 }
872};
873
880hi_export [[nodiscard]] inline generator<std::filesystem::path> glob(glob_pattern pattern) noexcept
881{
882 auto path = pattern.base_path();
883
884 auto const last = std::filesystem::recursive_directory_iterator{};
885
886 auto first = last;
887 try {
888 first = std::filesystem::recursive_directory_iterator(path);
889 } catch (...) {
890 co_return;
891 }
892
893 for (auto it = first; it != last; ++it) {
894 std::filesystem::path const *iterated_path = nullptr;
895 try {
896 iterated_path = std::addressof(it->path());
897 } catch (...) {
898 continue;
899 }
900
901 if (pattern.matches(*iterated_path)) {
902 co_yield *iterated_path;
903 }
904 }
905}
906
913hi_export [[nodiscard]] inline generator<std::filesystem::path> glob(std::string_view pattern) noexcept
914{
915 return glob(glob_pattern{pattern});
916}
917
924hi_export [[nodiscard]] inline generator<std::filesystem::path> glob(std::string pattern) noexcept
925{
926 return glob(glob_pattern{std::move(pattern)});
927}
928
935hi_export [[nodiscard]] inline generator<std::filesystem::path> glob(char const *pattern) noexcept
936{
937 return glob(glob_pattern{pattern});
938}
939
946hi_export [[nodiscard]] inline generator<std::filesystem::path> glob(std::filesystem::path pattern) noexcept
947{
948 return glob(glob_pattern{std::move(pattern)});
949}
950
958hi_export template<path_range Locations>
959[[nodiscard]] inline generator<std::filesystem::path> glob(Locations&& locations, std::filesystem::path ref) noexcept
960{
961 for (auto const& directory : locations) {
962 for (auto const& path : glob(directory / ref)) {
963 co_yield path;
964 }
965 }
966}
967
975hi_export template<path_range Locations>
976[[nodiscard]] inline generator<std::filesystem::path> glob(Locations&& locations, std::string_view ref) noexcept
977{
978 return glob(std::forward<Locations>(locations), std::filesystem::path{ref});
979}
980
988hi_export template<path_range Locations>
989[[nodiscard]] inline generator<std::filesystem::path> glob(Locations&& locations, std::string ref) noexcept
990{
991 return glob(std::forward<Locations>(locations), std::filesystem::path{ref});
992}
993
1001hi_export template<path_range Locations>
1002[[nodiscard]] inline generator<std::filesystem::path> glob(Locations&& locations, char const *ref) noexcept
1003{
1004 return glob(std::forward<Locations>(locations), std::filesystem::path{ref});
1005}
1006
1007}} // namespace hi::v1
functions to locate files and directories.
constexpr std::u32string to_u32string(std::u32string_view rhs) noexcept
Identity conversion from UTF-32 to UTF-32.
Definition to_string.hpp:28
hi_export generator< std::filesystem::path > glob(glob_pattern pattern) noexcept
Find paths on the filesystem that match the glob pattern.
Definition glob.hpp:880
STL namespace.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition token.hpp:18
A glob pattern.
Definition glob.hpp:44
constexpr bool matches(std::string const &str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:269
constexpr std::u32string base_u32string() const noexcept
Get the initial fixed part of the pattern.
Definition glob.hpp:154
constexpr std::string debug_string() noexcept
Convert a glob-pattern to a debug-string.
Definition glob.hpp:138
constexpr glob_pattern(std::u32string const &str)
Parse a string to a glob-pattern.
Definition glob.hpp:62
constexpr std::u32string u32string() noexcept
Convert a glob-pattern to a string.
Definition glob.hpp:99
constexpr glob_pattern(char32_t const *str)
Parse a string to a glob-pattern.
Definition glob.hpp:68
constexpr std::u32string debug_u32string() noexcept
Convert a glob-pattern to a debug-string.
Definition glob.hpp:123
constexpr bool matches(std::u32string const &str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:239
constexpr bool matches(char32_t const *str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:249
constexpr glob_pattern(std::u32string_view str)
Parse a string to a glob-pattern.
Definition glob.hpp:56
constexpr glob_pattern(char const *str)
Parse a string to a glob-pattern.
Definition glob.hpp:87
constexpr std::string base_string() const noexcept
Get the initial fixed part of the pattern.
Definition glob.hpp:179
constexpr bool matches(std::u32string_view str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:214
glob_pattern(std::filesystem::path const &path)
Parse a path to a glob-pattern.
Definition glob.hpp:93
constexpr glob_pattern(std::string const &str)
Parse a string to a glob-pattern.
Definition glob.hpp:80
std::filesystem::path base_path() const noexcept
Get the initial path of the pattern.
Definition glob.hpp:194
bool matches(std::filesystem::path const &path) const noexcept
Match the pattern with the given path.
Definition glob.hpp:289
constexpr glob_pattern(std::string_view str)
Parse a string to a glob-pattern.
Definition glob.hpp:74
constexpr bool matches(std::string_view str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:259
constexpr std::string string() noexcept
Convert a glob-pattern to a string.
Definition glob.hpp:112
constexpr bool matches(char const *str) const noexcept
Match the pattern with the given string.
Definition glob.hpp:279
T addressof(T... args)
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)