aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/WatcherFSEvents.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-11-15 17:23:46 +0800
committerLi Jin <dragon-fly@qq.com>2022-11-15 17:52:09 +0800
commit94f8330613877b3582d32bd11abd83a97b4399ad (patch)
tree5359de314be1ebde17f8d1e48632a97d18f9e50f /src/3rdParty/efsw/WatcherFSEvents.cpp
parent60f8f00a022ac08701792b2897b72d8c99b50f52 (diff)
downloadyuescript-94f8330613877b3582d32bd11abd83a97b4399ad.tar.gz
yuescript-94f8330613877b3582d32bd11abd83a97b4399ad.tar.bz2
yuescript-94f8330613877b3582d32bd11abd83a97b4399ad.zip
adding -w option to Yuescript tool.
Diffstat (limited to 'src/3rdParty/efsw/WatcherFSEvents.cpp')
-rwxr-xr-xsrc/3rdParty/efsw/WatcherFSEvents.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/3rdParty/efsw/WatcherFSEvents.cpp b/src/3rdParty/efsw/WatcherFSEvents.cpp
new file mode 100755
index 0000000..6ccf527
--- /dev/null
+++ b/src/3rdParty/efsw/WatcherFSEvents.cpp
@@ -0,0 +1,216 @@
1#include <efsw/Debug.hpp>
2#include <efsw/FileSystem.hpp>
3#include <efsw/FileWatcherFSEvents.hpp>
4#include <efsw/WatcherFSEvents.hpp>
5
6#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
7
8namespace efsw {
9
10WatcherFSEvents::WatcherFSEvents() :
11 Watcher(), FWatcher( NULL ), FSStream( NULL ), WatcherGen( NULL ), initializedAsync( false ) {}
12
13WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener,
14 bool recursive, WatcherFSEvents* parent ) :
15 Watcher( id, directory, listener, recursive ),
16 FWatcher( NULL ),
17 FSStream( NULL ),
18 WatcherGen( NULL ),
19 initializedAsync( false ) {}
20
21WatcherFSEvents::~WatcherFSEvents() {
22 if ( NULL != FSStream ) {
23 if ( initializedAsync ) {
24 FSEventStreamStop( FSStream );
25 }
26
27 FSEventStreamInvalidate( FSStream );
28 FSEventStreamRelease( FSStream );
29 }
30
31 efSAFE_DELETE( WatcherGen );
32}
33
34void WatcherFSEvents::init() {
35 CFStringRef CFDirectory =
36 CFStringCreateWithCString( NULL, Directory.c_str(), kCFStringEncodingUTF8 );
37 CFArrayRef CFDirectoryArray = CFArrayCreate( NULL, (const void**)&CFDirectory, 1, NULL );
38
39 Uint32 streamFlags = kFSEventStreamCreateFlagNone;
40
41 if ( FileWatcherFSEvents::isGranular() ) {
42 streamFlags = efswFSEventStreamCreateFlagFileEvents;
43 } else {
44 WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive );
45 }
46
47 FSEventStreamContext ctx;
48 /* Initialize context */
49 ctx.version = 0;
50 ctx.info = this;
51 ctx.retain = NULL;
52 ctx.release = NULL;
53 ctx.copyDescription = NULL;
54
55 FSStream =
56 FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx,
57 CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0.25, streamFlags );
58 FWatcher.load()->mNeedInitMutex.lock();
59 FWatcher.load()->mNeedInit.push_back( this );
60 FWatcher.load()->mNeedInitMutex.unlock();
61
62 CFRelease( CFDirectoryArray );
63 CFRelease( CFDirectory );
64}
65
66void WatcherFSEvents::initAsync() {
67 FSEventStreamScheduleWithRunLoop( FSStream, FWatcher.load()->mRunLoopRef.load(),
68 kCFRunLoopDefaultMode );
69 FSEventStreamStart( FSStream );
70 initializedAsync = true;
71}
72
73void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir,
74 const std::string& filename, Action action,
75 std::string oldFilename ) {
76 Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ),
77 FileSystem::precomposeFileName( filename ), action, oldFilename );
78}
79
80void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path,
81 std::string& dirPath, std::string& filePath ) {
82 if ( flags & efswFSEventStreamEventFlagItemCreated ) {
83 if ( FileInfo::exists( path ) ) {
84 sendFileAction( ID, dirPath, filePath, Actions::Add );
85 }
86 }
87
88 if ( flags & efswFSEventsModified ) {
89 sendFileAction( ID, dirPath, filePath, Actions::Modified );
90 }
91
92 if ( flags & efswFSEventStreamEventFlagItemRemoved ) {
93 // Since i don't know the order, at least i try to keep the data consistent with the real
94 // state
95 if ( !FileInfo::exists( path ) ) {
96 sendFileAction( ID, dirPath, filePath, Actions::Delete );
97 }
98 }
99}
100
101void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) {
102 size_t esize = events.size();
103
104 for ( size_t i = 0; i < esize; i++ ) {
105 FSEvent& event = events[i];
106
107 if ( event.Flags &
108 ( kFSEventStreamEventFlagUserDropped | kFSEventStreamEventFlagKernelDropped |
109 kFSEventStreamEventFlagEventIdsWrapped | kFSEventStreamEventFlagHistoryDone |
110 kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount |
111 kFSEventStreamEventFlagRootChanged ) ) {
112 continue;
113 }
114
115 if ( !Recursive ) {
116 /** In case that is not recursive the watcher, ignore the events from subfolders */
117 if ( event.Path.find_last_of( FileSystem::getOSSlash() ) != Directory.size() - 1 ) {
118 continue;
119 }
120 }
121
122 if ( FileWatcherFSEvents::isGranular() ) {
123 std::string dirPath( FileSystem::pathRemoveFileName( event.Path ) );
124 std::string filePath( FileSystem::fileNameFromPath( event.Path ) );
125
126 if ( event.Flags &
127 ( efswFSEventStreamEventFlagItemCreated | efswFSEventStreamEventFlagItemRemoved |
128 efswFSEventStreamEventFlagItemRenamed ) ) {
129 if ( dirPath != Directory ) {
130 DirsChanged.insert( dirPath );
131 }
132 }
133
134 // This is a mess. But it's FSEvents faults, because shrinks events from the same file
135 // in one single event ( so there's no order for them ) For example a file could have
136 // been added modified and erased, but i can't know if first was erased and then added
137 // and modified, or added, then modified and then erased. I don't know what they were
138 // thinking by doing this...
139 efDEBUG( "Event in: %s - flags: %ld\n", event.Path.c_str(), event.Flags );
140
141 if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) {
142 if ( ( i + 1 < esize ) &&
143 ( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) &&
144 ( events[i + 1].Id == event.Id + 1 ) ) {
145 FSEvent& nEvent = events[i + 1];
146 std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) );
147 std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) );
148
149 if ( event.Path != nEvent.Path ) {
150 if ( dirPath == newDir ) {
151 if ( !FileInfo::exists( event.Path ) ) {
152 sendFileAction( ID, dirPath, newFilepath, Actions::Moved,
153 filePath );
154 } else {
155 sendFileAction( ID, dirPath, filePath, Actions::Moved,
156 newFilepath );
157 }
158 } else {
159 sendFileAction( ID, dirPath, filePath, Actions::Delete );
160 sendFileAction( ID, newDir, newFilepath, Actions::Add );
161
162 if ( nEvent.Flags & efswFSEventsModified ) {
163 sendFileAction( ID, newDir, newFilepath, Actions::Modified );
164 }
165 }
166 } else {
167 handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath );
168 }
169
170 if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated |
171 efswFSEventStreamEventFlagItemRemoved |
172 efswFSEventStreamEventFlagItemRenamed ) ) {
173 if ( newDir != Directory ) {
174 DirsChanged.insert( newDir );
175 }
176 }
177
178 // Skip the renamed file
179 i++;
180 } else if ( FileInfo::exists( event.Path ) ) {
181 sendFileAction( ID, dirPath, filePath, Actions::Add );
182
183 if ( event.Flags & efswFSEventsModified ) {
184 sendFileAction( ID, dirPath, filePath, Actions::Modified );
185 }
186 } else {
187 sendFileAction( ID, dirPath, filePath, Actions::Delete );
188 }
189 } else {
190 handleAddModDel( event.Flags, event.Path, dirPath, filePath );
191 }
192 } else {
193 efDEBUG( "Directory: %s changed\n", event.Path.c_str() );
194 DirsChanged.insert( event.Path );
195 }
196 }
197}
198
199void WatcherFSEvents::process() {
200 std::set<std::string>::iterator it = DirsChanged.begin();
201
202 for ( ; it != DirsChanged.end(); it++ ) {
203 if ( !FileWatcherFSEvents::isGranular() ) {
204 WatcherGen->watchDir( ( *it ) );
205 } else {
206 sendFileAction( ID, FileSystem::pathRemoveFileName( ( *it ) ),
207 FileSystem::fileNameFromPath( ( *it ) ), Actions::Modified );
208 }
209 }
210
211 DirsChanged.clear();
212}
213
214} // namespace efsw
215
216#endif