comparison src/core/filesystem.cc @ 382:0265e125f680

filesystem: implement filesystem watcher I also ported the library code to use it as well. Once we implement proper directory watching on Windows (and maybe others) this will be fairly useful :)
author Paper <paper@tflc.us>
date Thu, 06 Nov 2025 03:16:55 -0500
parents 5912dafc6e28
children
comparison
equal deleted inserted replaced
381:5beae59cf042 382:0265e125f680
54 std::filesystem::path GetAnimePostersPath() 54 std::filesystem::path GetAnimePostersPath()
55 { 55 {
56 return GetDotPath() / "anime" / "posters"; 56 return GetDotPath() / "anime" / "posters";
57 } 57 }
58 58
59 /* ------------------------------------------------------------------------ */
60 /* Ehhhhh */
61
62 class Watcher : public IWatcher {
63 public:
64 Watcher(void *opaque, const std::filesystem::path &path, EventHandler handler)
65 : path_(path)
66 , handler_(handler)
67 , opaque_(opaque)
68 {
69 }
70
71 virtual ~Watcher() override
72 {
73 }
74
75 protected:
76 std::filesystem::path path_;
77 EventHandler handler_;
78 void *opaque_;
79 };
80
81 /* ------------------------------------------------------------------------ */
82 /* Non-recursive filesystem watcher.
83 * This is the portable version for non-Windows */
84
85 template<typename T>
86 class StdFilesystemWatcher : public Watcher {
87 public:
88 StdFilesystemWatcher(void *opaque, const std::filesystem::path &path, EventHandler handler)
89 : Watcher(opaque, path, handler)
90 {
91 }
92
93 virtual ~StdFilesystemWatcher() override
94 {
95 }
96
97 virtual void Process() override
98 {
99 /* Untoggle all paths. This allows us to only ever
100 * iterate over the directory ONCE. */
101 UntoggleAllPaths();
102
103 for (const auto &item : T(path_)) {
104 std::filesystem::path p = item.path();
105
106 if (FindAndTogglePath(p))
107 continue;
108
109 /* Hand the path off to the listener */
110 handler_(opaque_, p, Event::Created);
111 paths_.push_back({true, p});
112 }
113
114 DeleteUntoggledPaths();
115 }
116
117 protected:
118 bool FindAndTogglePath(const std::filesystem::path &p) {
119 for (auto &pp : paths_) {
120 if (pp.path == p) {
121 pp.found = true;
122 return true;
123 }
124 }
125
126 return false;
127 }
128
129 void UntoggleAllPaths()
130 {
131 for (auto &pp : paths_)
132 pp.found = false;
133 }
134
135 void DeleteUntoggledPaths()
136 {
137 for (const auto &path : paths_)
138 if (!path.found)
139 handler_(opaque_, path.path, Event::Deleted);
140
141 auto it = paths_.begin();
142
143 while (it != paths_.end()) {
144 if (!it->found) {
145 it = paths_.erase(it);
146 } else {
147 it++;
148 }
149 }
150 }
151
152 struct PathStatus {
153 bool found;
154 std::filesystem::path path;
155 };
156
157 /* TODO this is probably DAMN slow */
158 std::vector<PathStatus> paths_;
159 };
160
161 IWatcher *GetRecursiveFilesystemWatcher(void *opaque,
162 const std::filesystem::path &path, IWatcher::EventHandler handler)
163 {
164 /* .... :) */
165 return new StdFilesystemWatcher<std::filesystem::recursive_directory_iterator>(opaque, path, handler);
166 }
167
168 IWatcher *GetFilesystemWatcher(void *opaque, const std::filesystem::path &path, IWatcher::EventHandler handler)
169 {
170 return new StdFilesystemWatcher<std::filesystem::directory_iterator>(opaque, path, handler);
171 }
172
59 } // namespace Filesystem 173 } // namespace Filesystem