dius 0.1.0
Loading...
Searching...
No Matches
recursive_directory_iterator.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/container/queue/prelude.h"
4#include "dius/filesystem/directory_iterator.h"
5
6namespace dius::filesystem {
8 : public di::container::IteratorBase<RecursiveDirectoryIterator, di::InputIteratorTag,
9 di::Expected<DirectoryEntry, di::GenericCode>, i64>
10 , public di::meta::EnableBorrowedContainer<RecursiveDirectoryIterator>
11 , public di::meta::EnableView<RecursiveDirectoryIterator> {
12public:
14 -> di::Result<RecursiveDirectoryIterator> {
15 auto result = RecursiveDirectoryIterator { options };
16 auto base = DI_TRY(DirectoryIterator::create(di::move(path), options));
17 if (base != DirectoryIterator {}) {
18 result.m_stack.push(di::move(base));
19 result.m_recursion_pending = true;
20 }
21 return result;
22 }
23
25
28
31
32 auto operator*() const -> di::Expected<DirectoryEntry const&, di::GenericCode> { return **m_stack.top(); }
33
34 auto begin() -> RecursiveDirectoryIterator { return di::move(*this); }
35 auto end() const -> RecursiveDirectoryIterator { return {}; }
36
37 constexpr auto options() const -> DirectoryOptions { return m_options; }
38 constexpr auto depth() const -> i32 { return static_cast<i32>(m_stack.size()) - 1; }
39 constexpr auto recursion_pending() const -> bool { return m_recursion_pending; }
40
41 void advance_one() {
42 auto& top = *m_stack.top();
43 if (!*top) {
44 m_stack.clear();
45 return;
46 }
47 auto const& current = **top;
48
49 // If recursion is pending and the current entry is a directory,
50 // recurse by pushing to the stack.
51 if (di::exchange(m_recursion_pending, true)) {
52 auto is_directory_result = current.is_non_symlink_directory();
53 if (!is_directory_result) {
54 top.m_current = di::Unexpected(is_directory_result.error());
55 return;
56 }
57
58 // If this is really a directory, then create a new directory iterator and push.
59 if (*is_directory_result) {
60 auto new_iterator = DirectoryIterator::create(current.path_view().to_owned(), options());
61 if (!new_iterator) {
62 top.m_current = di::Unexpected(new_iterator.error());
63 return;
64 }
65
66 // If there are no entries, skip pushing.
67 if (new_iterator != DirectoryIterator {}) {
68 m_stack.push(*di::move(new_iterator));
69 return;
70 }
71 }
72 }
73
74 // Advance the current directory iterator, and pop if there is nothing left.
75 ++top;
76 if (top == DirectoryIterator {}) {
77 pop();
78 }
79 }
80
81 void pop() {
82 for (;;) {
83 m_stack.pop();
84
85 if (!m_stack.empty()) {
86 auto& top = *m_stack.top();
87 ++top;
88 if (top == DirectoryIterator {}) {
89 continue;
90 }
91 }
92 break;
93 }
94 }
95 constexpr void disable_recursion_pending() { m_recursion_pending = false; }
96
97private:
98 constexpr explicit RecursiveDirectoryIterator(DirectoryOptions options) : m_options(options) {}
99
100 constexpr friend auto operator==(RecursiveDirectoryIterator const& a, RecursiveDirectoryIterator const& b) -> bool {
101 return a.m_stack.empty() && b.m_stack.empty();
102 }
103
104 di::Stack<DirectoryIterator> m_stack;
106 bool m_recursion_pending { false };
107};
108}
Definition directory_entry.h:13
Definition directory_iterator.h:24
static auto create(di::Path path, DirectoryOptions options=DirectoryOptions::None) -> di::Expected< DirectoryIterator, di::GenericCode >
auto end() const -> RecursiveDirectoryIterator
Definition recursive_directory_iterator.h:35
constexpr void disable_recursion_pending()
Definition recursive_directory_iterator.h:95
constexpr auto recursion_pending() const -> bool
Definition recursive_directory_iterator.h:39
auto begin() -> RecursiveDirectoryIterator
Definition recursive_directory_iterator.h:34
constexpr friend auto operator==(RecursiveDirectoryIterator const &a, RecursiveDirectoryIterator const &b) -> bool
Definition recursive_directory_iterator.h:100
RecursiveDirectoryIterator(RecursiveDirectoryIterator &&)=default
auto operator=(RecursiveDirectoryIterator &&) -> RecursiveDirectoryIterator &=default
void advance_one()
Definition recursive_directory_iterator.h:41
auto operator*() const -> di::Expected< DirectoryEntry const &, di::GenericCode >
Definition recursive_directory_iterator.h:32
auto operator=(RecursiveDirectoryIterator const &) -> RecursiveDirectoryIterator &=delete
RecursiveDirectoryIterator(RecursiveDirectoryIterator const &)=delete
constexpr auto depth() const -> i32
Definition recursive_directory_iterator.h:38
static auto create(di::Path path, DirectoryOptions options=DirectoryOptions::None) -> di::Result< RecursiveDirectoryIterator >
Definition recursive_directory_iterator.h:13
constexpr auto options() const -> DirectoryOptions
Definition recursive_directory_iterator.h:37
void pop()
Definition recursive_directory_iterator.h:81
Definition error.h:7
Definition directory_entry.h:11
DirectoryOptions
Definition directory_options.h:6
@ None
Definition directory_options.h:7