aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/efsw.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdParty/efsw/efsw.hpp')
-rw-r--r--[-rwxr-xr-x]src/3rdParty/efsw/efsw.hpp456
1 files changed, 261 insertions, 195 deletions
diff --git a/src/3rdParty/efsw/efsw.hpp b/src/3rdParty/efsw/efsw.hpp
index 12af116..11a5dec 100755..100644
--- a/src/3rdParty/efsw/efsw.hpp
+++ b/src/3rdParty/efsw/efsw.hpp
@@ -1,195 +1,261 @@
1/** 1/**
2 @author Martín Lucas Golini 2 @author Martín Lucas Golini
3 3
4 Copyright (c) 2013 Martín Lucas Golini 4 Copyright (c) 2024 Martín Lucas Golini
5 5
6 Permission is hereby granted, free of charge, to any person obtaining a copy 6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal 7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights 8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is 10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions: 11 furnished to do so, subject to the following conditions:
12 12
13 The above copyright notice and this permission notice shall be included in 13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software. 14 all copies or substantial portions of the Software.
15 15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE. 22 THE SOFTWARE.
23 23
24 This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) 24 This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
25 http://code.google.com/p/simplefilewatcher/ also MIT licensed. 25 http://code.google.com/p/simplefilewatcher/ also MIT licensed.
26*/ 26*/
27 27
28#ifndef ESFW_HPP 28#ifndef ESFW_HPP
29#define ESFW_HPP 29#define ESFW_HPP
30 30
31#include <list> 31#include <string>
32#include <string> 32#include <vector>
33 33
34#if defined( _WIN32 ) 34#if defined( _WIN32 )
35#ifdef EFSW_DYNAMIC 35#ifdef EFSW_DYNAMIC
36// Windows platforms 36// Windows platforms
37#ifdef EFSW_EXPORTS 37#ifdef EFSW_EXPORTS
38// From DLL side, we must export 38// From DLL side, we must export
39#define EFSW_API __declspec( dllexport ) 39#define EFSW_API __declspec( dllexport )
40#else 40#else
41// From client application side, we must import 41// From client application side, we must import
42#define EFSW_API __declspec( dllimport ) 42#define EFSW_API __declspec( dllimport )
43#endif 43#endif
44#else 44#else
45// No specific directive needed for static build 45// No specific directive needed for static build
46#ifndef EFSW_API 46#ifndef EFSW_API
47#define EFSW_API 47#define EFSW_API
48#endif 48#endif
49#endif 49#endif
50#else 50#else
51#if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) 51#if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
52#ifndef EFSW_API 52#ifndef EFSW_API
53#define EFSW_API __attribute__( ( visibility( "default" ) ) ) 53#define EFSW_API __attribute__( ( visibility( "default" ) ) )
54#endif 54#endif
55#endif 55#endif
56 56
57// Other platforms don't need to define anything 57// Other platforms don't need to define anything
58#ifndef EFSW_API 58#ifndef EFSW_API
59#define EFSW_API 59#define EFSW_API
60#endif 60#endif
61#endif 61#endif
62 62
63namespace efsw { 63namespace efsw {
64 64
65/// Type for a watch id 65/// Type for a watch id
66typedef long WatchID; 66typedef long WatchID;
67 67
68// forward declarations 68// forward declarations
69class FileWatcherImpl; 69class FileWatcherImpl;
70class FileWatchListener; 70class FileWatchListener;
71 71class WatcherOption;
72/// Actions to listen for. Rename will send two events, one for 72
73/// the deletion of the old file, and one for the creation of the 73/// Actions to listen for. Rename will send two events, one for
74/// new file. 74/// the deletion of the old file, and one for the creation of the
75namespace Actions { 75/// new file.
76enum Action { 76namespace Actions {
77 /// Sent when a file is created or renamed 77enum Action {
78 Add = 1, 78 /// Sent when a file is created or renamed
79 /// Sent when a file is deleted or renamed 79 Add = 1,
80 Delete = 2, 80 /// Sent when a file is deleted or renamed
81 /// Sent when a file is modified 81 Delete = 2,
82 Modified = 3, 82 /// Sent when a file is modified
83 /// Sent when a file is moved 83 Modified = 3,
84 Moved = 4 84 /// Sent when a file is moved
85}; 85 Moved = 4
86} 86};
87typedef Actions::Action Action; 87}
88 88typedef Actions::Action Action;
89/// Errors log namespace 89
90namespace Errors { 90/// Errors log namespace
91 91namespace Errors {
92enum Error { 92
93 FileNotFound = -1, 93enum Error {
94 FileRepeated = -2, 94 NoError = 0,
95 FileOutOfScope = -3, 95 FileNotFound = -1,
96 FileNotReadable = -4, 96 FileRepeated = -2,
97 FileRemote = -5, /** Directory in remote file system ( create a generic FileWatcher instance to 97 FileOutOfScope = -3,
98 watch this directory ). */ 98 FileNotReadable = -4,
99 Unspecified = -6 99 /// Directory in remote file system
100}; 100 /// ( create a generic FileWatcher instance to watch this directory ).
101 101 FileRemote = -5,
102class EFSW_API Log { 102 /// File system watcher failed to watch for changes.
103 public: 103 WatcherFailed = -6,
104 /// @return The last error logged 104 Unspecified = -7
105 static std::string getLastErrorLog(); 105};
106 106
107 /// Creates an error of the type specified 107class EFSW_API Log {
108 static Error createLastError( Error err, std::string log ); 108 public:
109}; 109 /// @return The last error logged
110 110 static std::string getLastErrorLog();
111} // namespace Errors 111
112typedef Errors::Error Error; 112 /// @return The code of the last error logged
113 113 static Error getLastErrorCode();
114/// Listens to files and directories and dispatches events 114
115/// to notify the listener of files and directories changes. 115 /// Reset last error
116/// @class FileWatcher 116 static void clearLastError();
117class EFSW_API FileWatcher { 117
118 public: 118 /// Creates an error of the type specified
119 /// Default constructor, will use the default platform file watcher 119 static Error createLastError( Error err, std::string log );
120 FileWatcher(); 120};
121 121
122 /// Constructor that lets you force the use of the Generic File Watcher 122} // namespace Errors
123 explicit FileWatcher( bool useGenericFileWatcher ); 123typedef Errors::Error Error;
124 124
125 virtual ~FileWatcher(); 125/// Optional file watcher settings.
126 126namespace Options {
127 /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. 127enum Option {
128 /// For backwards compatibility. 128 /// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and
129 /// On error returns WatchID with Error type. 129 /// file system events may be dropped. For that, using a different (bigger) buffer size
130 WatchID addWatch( const std::string& directory, FileWatchListener* watcher ); 130 /// can be defined here, but note that this does not work for network drives,
131 131 /// because a buffer larger than 64K will fail the folder being watched, see
132 /// Add a directory watch 132 /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx)
133 /// On error returns WatchID with Error type. 133 WinBufferSize = 1,
134 WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); 134 /// For Windows, per default all events are captured but we might only be interested
135 135 /// in a subset; the value of the option should be set to a bitwise or'ed set of
136 /// Remove a directory watch. This is a brute force search O(nlogn). 136 /// FILE_NOTIFY_CHANGE_* flags.
137 void removeWatch( const std::string& directory ); 137 WinNotifyFilter = 2,
138 138 /// For macOS (FSEvents backend), per default all modified event types are capture but we might
139 /// Remove a directory watch. This is a map lookup O(logn). 139 /// only be interested in a subset; the value of the option should be set to a set of bitwise
140 void removeWatch( WatchID watchid ); 140 /// from:
141 141 /// kFSEventStreamEventFlagItemFinderInfoMod
142 /// Starts watching ( in other thread ) 142 /// kFSEventStreamEventFlagItemModified
143 void watch(); 143 /// kFSEventStreamEventFlagItemInodeMetaMod
144 144 /// Default configuration will set the 3 flags
145 /// @return Returns a list of the directories that are being watched 145 MacModifiedFilter = 3,
146 std::list<std::string> directories(); 146 /// macOS sometimes informs incorrect or old file states that may confuse the consumer
147 147 /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing
148 /** Allow recursive watchers to follow symbolic links to other directories 148 /// the number of events reported. This will have an small performance and memory impact as a
149 * followSymlinks is disabled by default 149 /// consequence.
150 */ 150 MacSanitizeEvents = 4,
151 void followSymlinks( bool follow ); 151 /// Linux does not support natively recursive watchers. This means that when using recursive
152 152 /// watches efsw registers new watchers for each directory. If new file are created between
153 /** @return If can follow symbolic links to directorioes */ 153 /// the time efsw takes to register the new directory those events might be missed. To avoid
154 const bool& followSymlinks() const; 154 /// missing new file notifications efsw will trigger synthetic created file events for existing
155 155 /// files in the new directroy watched. This might have the unintended consequence of sending
156 /** When enable this it will allow symlinks to watch recursively out of the pointed directory. 156 /// duplicated created events due to the system also emitting this event.
157 * follorSymlinks must be enabled to this work. 157 LinuxProduceSyntheticEvents = 5,
158 * For example, added symlink to /home/folder, and the symlink points to /, this by default is 158};
159 * not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid 159}
160 * great levels of recursion. Enabling this could lead in infinite recursion, and crash the 160typedef Options::Option Option;
161 * watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow 161
162 * this behavior. allowOutOfScopeLinks are disabled by default. 162/// Listens to files and directories and dispatches events
163 */ 163/// to notify the listener of files and directories changes.
164 void allowOutOfScopeLinks( bool allow ); 164/// @class FileWatcher
165 165class EFSW_API FileWatcher {
166 /// @return Returns if out of scope links are allowed 166 public:
167 const bool& allowOutOfScopeLinks() const; 167 /// Default constructor, will use the default platform file watcher
168 168 FileWatcher();
169 private: 169
170 /// The implementation 170 /// Constructor that lets you force the use of the Generic File Watcher
171 FileWatcherImpl* mImpl; 171 explicit FileWatcher( bool useGenericFileWatcher );
172 bool mFollowSymlinks; 172
173 bool mOutOfScopeLinks; 173 virtual ~FileWatcher();
174}; 174
175 175 /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option.
176/// Basic interface for listening for file events. 176 /// For backwards compatibility.
177/// @class FileWatchListener 177 /// On error returns WatchID with Error type.
178class FileWatchListener { 178 WatchID addWatch( const std::string& directory, FileWatchListener* watcher );
179 public: 179
180 virtual ~FileWatchListener() {} 180 /// Add a directory watch
181 181 /// On error returns WatchID with Error type.
182 /// Handles the action file action 182 WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive );
183 /// @param watchid The watch id for the directory 183
184 /// @param dir The directory 184 /// Add a directory watch, allowing customization with options
185 /// @param filename The filename that was accessed (not full path) 185 /// @param directory The folder to be watched
186 /// @param action Action that was performed 186 /// @param watcher The listener to receive events
187 /// @param oldFilename The name of the file or directory moved 187 /// @param recursive Set this to true to include subdirectories
188 virtual void handleFileAction( WatchID watchid, const std::string& dir, 188 /// @param options Allows customization of a watcher
189 const std::string& filename, Action action, 189 /// @return Returns the watch id for the directory or, on error, a WatchID with Error type.
190 std::string oldFilename = "" ) = 0; 190 WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
191}; 191 const std::vector<WatcherOption>& options );
192 192
193} // namespace efsw 193 /// Remove a directory watch. This is a brute force search O(nlogn).
194 194 void removeWatch( const std::string& directory );
195#endif 195
196 /// Remove a directory watch. This is a map lookup O(logn).
197 void removeWatch( WatchID watchid );
198
199 /// Starts watching ( in other thread )
200 void watch();
201
202 /// @return Returns a list of the directories that are being watched
203 std::vector<std::string> directories();
204
205 /** Allow recursive watchers to follow symbolic links to other directories
206 * followSymlinks is disabled by default
207 */
208 void followSymlinks( bool follow );
209
210 /** @return If can follow symbolic links to directorioes */
211 const bool& followSymlinks() const;
212
213 /** When enable this it will allow symlinks to watch recursively out of the pointed directory.
214 * follorSymlinks must be enabled to this work.
215 * For example, added symlink to /home/folder, and the symlink points to /, this by default is
216 * not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid
217 * great levels of recursion. Enabling this could lead in infinite recursion, and crash the
218 * watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow
219 * this behavior. allowOutOfScopeLinks are disabled by default.
220 */
221 void allowOutOfScopeLinks( bool allow );
222
223 /// @return Returns if out of scope links are allowed
224 const bool& allowOutOfScopeLinks() const;
225
226 private:
227 /// The implementation
228 FileWatcherImpl* mImpl;
229 bool mFollowSymlinks;
230 bool mOutOfScopeLinks;
231};
232
233/// Basic interface for listening for file events.
234/// @class FileWatchListener
235class FileWatchListener {
236 public:
237 virtual ~FileWatchListener() {}
238
239 /// Handles the action file action
240 /// @param watchid The watch id for the directory
241 /// @param dir The directory
242 /// @param filename The filename that was accessed (not full path)
243 /// @param action Action that was performed
244 /// @param oldFilename The name of the file or directory moved
245 virtual void handleFileAction( WatchID watchid, const std::string& dir,
246 const std::string& filename, Action action,
247 std::string oldFilename = "" ) = 0;
248};
249
250/// Optional, typically platform specific parameter for customization of a watcher.
251/// @class WatcherOption
252class WatcherOption {
253 public:
254 WatcherOption( Option option, int value ) : mOption( option ), mValue( value ){};
255 Option mOption;
256 int mValue;
257};
258
259} // namespace efsw
260
261#endif