Compare commits

..

3 Commits

17 changed files with 3837 additions and 3284 deletions

18
.clang-format Normal file
View File

@ -0,0 +1,18 @@
---
AlignEscapedNewlines: Left
AllowAllConstructorInitializersOnNextLine: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortFunctionsOnASingleLine: Inline
BreakConstructorInitializers: AfterColon
ColumnLimit: '100'
CompactNamespaces: 'true'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
ContinuationIndentWidth: '4'
IndentCaseLabels: 'true'
IndentWidth: '4'
PointerAlignment: Left
SpacesInParentheses: 'true'
TabWidth: '4'
UseTab: Always
...

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
bin/
build/
obj/
make/
lib/
CMakeFiles/
/cmake
/CMakeCache.txt
/cmake_install.cmake
/Makefile
*.DS_Store
.qtc_clangd
.cmake
.vscode/
*.so
*.a
*.dylib
*.lib
/.cache
/efsw-test
/efsw-test-stdc

View File

@ -1,57 +0,0 @@
# joomer-efsw-file-monitoring
Watch folder for images and flip them
# Demonstrates
- file monitoring
# Usage
```
joomer-ftxui-file-monitoring
- drag and drop files into the path folder
```
[todo]
# Build
```
learndir/
└── joomer-ftxui-file-monitoring/
```
- Download and Install Premake
## Ubuntu Linux (kasm-ubuntu)
```
mkdir learndir
cd learndir
git clone https://git.indoodle.com/jason/joomer-efsw-file-monitoring.git
cd joomer-ftxui-file-browser
make all
bin/Linux/release/joomer-ftxui-file-monitoring
```
## Windows (win10 enterprise)
- Download Visual Studio Community Edition 2022
- Run VisualStudioSetup.exe
- Workload = [x] Desktop developemnt with C++
- Individial components = [x] Git For Windows
Run **x64 Native Tools Command Prompt for VS 2022**
```
mkdir learndir
cd learndir
git clone https://git.indoodle.com/jason/joomer-ftxui-file-monitoring.git
cd joomer-ftxui-file-monitoring
msbuild joomer-ftxui-file-monitoring.vcxproj /t:Build /p:Configuration=Debug /p:Platform=x64
bin\Debug\joomer-ftxui-file-monitoring.exe
```
For a prototype app we can just dump the stb headers right into the helloworld dir for simplicity
```
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image.h
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h
make all -j4
```

View File

@ -1,267 +1,267 @@
/** /**
@author Martín Lucas Golini @author Martín Lucas Golini
Copyright (c) 2024 Martín Lucas Golini Copyright (c) 2024 Martín Lucas Golini
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
http://code.google.com/p/simplefilewatcher/ also MIT licensed. http://code.google.com/p/simplefilewatcher/ also MIT licensed.
*/ */
#ifndef ESFW_HPP #ifndef ESFW_HPP
#define ESFW_HPP #define ESFW_HPP
#include <string> #include <string>
#include <vector> #include <vector>
#if defined( _WIN32 ) #if defined( _WIN32 )
#ifdef EFSW_DYNAMIC #ifdef EFSW_DYNAMIC
// Windows platforms // Windows platforms
#ifdef EFSW_EXPORTS #ifdef EFSW_EXPORTS
// From DLL side, we must export // From DLL side, we must export
#define EFSW_API __declspec( dllexport ) #define EFSW_API __declspec( dllexport )
#else #else
// From client application side, we must import // From client application side, we must import
#define EFSW_API __declspec( dllimport ) #define EFSW_API __declspec( dllimport )
#endif #endif
#else #else
// No specific directive needed for static build // No specific directive needed for static build
#ifndef EFSW_API #ifndef EFSW_API
#define EFSW_API #define EFSW_API
#endif #endif
#endif #endif
#else #else
#if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
#ifndef EFSW_API #ifndef EFSW_API
#define EFSW_API __attribute__( ( visibility( "default" ) ) ) #define EFSW_API __attribute__( ( visibility( "default" ) ) )
#endif #endif
#endif #endif
// Other platforms don't need to define anything // Other platforms don't need to define anything
#ifndef EFSW_API #ifndef EFSW_API
#define EFSW_API #define EFSW_API
#endif #endif
#endif #endif
namespace efsw { namespace efsw {
/// Type for a watch id /// Type for a watch id
typedef long WatchID; typedef long WatchID;
// forward declarations // forward declarations
class FileWatcherImpl; class FileWatcherImpl;
class FileWatchListener; class FileWatchListener;
class WatcherOption; class WatcherOption;
/// Actions to listen for. Rename will send two events, one for /// Actions to listen for. Rename will send two events, one for
/// the deletion of the old file, and one for the creation of the /// the deletion of the old file, and one for the creation of the
/// new file. /// new file.
namespace Actions { namespace Actions {
enum Action { enum Action {
/// Sent when a file is created or renamed /// Sent when a file is created or renamed
Add = 1, Add = 1,
/// Sent when a file is deleted or renamed /// Sent when a file is deleted or renamed
Delete = 2, Delete = 2,
/// Sent when a file is modified /// Sent when a file is modified
Modified = 3, Modified = 3,
/// Sent when a file is moved /// Sent when a file is moved
Moved = 4 Moved = 4
}; };
} }
typedef Actions::Action Action; typedef Actions::Action Action;
/// Errors log namespace /// Errors log namespace
namespace Errors { namespace Errors {
enum Error { enum Error {
NoError = 0, NoError = 0,
FileNotFound = -1, FileNotFound = -1,
FileRepeated = -2, FileRepeated = -2,
FileOutOfScope = -3, FileOutOfScope = -3,
FileNotReadable = -4, FileNotReadable = -4,
/// Directory in remote file system /// Directory in remote file system
/// ( create a generic FileWatcher instance to watch this directory ). /// ( create a generic FileWatcher instance to watch this directory ).
FileRemote = -5, FileRemote = -5,
/// File system watcher failed to watch for changes. /// File system watcher failed to watch for changes.
WatcherFailed = -6, WatcherFailed = -6,
Unspecified = -7 Unspecified = -7
}; };
class EFSW_API Log { class EFSW_API Log {
public: public:
/// @return The last error logged /// @return The last error logged
static std::string getLastErrorLog(); static std::string getLastErrorLog();
/// @return The code of the last error logged /// @return The code of the last error logged
static Error getLastErrorCode(); static Error getLastErrorCode();
/// Reset last error /// Reset last error
static void clearLastError(); static void clearLastError();
/// Creates an error of the type specified /// Creates an error of the type specified
static Error createLastError( Error err, std::string log ); static Error createLastError( Error err, std::string log );
}; };
} // namespace Errors } // namespace Errors
typedef Errors::Error Error; typedef Errors::Error Error;
/// Optional file watcher settings. /// Optional file watcher settings.
namespace Options { namespace Options {
enum Option { enum Option {
/// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and /// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and
/// file system events may be dropped. For that, using a different (bigger) buffer size /// file system events may be dropped. For that, using a different (bigger) buffer size
/// can be defined here, but note that this does not work for network drives, /// can be defined here, but note that this does not work for network drives,
/// because a buffer larger than 64K will fail the folder being watched, see /// because a buffer larger than 64K will fail the folder being watched, see
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx)
WinBufferSize = 1, WinBufferSize = 1,
/// For Windows, per default all events are captured but we might only be interested /// For Windows, per default all events are captured but we might only be interested
/// in a subset; the value of the option should be set to a bitwise or'ed set of /// in a subset; the value of the option should be set to a bitwise or'ed set of
/// FILE_NOTIFY_CHANGE_* flags. /// FILE_NOTIFY_CHANGE_* flags.
WinNotifyFilter = 2, WinNotifyFilter = 2,
/// For macOS (FSEvents backend), per default all modified event types are capture but we might /// For macOS (FSEvents backend), per default all modified event types are capture but we might
/// only be interested in a subset; the value of the option should be set to a set of bitwise /// only be interested in a subset; the value of the option should be set to a set of bitwise
/// from: /// from:
/// kFSEventStreamEventFlagItemFinderInfoMod /// kFSEventStreamEventFlagItemFinderInfoMod
/// kFSEventStreamEventFlagItemModified /// kFSEventStreamEventFlagItemModified
/// kFSEventStreamEventFlagItemInodeMetaMod /// kFSEventStreamEventFlagItemInodeMetaMod
/// Default configuration will set the 3 flags /// Default configuration will set the 3 flags
MacModifiedFilter = 3, MacModifiedFilter = 3,
/// macOS sometimes informs incorrect or old file states that may confuse the consumer /// macOS sometimes informs incorrect or old file states that may confuse the consumer
/// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing
/// the number of events reported. This will have an small performance and memory impact as a /// the number of events reported. This will have an small performance and memory impact as a
/// consequence. /// consequence.
MacSanitizeEvents = 4, MacSanitizeEvents = 4,
/// Linux does not support natively recursive watchers. This means that when using recursive /// Linux does not support natively recursive watchers. This means that when using recursive
/// watches efsw registers new watchers for each directory. If new file are created between /// watches efsw registers new watchers for each directory. If new file are created between
/// the time efsw takes to register the new directory those events might be missed. To avoid /// the time efsw takes to register the new directory those events might be missed. To avoid
/// missing new file notifications efsw will trigger synthetic created file events for existing /// missing new file notifications efsw will trigger synthetic created file events for existing
/// files in the new directroy watched. This might have the unintended consequence of sending /// files in the new directroy watched. This might have the unintended consequence of sending
/// duplicated created events due to the system also emitting this event. /// duplicated created events due to the system also emitting this event.
LinuxProduceSyntheticEvents = 5, LinuxProduceSyntheticEvents = 5,
}; };
} }
typedef Options::Option Option; typedef Options::Option Option;
/// Listens to files and directories and dispatches events /// Listens to files and directories and dispatches events
/// to notify the listener of files and directories changes. /// to notify the listener of files and directories changes.
/// @class FileWatcher /// @class FileWatcher
class EFSW_API FileWatcher { class EFSW_API FileWatcher {
public: public:
/// Default constructor, will use the default platform file watcher /// Default constructor, will use the default platform file watcher
FileWatcher(); FileWatcher();
/// Constructor that lets you force the use of the Generic File Watcher /// Constructor that lets you force the use of the Generic File Watcher
explicit FileWatcher( bool useGenericFileWatcher ); explicit FileWatcher( bool useGenericFileWatcher );
virtual ~FileWatcher(); virtual ~FileWatcher();
/// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option.
/// For backwards compatibility. /// For backwards compatibility.
/// On error returns WatchID with Error type. /// On error returns WatchID with Error type.
WatchID addWatch( const std::string& directory, FileWatchListener* watcher ); WatchID addWatch( const std::string& directory, FileWatchListener* watcher );
/// Add a directory watch /// Add a directory watch
/// On error returns WatchID with Error type. /// On error returns WatchID with Error type.
WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive );
/// Add a directory watch, allowing customization with options /// Add a directory watch, allowing customization with options
/// @param directory The folder to be watched /// @param directory The folder to be watched
/// @param watcher The listener to receive events /// @param watcher The listener to receive events
/// @param recursive Set this to true to include subdirectories /// @param recursive Set this to true to include subdirectories
/// @param options Allows customization of a watcher /// @param options Allows customization of a watcher
/// @return Returns the watch id for the directory or, on error, a WatchID with Error type. /// @return Returns the watch id for the directory or, on error, a WatchID with Error type.
WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
const std::vector<WatcherOption>& options ); const std::vector<WatcherOption>& options );
/// Remove a directory watch. This is a brute force search O(nlogn). /// Remove a directory watch. This is a brute force search O(nlogn).
void removeWatch( const std::string& directory ); void removeWatch( const std::string& directory );
/// Remove a directory watch. This is a map lookup O(logn). /// Remove a directory watch. This is a map lookup O(logn).
void removeWatch( WatchID watchid ); void removeWatch( WatchID watchid );
/// Starts watching ( in other thread ) /// Starts watching ( in other thread )
void watch(); void watch();
/// @return Returns a list of the directories that are being watched /// @return Returns a list of the directories that are being watched
std::vector<std::string> directories(); std::vector<std::string> directories();
/** Allow recursive watchers to follow symbolic links to other directories /** Allow recursive watchers to follow symbolic links to other directories
* followSymlinks is disabled by default * followSymlinks is disabled by default
*/ */
void followSymlinks( bool follow ); void followSymlinks( bool follow );
/** @return If can follow symbolic links to directorioes */ /** @return If can follow symbolic links to directorioes */
const bool& followSymlinks() const; const bool& followSymlinks() const;
/** When enable this it will allow symlinks to watch recursively out of the pointed directory. /** When enable this it will allow symlinks to watch recursively out of the pointed directory.
* follorSymlinks must be enabled to this work. * follorSymlinks must be enabled to this work.
* For example, added symlink to /home/folder, and the symlink points to /, this by default is * For example, added symlink to /home/folder, and the symlink points to /, this by default is
* not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid * not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid
* great levels of recursion. Enabling this could lead in infinite recursion, and crash the * great levels of recursion. Enabling this could lead in infinite recursion, and crash the
* watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow * watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow
* this behavior. allowOutOfScopeLinks are disabled by default. * this behavior. allowOutOfScopeLinks are disabled by default.
*/ */
void allowOutOfScopeLinks( bool allow ); void allowOutOfScopeLinks( bool allow );
/// @return Returns if out of scope links are allowed /// @return Returns if out of scope links are allowed
const bool& allowOutOfScopeLinks() const; const bool& allowOutOfScopeLinks() const;
private: private:
/// The implementation /// The implementation
FileWatcherImpl* mImpl; FileWatcherImpl* mImpl;
bool mFollowSymlinks; bool mFollowSymlinks;
bool mOutOfScopeLinks; bool mOutOfScopeLinks;
}; };
/// Basic interface for listening for file events. /// Basic interface for listening for file events.
/// @class FileWatchListener /// @class FileWatchListener
class FileWatchListener { class FileWatchListener {
public: public:
virtual ~FileWatchListener() {} virtual ~FileWatchListener() {}
/// Handles the action file action /// Handles the action file action
/// @param watchid The watch id for the directory /// @param watchid The watch id for the directory
/// @param dir The directory /// @param dir The directory
/// @param filename The filename that was accessed (not full path) /// @param filename The filename that was accessed (not full path)
/// @param action Action that was performed /// @param action Action that was performed
/// @param oldFilename The name of the file or directory moved /// @param oldFilename The name of the file or directory moved
virtual void handleFileAction( WatchID watchid, const std::string& dir, virtual void handleFileAction( WatchID watchid, const std::string& dir,
const std::string& filename, Action action, const std::string& filename, Action action,
std::string oldFilename = "" ) = 0; std::string oldFilename = "" ) = 0;
/// Handles that have missed file actions /// Handles that have missed file actions
/// @param watchid The watch id for the directory /// @param watchid The watch id for the directory
/// @param dir The directory /// @param dir The directory
virtual void handleMissedFileActions( WatchID /*watchid*/, virtual void handleMissedFileActions( WatchID /*watchid*/,
const std::string& /*dir*/ ) {} const std::string& /*dir*/ ) {}
}; };
/// Optional, typically platform specific parameter for customization of a watcher. /// Optional, typically platform specific parameter for customization of a watcher.
/// @class WatcherOption /// @class WatcherOption
class WatcherOption { class WatcherOption {
public: public:
WatcherOption( Option option, int value ) : mOption( option ), mValue( value ){}; WatcherOption( Option option, int value ) : mOption( option ), mValue( value ){};
Option mOption; Option mOption;
int mValue; int mValue;
}; };
} // namespace efsw } // namespace efsw
#endif #endif

View File

@ -1,261 +1,261 @@
newoption { trigger = "verbose", description = "Build efsw with verbose mode." } newoption { trigger = "verbose", description = "Build efsw with verbose mode." }
newoption { trigger = "strip-symbols", description = "Strip debugging symbols in other file ( only for relwithdbginfo configuration )." } newoption { trigger = "strip-symbols", description = "Strip debugging symbols in other file ( only for relwithdbginfo configuration )." }
newoption { trigger = "thread-sanitizer", description ="Compile with ThreadSanitizer." } newoption { trigger = "thread-sanitizer", description ="Compile with ThreadSanitizer." }
efsw_major_version = "1" efsw_major_version = "1"
efsw_minor_version = "5" efsw_minor_version = "5"
efsw_patch_version = "0" efsw_patch_version = "0"
efsw_version = efsw_major_version .. "." .. efsw_minor_version .. "." .. efsw_patch_version efsw_version = efsw_major_version .. "." .. efsw_minor_version .. "." .. efsw_patch_version
function get_include_paths() function get_include_paths()
local function _insert_include_paths( file ) local function _insert_include_paths( file )
local function _trim(s) local function _trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1")) return (s:gsub("^%s*(.-)%s*$", "%1"))
end end
local paths = { } local paths = { }
local lines = file:read('*all') local lines = file:read('*all')
for line in string.gmatch(lines, '([^\n]+)') for line in string.gmatch(lines, '([^\n]+)')
do do
table.insert( paths, _trim( line ) ) table.insert( paths, _trim( line ) )
end end
file:close() file:close()
return paths return paths
end end
local file = io.popen( "echo | gcc -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/'", 'r' ) local file = io.popen( "echo | gcc -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/'", 'r' )
local include_paths = _insert_include_paths( file ) local include_paths = _insert_include_paths( file )
if next(include_paths) == nil then if next(include_paths) == nil then
file = io.popen( "echo | clang++ -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/' | grep -v 'nonexistent'", 'r' ) file = io.popen( "echo | clang++ -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/' | grep -v 'nonexistent'", 'r' )
include_paths = _insert_include_paths( file ) include_paths = _insert_include_paths( file )
if next(include_paths) == nil then if next(include_paths) == nil then
table.insert( include_paths, "/usr/include" ) table.insert( include_paths, "/usr/include" )
table.insert( include_paths, "/usr/local/include" ) table.insert( include_paths, "/usr/local/include" )
end end
end end
return include_paths return include_paths
end end
function inotify_header_exists() function inotify_header_exists()
local efsw_include_paths = get_include_paths() local efsw_include_paths = get_include_paths()
for _,v in pairs( efsw_include_paths ) for _,v in pairs( efsw_include_paths )
do do
local cur_path = v .. "/sys/inotify.h" local cur_path = v .. "/sys/inotify.h"
if os.isfile( cur_path ) then if os.isfile( cur_path ) then
return true return true
end end
end end
return false return false
end end
function string.starts(String,Start) function string.starts(String,Start)
if ( _ACTION ) then if ( _ACTION ) then
return string.sub(String,1,string.len(Start))==Start return string.sub(String,1,string.len(Start))==Start
end end
return false return false
end end
function is_vs() function is_vs()
return ( string.starts(_ACTION,"vs") ) return ( string.starts(_ACTION,"vs") )
end end
function conf_warnings() function conf_warnings()
if not is_vs() then if not is_vs() then
buildoptions{ "-Wall -Wno-long-long" } buildoptions{ "-Wall -Wno-long-long" }
if not os.is("windows") then if not os.is("windows") then
buildoptions{ "-fPIC" } buildoptions{ "-fPIC" }
end end
else else
defines { "_SCL_SECURE_NO_WARNINGS" } defines { "_SCL_SECURE_NO_WARNINGS" }
end end
if _OPTIONS["thread-sanitizer"] then if _OPTIONS["thread-sanitizer"] then
buildoptions { "-fsanitize=thread" } buildoptions { "-fsanitize=thread" }
linkoptions { "-fsanitize=thread" } linkoptions { "-fsanitize=thread" }
if not os.is("macosx") then if not os.is("macosx") then
links { "tsan" } links { "tsan" }
end end
end end
end end
function conf_links() function conf_links()
if not os.is("windows") and not os.is("haiku") then if not os.is("windows") and not os.is("haiku") then
links { "pthread" } links { "pthread" }
end end
if os.is("macosx") then if os.is("macosx") then
links { "CoreFoundation.framework", "CoreServices.framework" } links { "CoreFoundation.framework", "CoreServices.framework" }
end end
end end
function conf_excludes() function conf_excludes()
if os.is("windows") then if os.is("windows") then
excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherInotify.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherInotify.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("linux") then elseif os.is("linux") then
excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
elseif os.is("macosx") then elseif os.is("macosx") then
excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp" } excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp" }
elseif os.is("freebsd") then elseif os.is("freebsd") then
excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
end end
if os.is("linux") and not inotify_header_exists() then if os.is("linux") and not inotify_header_exists() then
defines { "EFSW_INOTIFY_NOSYS" } defines { "EFSW_INOTIFY_NOSYS" }
end end
end end
solution "efsw" solution "efsw"
location("./make/" .. os.get() .. "/") location("./make/" .. os.get() .. "/")
targetdir("./bin") targetdir("./bin")
configurations { "debug", "release", "relwithdbginfo" } configurations { "debug", "release", "relwithdbginfo" }
if os.is("windows") then if os.is("windows") then
osfiles = "src/efsw/platform/win/*.cpp" osfiles = "src/efsw/platform/win/*.cpp"
else else
osfiles = "src/efsw/platform/posix/*.cpp" osfiles = "src/efsw/platform/posix/*.cpp"
end end
-- Activates verbose mode -- Activates verbose mode
if _OPTIONS["verbose"] then if _OPTIONS["verbose"] then
defines { "EFSW_VERBOSE" } defines { "EFSW_VERBOSE" }
end end
if not is_vs() then if not is_vs() then
buildoptions { "-std=c++11" } buildoptions { "-std=c++11" }
end end
if os.is("macosx") then if os.is("macosx") then
-- Premake 4.4 needed for this -- Premake 4.4 needed for this
if not string.match(_PREMAKE_VERSION, "^4.[123]") then if not string.match(_PREMAKE_VERSION, "^4.[123]") then
local ver = os.getversion(); local ver = os.getversion();
if not ( ver.majorversion >= 10 and ver.minorversion >= 5 ) then if not ( ver.majorversion >= 10 and ver.minorversion >= 5 ) then
defines { "EFSW_FSEVENTS_NOT_SUPPORTED" } defines { "EFSW_FSEVENTS_NOT_SUPPORTED" }
end end
end end
end end
objdir("obj/" .. os.get() .. "/") objdir("obj/" .. os.get() .. "/")
project "efsw-static-lib" project "efsw-static-lib"
kind "StaticLib" kind "StaticLib"
language "C++" language "C++"
targetdir("./lib") targetdir("./lib")
includedirs { "include", "src" } includedirs { "include", "src" }
files { "src/efsw/*.cpp", osfiles } files { "src/efsw/*.cpp", osfiles }
conf_excludes() conf_excludes()
configuration "debug" configuration "debug"
defines { "DEBUG" } defines { "DEBUG" }
flags { "Symbols" } flags { "Symbols" }
targetname "efsw-static-debug" targetname "efsw-static-debug"
conf_warnings() conf_warnings()
configuration "release" configuration "release"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize" } flags { "Optimize" }
targetname "efsw-static-release" targetname "efsw-static-release"
conf_warnings() conf_warnings()
configuration "relwithdbginfo" configuration "relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize", "Symbols" } flags { "Optimize", "Symbols" }
targetname "efsw-static-reldbginfo" targetname "efsw-static-reldbginfo"
conf_warnings() conf_warnings()
project "efsw-test" project "efsw-test"
kind "ConsoleApp" kind "ConsoleApp"
language "C++" language "C++"
links { "efsw-static-lib" } links { "efsw-static-lib" }
files { "src/test/*.cpp" } files { "src/test/*.cpp" }
includedirs { "include", "src" } includedirs { "include", "src" }
conf_links() conf_links()
configuration "debug" configuration "debug"
defines { "DEBUG" } defines { "DEBUG" }
flags { "Symbols" } flags { "Symbols" }
targetname "efsw-test-debug" targetname "efsw-test-debug"
conf_warnings() conf_warnings()
configuration "release" configuration "release"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize" } flags { "Optimize" }
targetname "efsw-test-release" targetname "efsw-test-release"
conf_warnings() conf_warnings()
configuration "relwithdbginfo" configuration "relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize", "Symbols" } flags { "Optimize", "Symbols" }
targetname "efsw-test-reldbginfo" targetname "efsw-test-reldbginfo"
conf_warnings() conf_warnings()
project "efsw-test-stdc" project "efsw-test-stdc"
kind "ConsoleApp" kind "ConsoleApp"
language "C" language "C"
links { "efsw-shared-lib" } links { "efsw-shared-lib" }
files { "src/test/*.c" } files { "src/test/*.c" }
includedirs { "include", "src" } includedirs { "include", "src" }
conf_links() conf_links()
configuration "debug" configuration "debug"
defines { "DEBUG" } defines { "DEBUG" }
flags { "Symbols" } flags { "Symbols" }
targetname "efsw-test-stdc-debug" targetname "efsw-test-stdc-debug"
conf_warnings() conf_warnings()
configuration "release" configuration "release"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize" } flags { "Optimize" }
targetname "efsw-test-stdc-release" targetname "efsw-test-stdc-release"
conf_warnings() conf_warnings()
configuration "relwithdbginfo" configuration "relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize", "Symbols" } flags { "Optimize", "Symbols" }
targetname "efsw-test-stdc-reldbginfo" targetname "efsw-test-stdc-reldbginfo"
conf_warnings() conf_warnings()
project "efsw-shared-lib" project "efsw-shared-lib"
kind "SharedLib" kind "SharedLib"
language "C++" language "C++"
targetdir("./lib") targetdir("./lib")
includedirs { "include", "src" } includedirs { "include", "src" }
files { "src/efsw/*.cpp", osfiles } files { "src/efsw/*.cpp", osfiles }
defines { "EFSW_DYNAMIC", "EFSW_EXPORTS" } defines { "EFSW_DYNAMIC", "EFSW_EXPORTS" }
conf_excludes() conf_excludes()
conf_links() conf_links()
configuration "debug" configuration "debug"
defines { "DEBUG" } defines { "DEBUG" }
flags { "Symbols" } flags { "Symbols" }
targetname "efsw-debug" targetname "efsw-debug"
conf_warnings() conf_warnings()
configuration "release" configuration "release"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize" } flags { "Optimize" }
targetname "efsw" targetname "efsw"
conf_warnings() conf_warnings()
configuration "relwithdbginfo" configuration "relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
flags { "Optimize", "Symbols" } flags { "Optimize", "Symbols" }
targetname "efsw" targetname "efsw"
conf_warnings() conf_warnings()
if os.is("linux") or os.is("bsd") or os.is("haiku") then if os.is("linux") or os.is("bsd") or os.is("haiku") then
targetextension ( ".so." .. efsw_version ) targetextension ( ".so." .. efsw_version )
postbuildcommands { "sh ../../project/build.reldbginfo.sh " .. efsw_major_version .. " " .. efsw_minor_version .. " " .. efsw_patch_version .. " " .. iif( _OPTIONS["strip-symbols"], "strip-symbols", "" ) } postbuildcommands { "sh ../../project/build.reldbginfo.sh " .. efsw_major_version .. " " .. efsw_minor_version .. " " .. efsw_patch_version .. " " .. iif( _OPTIONS["strip-symbols"], "strip-symbols", "" ) }
end end

View File

@ -1,273 +1,273 @@
newoption { trigger = "verbose", description = "Build efsw with verbose mode." } newoption { trigger = "verbose", description = "Build efsw with verbose mode." }
newoption { trigger = "strip-symbols", description = "Strip debugging symbols in other file ( only for relwithdbginfo configuration )." } newoption { trigger = "strip-symbols", description = "Strip debugging symbols in other file ( only for relwithdbginfo configuration )." }
newoption { trigger = "thread-sanitizer", description ="Compile with ThreadSanitizer" } newoption { trigger = "thread-sanitizer", description ="Compile with ThreadSanitizer" }
efsw_major_version = "1" efsw_major_version = "1"
efsw_minor_version = "5" efsw_minor_version = "5"
efsw_patch_version = "0" efsw_patch_version = "0"
efsw_version = efsw_major_version .. "." .. efsw_minor_version .. "." .. efsw_patch_version efsw_version = efsw_major_version .. "." .. efsw_minor_version .. "." .. efsw_patch_version
function get_include_paths() function get_include_paths()
local function _insert_include_paths( file ) local function _insert_include_paths( file )
local function _trim(s) local function _trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1")) return (s:gsub("^%s*(.-)%s*$", "%1"))
end end
local paths = { } local paths = { }
local lines = file:read('*all') local lines = file:read('*all')
for line in string.gmatch(lines, '([^\n]+)') for line in string.gmatch(lines, '([^\n]+)')
do do
table.insert( paths, _trim( line ) ) table.insert( paths, _trim( line ) )
end end
file:close() file:close()
return paths return paths
end end
local file = io.popen( "echo | gcc -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/'", 'r' ) local file = io.popen( "echo | gcc -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/'", 'r' )
local include_paths = _insert_include_paths( file ) local include_paths = _insert_include_paths( file )
if next(include_paths) == nil then if next(include_paths) == nil then
file = io.popen( "echo | clang++ -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/' | grep -v 'nonexistent'", 'r' ) file = io.popen( "echo | clang++ -Wp,-v -x c++ - -fsyntax-only 2>&1 | grep -v '#' | grep '/' | grep -v 'nonexistent'", 'r' )
include_paths = _insert_include_paths( file ) include_paths = _insert_include_paths( file )
if next(include_paths) == nil then if next(include_paths) == nil then
table.insert( include_paths, "/usr/include" ) table.insert( include_paths, "/usr/include" )
table.insert( include_paths, "/usr/local/include" ) table.insert( include_paths, "/usr/local/include" )
end end
end end
return include_paths return include_paths
end end
function inotify_header_exists() function inotify_header_exists()
local efsw_include_paths = get_include_paths() local efsw_include_paths = get_include_paths()
for _,v in pairs( efsw_include_paths ) for _,v in pairs( efsw_include_paths )
do do
local cur_path = v .. "/sys/inotify.h" local cur_path = v .. "/sys/inotify.h"
if os.isfile( cur_path ) then if os.isfile( cur_path ) then
return true return true
end end
end end
return false return false
end end
function string.starts(String,Start) function string.starts(String,Start)
if ( _ACTION ) then if ( _ACTION ) then
return string.sub(String,1,string.len(Start))==Start return string.sub(String,1,string.len(Start))==Start
end end
return false return false
end end
function is_vs() function is_vs()
return ( string.starts(_ACTION,"vs") ) return ( string.starts(_ACTION,"vs") )
end end
function conf_warnings() function conf_warnings()
if not is_vs() then if not is_vs() then
buildoptions{ "-Wall -Wno-long-long" } buildoptions{ "-Wall -Wno-long-long" }
if not os.istarget("windows") then if not os.istarget("windows") then
buildoptions{ "-fPIC" } buildoptions{ "-fPIC" }
end end
else else
defines { "_SCL_SECURE_NO_WARNINGS" } defines { "_SCL_SECURE_NO_WARNINGS" }
end end
if _OPTIONS["thread-sanitizer"] then if _OPTIONS["thread-sanitizer"] then
buildoptions { "-fsanitize=thread" } buildoptions { "-fsanitize=thread" }
linkoptions { "-fsanitize=thread" } linkoptions { "-fsanitize=thread" }
if not os.istarget("macosx") then if not os.istarget("macosx") then
links { "tsan" } links { "tsan" }
end end
end end
end end
function conf_links() function conf_links()
if not os.istarget("windows") and not os.istarget("haiku") then if not os.istarget("windows") and not os.istarget("haiku") then
links { "pthread" } links { "pthread" }
end end
if os.istarget("macosx") then if os.istarget("macosx") then
links { "CoreFoundation.framework", "CoreServices.framework" } links { "CoreFoundation.framework", "CoreServices.framework" }
end end
end end
function conf_excludes() function conf_excludes()
if os.istarget("windows") then if os.istarget("windows") then
excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherInotify.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherInotify.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
elseif os.istarget("linux") then elseif os.istarget("linux") then
excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherKqueue.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherKqueue.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
elseif os.istarget("macosx") then elseif os.istarget("macosx") then
excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp" } excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp" }
elseif os.istarget("bsd") then elseif os.istarget("bsd") then
excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" } excludes { "src/efsw/WatcherInotify.cpp", "src/efsw/WatcherWin32.cpp", "src/efsw/WatcherFSEvents.cpp", "src/efsw/FileWatcherInotify.cpp", "src/efsw/FileWatcherWin32.cpp", "src/efsw/FileWatcherFSEvents.cpp" }
end end
if os.istarget("linux") and not inotify_header_exists() then if os.istarget("linux") and not inotify_header_exists() then
defines { "EFSW_INOTIFY_NOSYS" } defines { "EFSW_INOTIFY_NOSYS" }
end end
end end
workspace "efsw" workspace "efsw"
location("./make/" .. os.target() .. "/") location("./make/" .. os.target() .. "/")
targetdir("./bin") targetdir("./bin")
configurations { "debug", "release", "relwithdbginfo" } configurations { "debug", "release", "relwithdbginfo" }
platforms { "x86_64", "x86", "ARM", "ARM64" } platforms { "x86_64", "x86", "ARM", "ARM64" }
if os.istarget("windows") then if os.istarget("windows") then
osfiles = "src/efsw/platform/win/*.cpp" osfiles = "src/efsw/platform/win/*.cpp"
else else
osfiles = "src/efsw/platform/posix/*.cpp" osfiles = "src/efsw/platform/posix/*.cpp"
end end
-- Activates verbose mode -- Activates verbose mode
if _OPTIONS["verbose"] then if _OPTIONS["verbose"] then
defines { "EFSW_VERBOSE" } defines { "EFSW_VERBOSE" }
end end
cppdialect "C++11" cppdialect "C++11"
objdir("obj/" .. os.target() .. "/") objdir("obj/" .. os.target() .. "/")
filter "platforms:x86" filter "platforms:x86"
architecture "x86" architecture "x86"
filter "platforms:x86_64" filter "platforms:x86_64"
architecture "x86_64" architecture "x86_64"
filter "platforms:arm" filter "platforms:arm"
architecture "ARM" architecture "ARM"
filter "platforms:arm64" filter "platforms:arm64"
architecture "ARM64" architecture "ARM64"
project "efsw-static-lib" project "efsw-static-lib"
kind "StaticLib" kind "StaticLib"
language "C++" language "C++"
targetdir("./lib") targetdir("./lib")
includedirs { "include", "src" } includedirs { "include", "src" }
files { "src/efsw/*.cpp", osfiles } files { "src/efsw/*.cpp", osfiles }
conf_excludes() conf_excludes()
filter "configurations:debug" filter "configurations:debug"
defines { "DEBUG" } defines { "DEBUG" }
symbols "On" symbols "On"
targetname "efsw-static-debug" targetname "efsw-static-debug"
conf_warnings() conf_warnings()
filter "configurations:release" filter "configurations:release"
defines { "NDEBUG" } defines { "NDEBUG" }
optimize "On" optimize "On"
targetname "efsw-static-release" targetname "efsw-static-release"
conf_warnings() conf_warnings()
filter "configurations:relwithdbginfo" filter "configurations:relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
symbols "On" symbols "On"
optimize "On" optimize "On"
targetname "efsw-static-reldbginfo" targetname "efsw-static-reldbginfo"
conf_warnings() conf_warnings()
project "efsw-test" project "efsw-test"
kind "ConsoleApp" kind "ConsoleApp"
language "C++" language "C++"
links { "efsw-static-lib" } links { "efsw-static-lib" }
files { "src/test/*.cpp" } files { "src/test/*.cpp" }
includedirs { "include", "src" } includedirs { "include", "src" }
conf_links() conf_links()
filter "configurations:debug" filter "configurations:debug"
defines { "DEBUG" } defines { "DEBUG" }
symbols "On" symbols "On"
targetname "efsw-test-debug" targetname "efsw-test-debug"
conf_warnings() conf_warnings()
filter "configurations:release" filter "configurations:release"
defines { "NDEBUG" } defines { "NDEBUG" }
optimize "On" optimize "On"
targetname "efsw-test-release" targetname "efsw-test-release"
conf_warnings() conf_warnings()
filter "configurations:relwithdbginfo" filter "configurations:relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
symbols "On" symbols "On"
optimize "On" optimize "On"
targetname "efsw-test-reldbginfo" targetname "efsw-test-reldbginfo"
conf_warnings() conf_warnings()
project "joomer-efsw-file-monitoring" project "joomer-efsw-file-monitoring"
kind "ConsoleApp" kind "ConsoleApp"
language "C++" language "C++"
links { "efsw-static-lib" } links { "efsw-static-lib" }
files { "src/joomer-efsw-file-monitoring.cpp" } files { "src/joomer-efsw-file-monitoring.cpp" }
includedirs { "include", "src" } includedirs { "include", "src" }
conf_links() conf_links()
project "efsw-test-stdc" project "efsw-test-stdc"
kind "ConsoleApp" kind "ConsoleApp"
language "C" language "C"
links { "efsw-shared-lib" } links { "efsw-shared-lib" }
files { "src/test/*.c" } files { "src/test/*.c" }
includedirs { "include", "src" } includedirs { "include", "src" }
conf_links() conf_links()
filter "configurations:debug" filter "configurations:debug"
defines { "DEBUG" } defines { "DEBUG" }
symbols "On" symbols "On"
targetname "efsw-test-stdc-debug" targetname "efsw-test-stdc-debug"
conf_warnings() conf_warnings()
filter "configurations:release" filter "configurations:release"
defines { "NDEBUG" } defines { "NDEBUG" }
optimize "On" optimize "On"
targetname "efsw-test-stdc-release" targetname "efsw-test-stdc-release"
conf_warnings() conf_warnings()
filter "configurations:relwithdbginfo" filter "configurations:relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
symbols "On" symbols "On"
optimize "On" optimize "On"
targetname "efsw-test-stdc-reldbginfo" targetname "efsw-test-stdc-reldbginfo"
conf_warnings() conf_warnings()
project "efsw-shared-lib" project "efsw-shared-lib"
kind "SharedLib" kind "SharedLib"
language "C++" language "C++"
targetdir("./lib") targetdir("./lib")
includedirs { "include", "src" } includedirs { "include", "src" }
files { "src/efsw/*.cpp", osfiles } files { "src/efsw/*.cpp", osfiles }
defines { "EFSW_DYNAMIC", "EFSW_EXPORTS" } defines { "EFSW_DYNAMIC", "EFSW_EXPORTS" }
conf_excludes() conf_excludes()
conf_links() conf_links()
filter "configurations:debug" filter "configurations:debug"
defines { "DEBUG" } defines { "DEBUG" }
symbols "On" symbols "On"
targetname "efsw-debug" targetname "efsw-debug"
conf_warnings() conf_warnings()
filter "configurations:release" filter "configurations:release"
defines { "NDEBUG" } defines { "NDEBUG" }
optimize "On" optimize "On"
targetname "efsw" targetname "efsw"
conf_warnings() conf_warnings()
filter "configurations:relwithdbginfo" filter "configurations:relwithdbginfo"
defines { "NDEBUG" } defines { "NDEBUG" }
symbols "On" symbols "On"
optimize "On" optimize "On"
targetname "efsw" targetname "efsw"
conf_warnings() conf_warnings()
if os.istarget("linux") or os.istarget("bsd") or os.istarget("haiku") then if os.istarget("linux") or os.istarget("bsd") or os.istarget("haiku") then
targetextension ( ".so." .. efsw_version ) targetextension ( ".so." .. efsw_version )
postbuildcommands { "sh ../../project/build.reldbginfo.sh " .. efsw_major_version .. " " .. efsw_minor_version .. " " .. efsw_patch_version .. " " .. iif( _OPTIONS["strip-symbols"], "strip-symbols", "" ) } postbuildcommands { "sh ../../project/build.reldbginfo.sh " .. efsw_major_version .. " " .. efsw_minor_version .. " " .. efsw_patch_version .. " " .. iif( _OPTIONS["strip-symbols"], "strip-symbols", "" ) }
end end

View File

@ -1,211 +1,425 @@
<?xml version="1.0" encoding="UTF-8"?> <<<<<<< HEAD
<!DOCTYPE QtCreatorProject> <?xml version="1.0" encoding="UTF-8"?>
<!-- Written by QtCreator 4.10.2, 2019-11-10T01:12:11. --> <!DOCTYPE QtCreatorProject>
<qtcreator> <!-- Written by QtCreator 4.10.2, 2019-11-10T01:12:11. -->
<data> <qtcreator>
<variable>EnvironmentId</variable> <data>
<value type="QByteArray">{55fc4913-4acc-49e6-b0d5-ebf25d4d498e}</value> <variable>EnvironmentId</variable>
</data> <value type="QByteArray">{55fc4913-4acc-49e6-b0d5-ebf25d4d498e}</value>
<data> </data>
<variable>ProjectExplorer.Project.ActiveTarget</variable> <data>
<value type="int">0</value> <variable>ProjectExplorer.Project.ActiveTarget</variable>
</data> <value type="int">0</value>
<data> </data>
<variable>ProjectExplorer.Project.EditorSettings</variable> <data>
<valuemap type="QVariantMap"> <variable>ProjectExplorer.Project.EditorSettings</variable>
<value type="bool" key="EditorConfiguration.AutoIndent">true</value> <valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<value type="QString" key="language">Cpp</value> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<valuemap type="QVariantMap" key="value"> <value type="QString" key="language">Cpp</value>
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value> <valuemap type="QVariantMap" key="value">
</valuemap> <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap> </valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1"> </valuemap>
<value type="QString" key="language">QmlJS</value> <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<valuemap type="QVariantMap" key="value"> <value type="QString" key="language">QmlJS</value>
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value> <valuemap type="QVariantMap" key="value">
</valuemap> <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap> </valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value> </valuemap>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value> <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> <value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value> <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value> <value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value> <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value> <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> <value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value> <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value> <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabSize">8</value> <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value> <value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value> <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value> <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
</valuemap> <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</data> </valuemap>
<data> </data>
<variable>ProjectExplorer.Project.PluginSettings</variable> <data>
<valuemap type="QVariantMap"/> <variable>ProjectExplorer.Project.PluginSettings</variable>
</data> <valuemap type="QVariantMap"/>
<data> </data>
<variable>ProjectExplorer.Project.Target.0</variable> <data>
<valuemap type="QVariantMap"> <variable>ProjectExplorer.Project.Target.0</variable>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> <valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{eb5b6178-a7a7-439e-ab01-e63b057196a1}</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{eb5b6178-a7a7-439e-ab01-e63b057196a1}</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\programming\efsw\make\windows</value> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\programming\efsw\make\windows</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString">all</value> <valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
</valuelist> <value type="QString">all</value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value> </valuelist>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value> <value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value> <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value> <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> <value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> </valuemap>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> </valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString">clean</value> <valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
</valuelist> <value type="QString">clean</value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">true</value> </valuelist>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value> <value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">true</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value> <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value> <value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> <value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> </valuemap>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> </valuemap>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default</value> <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value> </valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value> <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value> </valuemap>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value> <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
</valuemap> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value> </valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/> <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value> <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Perf.Events"> <value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<value type="QString">cpu-cycles</value> <valuelist type="QVariantList" key="Analyzer.Perf.Events">
</valuelist> <value type="QString">cpu-cycles</value>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/> </valuelist>
<value type="int" key="Analyzer.Perf.Frequency">250</value> <valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value> <value type="int" key="Analyzer.Perf.Frequency">250</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value> <value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value> <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value> <value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value> <value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value> <value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value> <value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value> <value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/> <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value> <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value> <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value> <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value> <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value> <value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value> <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/> <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value> <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value> <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value> <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value> <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value> <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds"> <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<value type="int">0</value> <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">1</value> <value type="int">0</value>
<value type="int">2</value> <value type="int">1</value>
<value type="int">3</value> <value type="int">2</value>
<value type="int">4</value> <value type="int">3</value>
<value type="int">5</value> <value type="int">4</value>
<value type="int">6</value> <value type="int">5</value>
<value type="int">7</value> <value type="int">6</value>
<value type="int">8</value> <value type="int">7</value>
<value type="int">9</value> <value type="int">8</value>
<value type="int">10</value> <value type="int">9</value>
<value type="int">11</value> <value type="int">10</value>
<value type="int">12</value> <value type="int">11</value>
<value type="int">13</value> <value type="int">12</value>
<value type="int">14</value> <value type="int">13</value>
</valuelist> <value type="int">14</value>
<value type="int" key="PE.EnvironmentAspect.Base">2</value> </valuelist>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> <value type="int" key="PE.EnvironmentAspect.Base">2</value>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%{buildDir}\..\..\bin\efsw-test-debug.exe</value> <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run C:\programming\efsw\bin\efsw-test-debug.exe</value> <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%{buildDir}\..\..\bin\efsw-test-debug.exe</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run C:\programming\efsw\bin\efsw-test-debug.exe</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="RunConfiguration.Arguments"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> <value type="QString" key="RunConfiguration.Arguments"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="QString" key="RunConfiguration.WorkingDirectory">%{buildDir}</value> <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value> <value type="QString" key="RunConfiguration.WorkingDirectory">%{buildDir}</value>
</valuemap> <value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> </valuemap>
</valuemap> <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</data> </valuemap>
<data> </data>
<variable>ProjectExplorer.Project.TargetCount</variable> <data>
<value type="int">1</value> <variable>ProjectExplorer.Project.TargetCount</variable>
</data> <value type="int">1</value>
<data> </data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable> <data>
<value type="int">22</value> <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
</data> <value type="int">22</value>
<data> </data>
<variable>Version</variable> <data>
<value type="int">22</value> <variable>Version</variable>
</data> <value type="int">22</value>
</qtcreator> </data>
</qtcreator>
=======
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.10.2, 2019-11-10T01:12:11. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{55fc4913-4acc-49e6-b0d5-ebf25d4d498e}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{eb5b6178-a7a7-439e-ab01-e63b057196a1}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\programming\efsw\make\windows</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">false</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="GenericProjectManager.GenericMakeStep.Clean">true</value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeArguments"></value>
<value type="QString" key="GenericProjectManager.GenericMakeStep.MakeCommand"></value>
<value type="bool" key="GenericProjectManager.GenericMakeStep.OverrideMakeflags">false</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%{buildDir}\..\..\bin\efsw-test-debug.exe</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run C:\programming\efsw\bin\efsw-test-debug.exe</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory">%{buildDir}</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>
>>>>>>> 0adf96dcdb6ba38e789d409ca1bf1fc149e60808

View File

@ -1,215 +1,433 @@
../../include/efsw/efsw.hpp <<<<<<< HEAD
../../premake5.lua ../../include/efsw/efsw.hpp
../../src/efsw/FileWatcher.cpp ../../premake5.lua
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/Thread.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/Thread.cpp
../../src/efsw/System.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/platform/platformimpl.hpp ../../src/efsw/System.cpp
../../src/efsw/platform/posix/ThreadImpl.hpp ../../src/efsw/platform/platformimpl.hpp
../../src/efsw/platform/posix/MutexImpl.hpp ../../src/efsw/platform/posix/ThreadImpl.hpp
../../src/efsw/platform/posix/SystemImpl.hpp ../../src/efsw/platform/posix/MutexImpl.hpp
../../src/efsw/platform/posix/ThreadImpl.cpp ../../src/efsw/platform/posix/SystemImpl.hpp
../../src/efsw/platform/posix/MutexImpl.cpp ../../src/efsw/platform/posix/ThreadImpl.cpp
../../src/efsw/platform/posix/SystemImpl.cpp ../../src/efsw/platform/posix/MutexImpl.cpp
../../src/efsw/platform/win/ThreadImpl.hpp ../../src/efsw/platform/posix/SystemImpl.cpp
../../src/efsw/platform/win/MutexImpl.hpp ../../src/efsw/platform/win/ThreadImpl.hpp
../../src/efsw/platform/win/SystemImpl.hpp ../../src/efsw/platform/win/MutexImpl.hpp
../../src/efsw/platform/win/ThreadImpl.cpp ../../src/efsw/platform/win/SystemImpl.hpp
../../src/efsw/platform/win/MutexImpl.cpp ../../src/efsw/platform/win/ThreadImpl.cpp
../../src/efsw/platform/win/SystemImpl.cpp ../../src/efsw/platform/win/MutexImpl.cpp
../../src/efsw/base.hpp ../../src/efsw/platform/win/SystemImpl.cpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/base.hpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/platform/posix/FileSystemImpl.hpp ../../src/efsw/FileSystem.cpp
../../src/efsw/platform/posix/FileSystemImpl.cpp ../../src/efsw/platform/posix/FileSystemImpl.hpp
../../src/efsw/platform/win/FileSystemImpl.hpp ../../src/efsw/platform/posix/FileSystemImpl.cpp
../../src/efsw/platform/win/FileSystemImpl.cpp ../../src/efsw/platform/win/FileSystemImpl.hpp
../../src/efsw/FileInfo.cpp ../../src/efsw/platform/win/FileSystemImpl.cpp
../../src/efsw/base.hpp ../../src/efsw/FileInfo.cpp
../../src/efsw/Thread.hpp ../../src/efsw/base.hpp
../../src/efsw/System.hpp ../../src/efsw/Thread.hpp
../../src/efsw/Mutex.hpp ../../src/efsw/System.hpp
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileSystem.hpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileInfo.hpp ../../src/efsw/FileSystem.hpp
../../src/efsw/Thread.cpp ../../src/efsw/FileInfo.hpp
../../src/efsw/System.cpp ../../src/efsw/Thread.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/System.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileInfo.cpp ../../src/efsw/FileSystem.cpp
../../src/efsw/sophist.h ../../src/efsw/FileInfo.cpp
../../src/efsw/base.hpp ../../src/efsw/sophist.h
../../src/efsw/Utf.hpp ../../src/efsw/base.hpp
../../src/efsw/Thread.hpp ../../src/efsw/Utf.hpp
../../src/efsw/System.hpp ../../src/efsw/Thread.hpp
../../src/efsw/String.hpp ../../src/efsw/System.hpp
../../src/efsw/Mutex.hpp ../../src/efsw/String.hpp
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileSystem.hpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileInfo.hpp ../../src/efsw/FileSystem.hpp
../../src/efsw/Utf.inl ../../src/efsw/FileInfo.hpp
../../src/efsw/Thread.cpp ../../src/efsw/Utf.inl
../../src/efsw/System.cpp ../../src/efsw/Thread.cpp
../../src/efsw/String.cpp ../../src/efsw/System.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/String.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileInfo.cpp ../../src/efsw/FileSystem.cpp
../../src/test/efsw-test.cpp ../../src/efsw/FileInfo.cpp
../../src/efsw/WatcherKqueue.hpp ../../src/test/efsw-test.cpp
../../src/efsw/WatcherInotify.hpp ../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherGeneric.hpp ../../src/efsw/WatcherInotify.hpp
../../src/efsw/Utf.hpp ../../src/efsw/WatcherGeneric.hpp
../../src/efsw/Thread.hpp ../../src/efsw/Utf.hpp
../../src/efsw/System.hpp ../../src/efsw/Thread.hpp
../../src/efsw/String.hpp ../../src/efsw/System.hpp
../../src/efsw/Mutex.hpp ../../src/efsw/String.hpp
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileSystem.hpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileInfo.hpp ../../src/efsw/FileSystem.hpp
../../src/efsw/DirWatcherGeneric.hpp ../../src/efsw/FileInfo.hpp
../../src/efsw/Debug.hpp ../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/base.hpp ../../src/efsw/Debug.hpp
../../src/efsw/sophist.h ../../src/efsw/base.hpp
../../src/efsw/Utf.inl ../../src/efsw/sophist.h
../../src/efsw/WatcherKqueue.cpp ../../src/efsw/Utf.inl
../../src/efsw/WatcherInotify.cpp ../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherGeneric.cpp ../../src/efsw/WatcherInotify.cpp
../../src/efsw/Thread.cpp ../../src/efsw/WatcherGeneric.cpp
../../src/efsw/System.cpp ../../src/efsw/Thread.cpp
../../src/efsw/String.cpp ../../src/efsw/System.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/String.cpp
../../src/efsw/Log.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/Log.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileInfo.cpp ../../src/efsw/FileSystem.cpp
../../src/efsw/DirWatcherGeneric.cpp ../../src/efsw/FileInfo.cpp
../../src/efsw/Debug.cpp ../../src/efsw/DirWatcherGeneric.cpp
../../premake4.lua ../../src/efsw/Debug.cpp
../../src/efsw/WatcherKqueue.hpp ../../premake4.lua
../../src/efsw/WatcherInotify.hpp ../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherGeneric.hpp ../../src/efsw/WatcherInotify.hpp
../../src/efsw/Utf.hpp ../../src/efsw/WatcherGeneric.hpp
../../src/efsw/Thread.hpp ../../src/efsw/Utf.hpp
../../src/efsw/System.hpp ../../src/efsw/Thread.hpp
../../src/efsw/String.hpp ../../src/efsw/System.hpp
../../src/efsw/sophist.h ../../src/efsw/String.hpp
../../src/efsw/Mutex.hpp ../../src/efsw/sophist.h
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileSystem.hpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileInfo.hpp ../../src/efsw/FileSystem.hpp
../../src/efsw/DirWatcherGeneric.hpp ../../src/efsw/FileInfo.hpp
../../src/efsw/Debug.hpp ../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/base.hpp ../../src/efsw/Debug.hpp
../../src/efsw/Utf.inl ../../src/efsw/base.hpp
../../src/efsw/WatcherKqueue.cpp ../../src/efsw/Utf.inl
../../src/efsw/WatcherInotify.cpp ../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherGeneric.cpp ../../src/efsw/WatcherInotify.cpp
../../src/efsw/Thread.cpp ../../src/efsw/WatcherGeneric.cpp
../../src/efsw/System.cpp ../../src/efsw/Thread.cpp
../../src/efsw/String.cpp ../../src/efsw/System.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/String.cpp
../../src/efsw/Log.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/Log.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherImpl.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherImpl.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileInfo.cpp ../../src/efsw/FileSystem.cpp
../../src/efsw/DirWatcherGeneric.cpp ../../src/efsw/FileInfo.cpp
../../src/efsw/Debug.cpp ../../src/efsw/DirWatcherGeneric.cpp
../../src/efsw/WatcherWin32.hpp ../../src/efsw/Debug.cpp
../../src/efsw/WatcherKqueue.hpp ../../src/efsw/WatcherWin32.hpp
../../src/efsw/WatcherInotify.hpp ../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherGeneric.hpp ../../src/efsw/WatcherInotify.hpp
../../src/efsw/WatcherFSEvents.hpp ../../src/efsw/WatcherGeneric.hpp
../../src/efsw/Watcher.hpp ../../src/efsw/WatcherFSEvents.hpp
../../src/efsw/Utf.hpp ../../src/efsw/Watcher.hpp
../../src/efsw/Thread.hpp ../../src/efsw/Utf.hpp
../../src/efsw/System.hpp ../../src/efsw/Thread.hpp
../../src/efsw/String.hpp ../../src/efsw/System.hpp
../../src/efsw/sophist.h ../../src/efsw/String.hpp
../../src/efsw/Mutex.hpp ../../src/efsw/sophist.h
../../src/efsw/FileWatcherWin32.hpp ../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherKqueue.hpp ../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherInotify.hpp ../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherImpl.hpp ../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherGeneric.hpp ../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherFSEvents.hpp ../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.hpp ../../src/efsw/FileWatcherFSEvents.hpp
../../src/efsw/FileInfo.hpp ../../src/efsw/FileSystem.hpp
../../src/efsw/DirWatcherGeneric.hpp ../../src/efsw/FileInfo.hpp
../../src/efsw/DirectorySnapshotDiff.hpp ../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/DirectorySnapshot.hpp ../../src/efsw/DirectorySnapshotDiff.hpp
../../src/efsw/Debug.hpp ../../src/efsw/DirectorySnapshot.hpp
../../src/efsw/base.hpp ../../src/efsw/Debug.hpp
../../src/efsw/Utf.inl ../../src/efsw/base.hpp
../../src/efsw/WatcherWin32.cpp ../../src/efsw/Utf.inl
../../src/efsw/WatcherKqueue.cpp ../../src/efsw/WatcherWin32.cpp
../../src/efsw/WatcherInotify.cpp ../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherGeneric.cpp ../../src/efsw/WatcherInotify.cpp
../../src/efsw/WatcherFSEvents.cpp ../../src/efsw/WatcherGeneric.cpp
../../src/efsw/Watcher.cpp ../../src/efsw/WatcherFSEvents.cpp
../../src/efsw/Thread.cpp ../../src/efsw/Watcher.cpp
../../src/efsw/System.cpp ../../src/efsw/Thread.cpp
../../src/efsw/String.cpp ../../src/efsw/System.cpp
../../src/efsw/Mutex.cpp ../../src/efsw/String.cpp
../../src/efsw/Log.cpp ../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherWin32.cpp ../../src/efsw/Log.cpp
../../src/efsw/FileWatcherKqueue.cpp ../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherInotify.cpp ../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherImpl.cpp ../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherGeneric.cpp ../../src/efsw/FileWatcherImpl.cpp
../../src/efsw/FileWatcherFSEvents.cpp ../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcher.cpp ../../src/efsw/FileWatcherFSEvents.cpp
../../src/efsw/FileSystem.cpp ../../src/efsw/FileWatcher.cpp
../../src/efsw/FileInfo.cpp ../../src/efsw/FileSystem.cpp
../../src/efsw/DirWatcherGeneric.cpp ../../src/efsw/FileInfo.cpp
../../src/efsw/DirectorySnapshotDiff.cpp ../../src/efsw/DirWatcherGeneric.cpp
../../src/efsw/DirectorySnapshot.cpp ../../src/efsw/DirectorySnapshotDiff.cpp
../../src/efsw/Debug.cpp ../../src/efsw/DirectorySnapshot.cpp
../../include/efsw/efsw.h ../../src/efsw/Debug.cpp
../../src/efsw/FileWatcherCWrapper.cpp ../../include/efsw/efsw.h
../../src/efsw/FileWatcherCWrapper.cpp
=======
../../include/efsw/efsw.hpp
../../premake5.lua
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/Thread.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/System.cpp
../../src/efsw/platform/platformimpl.hpp
../../src/efsw/platform/posix/ThreadImpl.hpp
../../src/efsw/platform/posix/MutexImpl.hpp
../../src/efsw/platform/posix/SystemImpl.hpp
../../src/efsw/platform/posix/ThreadImpl.cpp
../../src/efsw/platform/posix/MutexImpl.cpp
../../src/efsw/platform/posix/SystemImpl.cpp
../../src/efsw/platform/win/ThreadImpl.hpp
../../src/efsw/platform/win/MutexImpl.hpp
../../src/efsw/platform/win/SystemImpl.hpp
../../src/efsw/platform/win/ThreadImpl.cpp
../../src/efsw/platform/win/MutexImpl.cpp
../../src/efsw/platform/win/SystemImpl.cpp
../../src/efsw/base.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/platform/posix/FileSystemImpl.hpp
../../src/efsw/platform/posix/FileSystemImpl.cpp
../../src/efsw/platform/win/FileSystemImpl.hpp
../../src/efsw/platform/win/FileSystemImpl.cpp
../../src/efsw/FileInfo.cpp
../../src/efsw/base.hpp
../../src/efsw/Thread.hpp
../../src/efsw/System.hpp
../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.hpp
../../src/efsw/FileInfo.hpp
../../src/efsw/Thread.cpp
../../src/efsw/System.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/FileInfo.cpp
../../src/efsw/sophist.h
../../src/efsw/base.hpp
../../src/efsw/Utf.hpp
../../src/efsw/Thread.hpp
../../src/efsw/System.hpp
../../src/efsw/String.hpp
../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.hpp
../../src/efsw/FileInfo.hpp
../../src/efsw/Utf.inl
../../src/efsw/Thread.cpp
../../src/efsw/System.cpp
../../src/efsw/String.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/FileInfo.cpp
../../src/test/efsw-test.cpp
../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherInotify.hpp
../../src/efsw/WatcherGeneric.hpp
../../src/efsw/Utf.hpp
../../src/efsw/Thread.hpp
../../src/efsw/System.hpp
../../src/efsw/String.hpp
../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.hpp
../../src/efsw/FileInfo.hpp
../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/Debug.hpp
../../src/efsw/base.hpp
../../src/efsw/sophist.h
../../src/efsw/Utf.inl
../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherInotify.cpp
../../src/efsw/WatcherGeneric.cpp
../../src/efsw/Thread.cpp
../../src/efsw/System.cpp
../../src/efsw/String.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/Log.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/FileInfo.cpp
../../src/efsw/DirWatcherGeneric.cpp
../../src/efsw/Debug.cpp
../../premake4.lua
../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherInotify.hpp
../../src/efsw/WatcherGeneric.hpp
../../src/efsw/Utf.hpp
../../src/efsw/Thread.hpp
../../src/efsw/System.hpp
../../src/efsw/String.hpp
../../src/efsw/sophist.h
../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileSystem.hpp
../../src/efsw/FileInfo.hpp
../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/Debug.hpp
../../src/efsw/base.hpp
../../src/efsw/Utf.inl
../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherInotify.cpp
../../src/efsw/WatcherGeneric.cpp
../../src/efsw/Thread.cpp
../../src/efsw/System.cpp
../../src/efsw/String.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/Log.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherImpl.cpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/FileInfo.cpp
../../src/efsw/DirWatcherGeneric.cpp
../../src/efsw/Debug.cpp
../../src/efsw/WatcherWin32.hpp
../../src/efsw/WatcherKqueue.hpp
../../src/efsw/WatcherInotify.hpp
../../src/efsw/WatcherGeneric.hpp
../../src/efsw/WatcherFSEvents.hpp
../../src/efsw/Watcher.hpp
../../src/efsw/Utf.hpp
../../src/efsw/Thread.hpp
../../src/efsw/System.hpp
../../src/efsw/String.hpp
../../src/efsw/sophist.h
../../src/efsw/Mutex.hpp
../../src/efsw/FileWatcherWin32.hpp
../../src/efsw/FileWatcherKqueue.hpp
../../src/efsw/FileWatcherInotify.hpp
../../src/efsw/FileWatcherImpl.hpp
../../src/efsw/FileWatcherGeneric.hpp
../../src/efsw/FileWatcherFSEvents.hpp
../../src/efsw/FileSystem.hpp
../../src/efsw/FileInfo.hpp
../../src/efsw/DirWatcherGeneric.hpp
../../src/efsw/DirectorySnapshotDiff.hpp
../../src/efsw/DirectorySnapshot.hpp
../../src/efsw/Debug.hpp
../../src/efsw/base.hpp
../../src/efsw/Utf.inl
../../src/efsw/WatcherWin32.cpp
../../src/efsw/WatcherKqueue.cpp
../../src/efsw/WatcherInotify.cpp
../../src/efsw/WatcherGeneric.cpp
../../src/efsw/WatcherFSEvents.cpp
../../src/efsw/Watcher.cpp
../../src/efsw/Thread.cpp
../../src/efsw/System.cpp
../../src/efsw/String.cpp
../../src/efsw/Mutex.cpp
../../src/efsw/Log.cpp
../../src/efsw/FileWatcherWin32.cpp
../../src/efsw/FileWatcherKqueue.cpp
../../src/efsw/FileWatcherInotify.cpp
../../src/efsw/FileWatcherImpl.cpp
../../src/efsw/FileWatcherGeneric.cpp
../../src/efsw/FileWatcherFSEvents.cpp
../../src/efsw/FileWatcher.cpp
../../src/efsw/FileSystem.cpp
../../src/efsw/FileInfo.cpp
../../src/efsw/DirWatcherGeneric.cpp
../../src/efsw/DirectorySnapshotDiff.cpp
../../src/efsw/DirectorySnapshot.cpp
../../src/efsw/Debug.cpp
../../include/efsw/efsw.h
../../src/efsw/FileWatcherCWrapper.cpp
>>>>>>> 0adf96dcdb6ba38e789d409ca1bf1fc149e60808

View File

@ -1,120 +1,120 @@
#include <efsw/FileSystem.hpp> #include <efsw/FileSystem.hpp>
#include <efsw/FileWatcherGeneric.hpp> #include <efsw/FileWatcherGeneric.hpp>
#include <efsw/FileWatcherImpl.hpp> #include <efsw/FileWatcherImpl.hpp>
#include <efsw/efsw.hpp> #include <efsw/efsw.hpp>
#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
#include <efsw/FileWatcherWin32.hpp> #include <efsw/FileWatcherWin32.hpp>
#define FILEWATCHER_IMPL FileWatcherWin32 #define FILEWATCHER_IMPL FileWatcherWin32
#define BACKEND_NAME "Win32" #define BACKEND_NAME "Win32"
#elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY #elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY
#include <efsw/FileWatcherInotify.hpp> #include <efsw/FileWatcherInotify.hpp>
#define FILEWATCHER_IMPL FileWatcherInotify #define FILEWATCHER_IMPL FileWatcherInotify
#define BACKEND_NAME "Inotify" #define BACKEND_NAME "Inotify"
#elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE #elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE
#include <efsw/FileWatcherKqueue.hpp> #include <efsw/FileWatcherKqueue.hpp>
#define FILEWATCHER_IMPL FileWatcherKqueue #define FILEWATCHER_IMPL FileWatcherKqueue
#define BACKEND_NAME "Kqueue" #define BACKEND_NAME "Kqueue"
#elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS #elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
#include <efsw/FileWatcherFSEvents.hpp> #include <efsw/FileWatcherFSEvents.hpp>
#define FILEWATCHER_IMPL FileWatcherFSEvents #define FILEWATCHER_IMPL FileWatcherFSEvents
#define BACKEND_NAME "FSEvents" #define BACKEND_NAME "FSEvents"
#else #else
#define FILEWATCHER_IMPL FileWatcherGeneric #define FILEWATCHER_IMPL FileWatcherGeneric
#define BACKEND_NAME "Generic" #define BACKEND_NAME "Generic"
#endif #endif
#include <efsw/Debug.hpp> #include <efsw/Debug.hpp>
namespace efsw { namespace efsw {
FileWatcher::FileWatcher() : mFollowSymlinks( false ), mOutOfScopeLinks( false ) { FileWatcher::FileWatcher() : mFollowSymlinks( false ), mOutOfScopeLinks( false ) {
efDEBUG( "Using backend: %s\n", BACKEND_NAME ); efDEBUG( "Using backend: %s\n", BACKEND_NAME );
mImpl = new FILEWATCHER_IMPL( this ); mImpl = new FILEWATCHER_IMPL( this );
if ( !mImpl->initOK() ) { if ( !mImpl->initOK() ) {
efSAFE_DELETE( mImpl ); efSAFE_DELETE( mImpl );
efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME );
mImpl = new FileWatcherGeneric( this ); mImpl = new FileWatcherGeneric( this );
} }
} }
FileWatcher::FileWatcher( bool useGenericFileWatcher ) : FileWatcher::FileWatcher( bool useGenericFileWatcher ) :
mFollowSymlinks( false ), mOutOfScopeLinks( false ) { mFollowSymlinks( false ), mOutOfScopeLinks( false ) {
if ( useGenericFileWatcher ) { if ( useGenericFileWatcher ) {
efDEBUG( "Using backend: Generic\n" ); efDEBUG( "Using backend: Generic\n" );
mImpl = new FileWatcherGeneric( this ); mImpl = new FileWatcherGeneric( this );
} else { } else {
efDEBUG( "Using backend: %s\n", BACKEND_NAME ); efDEBUG( "Using backend: %s\n", BACKEND_NAME );
mImpl = new FILEWATCHER_IMPL( this ); mImpl = new FILEWATCHER_IMPL( this );
if ( !mImpl->initOK() ) { if ( !mImpl->initOK() ) {
efSAFE_DELETE( mImpl ); efSAFE_DELETE( mImpl );
efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME );
mImpl = new FileWatcherGeneric( this ); mImpl = new FileWatcherGeneric( this );
} }
} }
} }
FileWatcher::~FileWatcher() { FileWatcher::~FileWatcher() {
efSAFE_DELETE( mImpl ); efSAFE_DELETE( mImpl );
} }
WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher ) { WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher ) {
return addWatch( directory, watcher, false, {} ); return addWatch( directory, watcher, false, {} );
} }
WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher,
bool recursive ) { bool recursive ) {
return addWatch( directory, watcher, recursive, {} ); return addWatch( directory, watcher, recursive, {} );
} }
WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher,
bool recursive, const std::vector<WatcherOption>& options ) { bool recursive, const std::vector<WatcherOption>& options ) {
if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) { if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) {
return mImpl->addWatch( directory, watcher, recursive, options ); return mImpl->addWatch( directory, watcher, recursive, options );
} else { } else {
return Errors::Log::createLastError( Errors::FileRemote, directory ); return Errors::Log::createLastError( Errors::FileRemote, directory );
} }
} }
void FileWatcher::removeWatch( const std::string& directory ) { void FileWatcher::removeWatch( const std::string& directory ) {
mImpl->removeWatch( directory ); mImpl->removeWatch( directory );
} }
void FileWatcher::removeWatch( WatchID watchid ) { void FileWatcher::removeWatch( WatchID watchid ) {
mImpl->removeWatch( watchid ); mImpl->removeWatch( watchid );
} }
void FileWatcher::watch() { void FileWatcher::watch() {
mImpl->watch(); mImpl->watch();
} }
std::vector<std::string> FileWatcher::directories() { std::vector<std::string> FileWatcher::directories() {
return mImpl->directories(); return mImpl->directories();
} }
void FileWatcher::followSymlinks( bool follow ) { void FileWatcher::followSymlinks( bool follow ) {
mFollowSymlinks = follow; mFollowSymlinks = follow;
} }
const bool& FileWatcher::followSymlinks() const { const bool& FileWatcher::followSymlinks() const {
return mFollowSymlinks; return mFollowSymlinks;
} }
void FileWatcher::allowOutOfScopeLinks( bool allow ) { void FileWatcher::allowOutOfScopeLinks( bool allow ) {
mOutOfScopeLinks = allow; mOutOfScopeLinks = allow;
} }
const bool& FileWatcher::allowOutOfScopeLinks() const { const bool& FileWatcher::allowOutOfScopeLinks() const {
return mOutOfScopeLinks; return mOutOfScopeLinks;
} }
} // namespace efsw } // namespace efsw

View File

@ -1,34 +1,34 @@
#include <efsw/FileWatcherImpl.hpp> #include <efsw/FileWatcherImpl.hpp>
#include <efsw/String.hpp> #include <efsw/String.hpp>
#include <efsw/System.hpp> #include <efsw/System.hpp>
namespace efsw { namespace efsw {
FileWatcherImpl::FileWatcherImpl( FileWatcher* parent ) : FileWatcherImpl::FileWatcherImpl( FileWatcher* parent ) :
mFileWatcher( parent ), mInitOK( false ), mIsGeneric( false ) { mFileWatcher( parent ), mInitOK( false ), mIsGeneric( false ) {
System::maxFD(); System::maxFD();
} }
FileWatcherImpl::~FileWatcherImpl() {} FileWatcherImpl::~FileWatcherImpl() {}
bool FileWatcherImpl::initOK() { bool FileWatcherImpl::initOK() {
return static_cast<bool>( mInitOK ); return static_cast<bool>( mInitOK );
} }
bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) { bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) {
return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) ||
-1 != String::strStartsWith( curPath, link ); -1 != String::strStartsWith( curPath, link );
} }
int FileWatcherImpl::getOptionValue( const std::vector<WatcherOption>& options, Option option, int FileWatcherImpl::getOptionValue( const std::vector<WatcherOption>& options, Option option,
int defaultValue ) { int defaultValue ) {
for ( size_t i = 0; i < options.size(); i++ ) { for ( size_t i = 0; i < options.size(); i++ ) {
if ( options[i].mOption == option ) { if ( options[i].mOption == option ) {
return options[i].mValue; return options[i].mValue;
} }
} }
return defaultValue; return defaultValue;
} }
} // namespace efsw } // namespace efsw

View File

@ -1,64 +1,64 @@
#ifndef EFSW_FILEWATCHERIMPL_HPP #ifndef EFSW_FILEWATCHERIMPL_HPP
#define EFSW_FILEWATCHERIMPL_HPP #define EFSW_FILEWATCHERIMPL_HPP
#include <efsw/Atomic.hpp> #include <efsw/Atomic.hpp>
#include <efsw/Mutex.hpp> #include <efsw/Mutex.hpp>
#include <efsw/Thread.hpp> #include <efsw/Thread.hpp>
#include <efsw/Watcher.hpp> #include <efsw/Watcher.hpp>
#include <efsw/base.hpp> #include <efsw/base.hpp>
#include <efsw/efsw.hpp> #include <efsw/efsw.hpp>
namespace efsw { namespace efsw {
class FileWatcherImpl { class FileWatcherImpl {
public: public:
FileWatcherImpl( FileWatcher* parent ); FileWatcherImpl( FileWatcher* parent );
virtual ~FileWatcherImpl(); virtual ~FileWatcherImpl();
/// Add a directory watch /// Add a directory watch
/// On error returns WatchID with Error type. /// On error returns WatchID with Error type.
virtual WatchID addWatch( const std::string& directory, FileWatchListener* watcher, virtual WatchID addWatch( const std::string& directory, FileWatchListener* watcher,
bool recursive, const std::vector<WatcherOption>& options = {} ) = 0; bool recursive, const std::vector<WatcherOption>& options = {} ) = 0;
/// Remove a directory watch. This is a brute force lazy search O(nlogn). /// Remove a directory watch. This is a brute force lazy search O(nlogn).
virtual void removeWatch( const std::string& directory ) = 0; virtual void removeWatch( const std::string& directory ) = 0;
/// Remove a directory watch. This is a map lookup O(logn). /// Remove a directory watch. This is a map lookup O(logn).
virtual void removeWatch( WatchID watchid ) = 0; virtual void removeWatch( WatchID watchid ) = 0;
/// Updates the watcher. Must be called often. /// Updates the watcher. Must be called often.
virtual void watch() = 0; virtual void watch() = 0;
/// Handles the action /// Handles the action
virtual void handleAction( Watcher* watch, const std::string& filename, unsigned long action, virtual void handleAction( Watcher* watch, const std::string& filename, unsigned long action,
std::string oldFilename = "" ) = 0; std::string oldFilename = "" ) = 0;
/// @return Returns a list of the directories that are being watched /// @return Returns a list of the directories that are being watched
virtual std::vector<std::string> directories() = 0; virtual std::vector<std::string> directories() = 0;
/// @return true if the backend init successfully /// @return true if the backend init successfully
virtual bool initOK(); virtual bool initOK();
/// @return If the link is allowed according to the current path and the state of out scope /// @return If the link is allowed according to the current path and the state of out scope
/// links /// links
virtual bool linkAllowed( const std::string& curPath, const std::string& link ); virtual bool linkAllowed( const std::string& curPath, const std::string& link );
/// Search if a directory already exists in the watches /// Search if a directory already exists in the watches
virtual bool pathInWatches( const std::string& path ) = 0; virtual bool pathInWatches( const std::string& path ) = 0;
protected: protected:
friend class FileWatcher; friend class FileWatcher;
friend class DirWatcherGeneric; friend class DirWatcherGeneric;
FileWatcher* mFileWatcher; FileWatcher* mFileWatcher;
Atomic<bool> mInitOK; Atomic<bool> mInitOK;
bool mIsGeneric; bool mIsGeneric;
int getOptionValue( const std::vector<WatcherOption>& options, Option option, int getOptionValue( const std::vector<WatcherOption>& options, Option option,
int defaultValue ); int defaultValue );
}; };
} // namespace efsw } // namespace efsw
#endif #endif

View File

@ -1,267 +1,267 @@
#include <efsw/FileSystem.hpp> #include <efsw/FileSystem.hpp>
#include <efsw/FileWatcherWin32.hpp> #include <efsw/FileWatcherWin32.hpp>
#include <efsw/Lock.hpp> #include <efsw/Lock.hpp>
#include <efsw/String.hpp> #include <efsw/String.hpp>
#include <efsw/System.hpp> #include <efsw/System.hpp>
#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
namespace efsw { namespace efsw {
FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) :
FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) { FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) {
mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ); mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 );
if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE )
mInitOK = true; mInitOK = true;
} }
FileWatcherWin32::~FileWatcherWin32() { FileWatcherWin32::~FileWatcherWin32() {
mInitOK = false; mInitOK = false;
if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) { if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) {
PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL ); PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL );
} }
efSAFE_DELETE( mThread ); efSAFE_DELETE( mThread );
removeAllWatches(); removeAllWatches();
if ( mIOCP ) if ( mIOCP )
CloseHandle( mIOCP ); CloseHandle( mIOCP );
} }
WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher,
bool recursive, const std::vector<WatcherOption> &options ) { bool recursive, const std::vector<WatcherOption> &options ) {
std::string dir( directory ); std::string dir( directory );
FileInfo fi( dir ); FileInfo fi( dir );
if ( !fi.isDirectory() ) { if ( !fi.isDirectory() ) {
return Errors::Log::createLastError( Errors::FileNotFound, dir ); return Errors::Log::createLastError( Errors::FileNotFound, dir );
} else if ( !fi.isReadable() ) { } else if ( !fi.isReadable() ) {
return Errors::Log::createLastError( Errors::FileNotReadable, dir ); return Errors::Log::createLastError( Errors::FileNotReadable, dir );
} }
FileSystem::dirAddSlashAtEnd( dir ); FileSystem::dirAddSlashAtEnd( dir );
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
if ( pathInWatches( dir ) ) { if ( pathInWatches( dir ) ) {
return Errors::Log::createLastError( Errors::FileRepeated, dir ); return Errors::Log::createLastError( Errors::FileRepeated, dir );
} }
WatchID watchid = ++mLastWatchID; WatchID watchid = ++mLastWatchID;
DWORD bufferSize = static_cast<DWORD>( getOptionValue(options, Option::WinBufferSize, 63 * 1024) ); DWORD bufferSize = static_cast<DWORD>( getOptionValue(options, Option::WinBufferSize, 63 * 1024) );
DWORD notifyFilter = static_cast<DWORD>( getOptionValue(options, Option::WinNotifyFilter, DWORD notifyFilter = static_cast<DWORD>( getOptionValue(options, Option::WinNotifyFilter,
FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_SIZE) ); FILE_NOTIFY_CHANGE_SIZE) );
WatcherStructWin32* watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), WatcherStructWin32* watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(),
recursive, bufferSize, notifyFilter, mIOCP ); recursive, bufferSize, notifyFilter, mIOCP );
if ( NULL == watch ) { if ( NULL == watch ) {
return Errors::Log::createLastError( Errors::FileNotFound, dir ); return Errors::Log::createLastError( Errors::FileNotFound, dir );
} }
// Add the handle to the handles vector // Add the handle to the handles vector
watch->Watch->ID = watchid; watch->Watch->ID = watchid;
watch->Watch->Watch = this; watch->Watch->Watch = this;
watch->Watch->Listener = watcher; watch->Watch->Listener = watcher;
watch->Watch->DirName = new char[dir.length() + 1]; watch->Watch->DirName = new char[dir.length() + 1];
strcpy( watch->Watch->DirName, dir.c_str() ); strcpy( watch->Watch->DirName, dir.c_str() );
mWatches.insert( watch ); mWatches.insert( watch );
return watchid; return watchid;
} }
void FileWatcherWin32::removeWatch( const std::string& directory ) { void FileWatcherWin32::removeWatch( const std::string& directory ) {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
Watches::iterator iter = mWatches.begin(); Watches::iterator iter = mWatches.begin();
for ( ; iter != mWatches.end(); ++iter ) { for ( ; iter != mWatches.end(); ++iter ) {
if ( directory == ( *iter )->Watch->DirName ) { if ( directory == ( *iter )->Watch->DirName ) {
removeWatch( *iter ); removeWatch( *iter );
break; break;
} }
} }
} }
void FileWatcherWin32::removeWatch( WatchID watchid ) { void FileWatcherWin32::removeWatch( WatchID watchid ) {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
Watches::iterator iter = mWatches.begin(); Watches::iterator iter = mWatches.begin();
for ( ; iter != mWatches.end(); ++iter ) { for ( ; iter != mWatches.end(); ++iter ) {
// Find the watch ID // Find the watch ID
if ( ( *iter )->Watch->ID == watchid ) { if ( ( *iter )->Watch->ID == watchid ) {
removeWatch( *iter ); removeWatch( *iter );
return; return;
} }
} }
} }
void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
DestroyWatch( watch ); DestroyWatch( watch );
mWatches.erase( watch ); mWatches.erase( watch );
} }
void FileWatcherWin32::watch() { void FileWatcherWin32::watch() {
if ( NULL == mThread ) { if ( NULL == mThread ) {
mThread = new Thread([this]{run();}); mThread = new Thread([this]{run();});
mThread->launch(); mThread->launch();
} }
} }
void FileWatcherWin32::removeAllWatches() { void FileWatcherWin32::removeAllWatches() {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
Watches::iterator iter = mWatches.begin(); Watches::iterator iter = mWatches.begin();
for ( ; iter != mWatches.end(); ++iter ) { for ( ; iter != mWatches.end(); ++iter ) {
DestroyWatch( ( *iter ) ); DestroyWatch( ( *iter ) );
} }
mWatches.clear(); mWatches.clear();
} }
void FileWatcherWin32::run() { void FileWatcherWin32::run() {
do { do {
if ( mInitOK && !mWatches.empty() ) { if ( mInitOK && !mWatches.empty() ) {
DWORD numOfBytes = 0; DWORD numOfBytes = 0;
OVERLAPPED* ov = NULL; OVERLAPPED* ov = NULL;
ULONG_PTR compKey = 0; ULONG_PTR compKey = 0;
BOOL res = FALSE; BOOL res = FALSE;
while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov, while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov,
INFINITE ) ) != FALSE ) { INFINITE ) ) != FALSE ) {
if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) { if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) {
break; break;
} else { } else {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
if (mWatches.find( (WatcherStructWin32*)ov ) != mWatches.end()) if (mWatches.find( (WatcherStructWin32*)ov ) != mWatches.end())
WatchCallback( numOfBytes, ov ); WatchCallback( numOfBytes, ov );
} }
} }
} else { } else {
System::sleep( 10 ); System::sleep( 10 );
} }
} while ( mInitOK ); } while ( mInitOK );
removeAllWatches(); removeAllWatches();
} }
void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename, void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename,
unsigned long action, std::string /*oldFilename*/ ) { unsigned long action, std::string /*oldFilename*/ ) {
Action fwAction; Action fwAction;
switch ( action ) { switch ( action ) {
case FILE_ACTION_RENAMED_OLD_NAME: case FILE_ACTION_RENAMED_OLD_NAME:
watch->OldFileName = filename; watch->OldFileName = filename;
return; return;
case FILE_ACTION_ADDED: case FILE_ACTION_ADDED:
fwAction = Actions::Add; fwAction = Actions::Add;
break; break;
case FILE_ACTION_RENAMED_NEW_NAME: { case FILE_ACTION_RENAMED_NEW_NAME: {
fwAction = Actions::Moved; fwAction = Actions::Moved;
std::string fpath( watch->Directory + filename ); std::string fpath( watch->Directory + filename );
// Update the directory path // Update the directory path
if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) {
// Update the new directory path // Update the new directory path
std::string opath( watch->Directory + watch->OldFileName ); std::string opath( watch->Directory + watch->OldFileName );
FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( opath );
FileSystem::dirAddSlashAtEnd( fpath ); FileSystem::dirAddSlashAtEnd( fpath );
for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
if ( ( *it )->Watch->Directory == opath ) { if ( ( *it )->Watch->Directory == opath ) {
( *it )->Watch->Directory = fpath; ( *it )->Watch->Directory = fpath;
break; break;
} }
} }
} }
std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName );
std::string realFilename = filename; std::string realFilename = filename;
std::size_t sepPos = filename.find_last_of( "/\\" ); std::size_t sepPos = filename.find_last_of( "/\\" );
std::string oldFolderPath = std::string oldFolderPath =
static_cast<WatcherWin32*>( watch )->DirName + static_cast<WatcherWin32*>( watch )->DirName +
watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) ); watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) );
if ( sepPos != std::string::npos ) { if ( sepPos != std::string::npos ) {
folderPath += folderPath +=
filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos );
realFilename = filename.substr( sepPos + 1 ); realFilename = filename.substr( sepPos + 1 );
} }
if ( folderPath == oldFolderPath ) { if ( folderPath == oldFolderPath ) {
watch->Listener->handleFileAction( watch->Listener->handleFileAction(
watch->ID, folderPath, realFilename, fwAction, watch->ID, folderPath, realFilename, fwAction,
FileSystem::fileNameFromPath( watch->OldFileName ) ); FileSystem::fileNameFromPath( watch->OldFileName ) );
} else { } else {
watch->Listener->handleFileAction( watch->ID, watch->Listener->handleFileAction( watch->ID,
static_cast<WatcherWin32*>( watch )->DirName, static_cast<WatcherWin32*>( watch )->DirName,
filename, fwAction, watch->OldFileName ); filename, fwAction, watch->OldFileName );
} }
return; return;
} }
case FILE_ACTION_REMOVED: case FILE_ACTION_REMOVED:
fwAction = Actions::Delete; fwAction = Actions::Delete;
break; break;
case FILE_ACTION_MODIFIED: case FILE_ACTION_MODIFIED:
fwAction = Actions::Modified; fwAction = Actions::Modified;
break; break;
default: default:
return; return;
}; };
std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName );
std::string realFilename = filename; std::string realFilename = filename;
std::size_t sepPos = filename.find_last_of( "/\\" ); std::size_t sepPos = filename.find_last_of( "/\\" );
if ( sepPos != std::string::npos ) { if ( sepPos != std::string::npos ) {
folderPath += filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); folderPath += filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos );
realFilename = filename.substr( sepPos + 1 ); realFilename = filename.substr( sepPos + 1 );
} }
FileSystem::dirAddSlashAtEnd( folderPath ); FileSystem::dirAddSlashAtEnd( folderPath );
watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction ); watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction );
} }
std::vector<std::string> FileWatcherWin32::directories() { std::vector<std::string> FileWatcherWin32::directories() {
std::vector<std::string> dirs; std::vector<std::string> dirs;
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
dirs.reserve( mWatches.size() ); dirs.reserve( mWatches.size() );
for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
dirs.push_back( std::string( ( *it )->Watch->DirName ) ); dirs.push_back( std::string( ( *it )->Watch->DirName ) );
} }
return dirs; return dirs;
} }
bool FileWatcherWin32::pathInWatches( const std::string& path ) { bool FileWatcherWin32::pathInWatches( const std::string& path ) {
Lock lock( mWatchesLock ); Lock lock( mWatchesLock );
for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) {
if ( ( *it )->Watch->DirName == path ) { if ( ( *it )->Watch->DirName == path ) {
return true; return true;
} }
} }
return false; return false;
} }
} // namespace efsw } // namespace efsw
#endif #endif

View File

@ -1,71 +1,71 @@
#ifndef EFSW_FILEWATCHERWIN32_HPP #ifndef EFSW_FILEWATCHERWIN32_HPP
#define EFSW_FILEWATCHERWIN32_HPP #define EFSW_FILEWATCHERWIN32_HPP
#include <efsw/base.hpp> #include <efsw/base.hpp>
#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
#include <efsw/WatcherWin32.hpp> #include <efsw/WatcherWin32.hpp>
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
namespace efsw { namespace efsw {
/// Implementation for Win32 based on ReadDirectoryChangesW. /// Implementation for Win32 based on ReadDirectoryChangesW.
/// @class FileWatcherWin32 /// @class FileWatcherWin32
class FileWatcherWin32 : public FileWatcherImpl { class FileWatcherWin32 : public FileWatcherImpl {
public: public:
/// type for a map from WatchID to WatcherWin32 pointer /// type for a map from WatchID to WatcherWin32 pointer
typedef std::unordered_set<WatcherStructWin32*> Watches; typedef std::unordered_set<WatcherStructWin32*> Watches;
FileWatcherWin32( FileWatcher* parent ); FileWatcherWin32( FileWatcher* parent );
virtual ~FileWatcherWin32(); virtual ~FileWatcherWin32();
/// Add a directory watch /// Add a directory watch
/// On error returns WatchID with Error type. /// On error returns WatchID with Error type.
WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive,
const std::vector<WatcherOption> &options ) override; const std::vector<WatcherOption> &options ) override;
/// Remove a directory watch. This is a brute force lazy search O(nlogn). /// Remove a directory watch. This is a brute force lazy search O(nlogn).
void removeWatch( const std::string& directory ) override; void removeWatch( const std::string& directory ) override;
/// Remove a directory watch. This is a map lookup O(logn). /// Remove a directory watch. This is a map lookup O(logn).
void removeWatch( WatchID watchid ) override; void removeWatch( WatchID watchid ) override;
/// Updates the watcher. Must be called often. /// Updates the watcher. Must be called often.
void watch() override; void watch() override;
/// Handles the action /// Handles the action
void handleAction( Watcher* watch, const std::string& filename, unsigned long action, void handleAction( Watcher* watch, const std::string& filename, unsigned long action,
std::string oldFilename = "" ) override; std::string oldFilename = "" ) override;
/// @return Returns a list of the directories that are being watched /// @return Returns a list of the directories that are being watched
std::vector<std::string> directories() override; std::vector<std::string> directories() override;
protected: protected:
HANDLE mIOCP; HANDLE mIOCP;
Watches mWatches; Watches mWatches;
/// The last watchid /// The last watchid
WatchID mLastWatchID; WatchID mLastWatchID;
Thread* mThread; Thread* mThread;
Mutex mWatchesLock; Mutex mWatchesLock;
bool pathInWatches( const std::string& path ) override; bool pathInWatches( const std::string& path ) override;
/// Remove all directory watches. /// Remove all directory watches.
void removeAllWatches(); void removeAllWatches();
void removeWatch( WatcherStructWin32* watch ); void removeWatch( WatcherStructWin32* watch );
private: private:
void run(); void run();
}; };
} // namespace efsw } // namespace efsw
#endif #endif
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,147 +1,147 @@
/* sophist.h - 0.3 - public domain - Sean Barrett 2010 /* sophist.h - 0.3 - public domain - Sean Barrett 2010
** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net ** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net
** Sophist provides portable types; you typedef/#define them to your own names ** Sophist provides portable types; you typedef/#define them to your own names
** **
** defines: ** defines:
** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian ** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian
** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined ** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined
** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit ** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit
** **
** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer ** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer
** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16 ** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16
** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64 ** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64
** - SOPHIST_int64_constant(number) - macros for creating 64-bit ** - SOPHIST_int64_constant(number) - macros for creating 64-bit
** - SOPHIST_uint64_constant(number) integer constants ** - SOPHIST_uint64_constant(number) integer constants
** - SOPHIST_printf_format64 - string for printf format for int64 ** - SOPHIST_printf_format64 - string for printf format for int64
*/ */
#ifndef __INCLUDE_SOPHIST_H__ #ifndef __INCLUDE_SOPHIST_H__
#define __INCLUDE_SOPHIST_H__ #define __INCLUDE_SOPHIST_H__
#define SOPHIST_compiletime_assert(name,val) \ #define SOPHIST_compiletime_assert(name,val) \
typedef int SOPHIST__assert##name[(val) ? 1 : -1] typedef int SOPHIST__assert##name[(val) ? 1 : -1]
/* define a couple synthetic rules to make code more readable */ /* define a couple synthetic rules to make code more readable */
#if (defined(__sparc__) || defined(__sparc)) && \ #if (defined(__sparc__) || defined(__sparc)) && \
(defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)) (defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__))
#define SOPHIST_sparc64 #define SOPHIST_sparc64
#endif #endif
#if (defined(linux) || defined(__linux__)) && \ #if (defined(linux) || defined(__linux__)) && \
(defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64)) (defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64))
#define SOPHIST_linux64 #define SOPHIST_linux64
#endif #endif
/* basic types */ /* basic types */
typedef signed char SOPHIST_int8; typedef signed char SOPHIST_int8;
typedef unsigned char SOPHIST_uint8; typedef unsigned char SOPHIST_uint8;
typedef signed short SOPHIST_int16; typedef signed short SOPHIST_int16;
typedef unsigned short SOPHIST_uint16; typedef unsigned short SOPHIST_uint16;
#ifdef __palmos__ #ifdef __palmos__
typedef signed long SOPHIST_int32; typedef signed long SOPHIST_int32;
typedef unsigned long SOPHIST_uint32; typedef unsigned long SOPHIST_uint32;
#else #else
typedef signed int SOPHIST_int32; typedef signed int SOPHIST_int32;
typedef unsigned int SOPHIST_uint32; typedef unsigned int SOPHIST_uint32;
#endif #endif
#ifndef SOPHIST_NO_64 #ifndef SOPHIST_NO_64
#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \
|| (defined(__alpha) && defined(__DECC)) || (defined(__alpha) && defined(__DECC))
typedef signed __int64 SOPHIST_int64; typedef signed __int64 SOPHIST_int64;
typedef unsigned __int64 SOPHIST_uint64; typedef unsigned __int64 SOPHIST_uint64;
#define SOPHIST_has_64 1 #define SOPHIST_has_64 1
#define SOPHIST_int64_constant(x) (x##i64) #define SOPHIST_int64_constant(x) (x##i64)
#define SOPHIST_uint64_constant(x) (x##ui64) #define SOPHIST_uint64_constant(x) (x##ui64)
#define SOPHIST_printf_format64 "I64" #define SOPHIST_printf_format64 "I64"
#elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64)
typedef signed long SOPHIST_int64; typedef signed long SOPHIST_int64;
typedef unsigned long SOPHIST_uint64; typedef unsigned long SOPHIST_uint64;
#define SOPHIST_has_64 1 #define SOPHIST_has_64 1
#define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x)
#define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x)
#define SOPHIST_printf_format64 "l" #define SOPHIST_printf_format64 "l"
#elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \
|| defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \
|| defined(sgi) || defined (__sgi) || defined(__sgi__) \ || defined(sgi) || defined (__sgi) || defined(__sgi__) \
|| defined(_CRAYC) || defined(_CRAYC)
typedef signed long long SOPHIST_int64; typedef signed long long SOPHIST_int64;
typedef unsigned long long SOPHIST_uint64; typedef unsigned long long SOPHIST_uint64;
#define SOPHIST_has_64 1 #define SOPHIST_has_64 1
#define SOPHIST_int64_constant(x) (x##LL) #define SOPHIST_int64_constant(x) (x##LL)
#define SOPHIST_uint64_constant(x) (x##ULL) #define SOPHIST_uint64_constant(x) (x##ULL)
#define SOPHIST_printf_format64 "ll" #define SOPHIST_printf_format64 "ll"
#endif #endif
#endif #endif
#ifndef SOPHIST_has_64 #ifndef SOPHIST_has_64
#define SOPHIST_has_64 0 #define SOPHIST_has_64 0
#endif #endif
SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1); SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1);
SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2); SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2);
SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4); SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4);
SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4); SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4);
#if SOPHIST_has_64 #if SOPHIST_has_64
SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8); SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8);
SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8); SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8);
#endif #endif
/* determine whether pointers are 64-bit */ /* determine whether pointers are 64-bit */
#if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \ #if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \
|| defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \ || defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \
|| defined(__64BIT__) \ || defined(__64BIT__) \
|| defined(__LP64) || defined(__LP64__) || defined(_LP64) \ || defined(__LP64) || defined(__LP64__) || defined(_LP64) \
|| defined(_ADDR64) || defined(_CRAYC) \ || defined(_ADDR64) || defined(_CRAYC) \
#define SOPHIST_pointer64 1 #define SOPHIST_pointer64 1
SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8); SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8);
typedef SOPHIST_int64 SOPHIST_intptr; typedef SOPHIST_int64 SOPHIST_intptr;
typedef SOPHIST_uint64 SOPHIST_uintptr; typedef SOPHIST_uint64 SOPHIST_uintptr;
#else #else
#define SOPHIST_pointer64 0 #define SOPHIST_pointer64 0
SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4); SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4);
/* do we care about pointers that are only 16-bit? */ /* do we care about pointers that are only 16-bit? */
typedef SOPHIST_int32 SOPHIST_intptr; typedef SOPHIST_int32 SOPHIST_intptr;
typedef SOPHIST_uint32 SOPHIST_uintptr; typedef SOPHIST_uint32 SOPHIST_uintptr;
#endif #endif
SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *)); SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *));
/* enumerate known little endian cases; fallback to big-endian */ /* enumerate known little endian cases; fallback to big-endian */
#define SOPHIST_little_endian 1 #define SOPHIST_little_endian 1
#define SOPHIST_big_endian 2 #define SOPHIST_big_endian 2
#if defined(__386__) || defined(i386) || defined(__i386__) \ #if defined(__386__) || defined(i386) || defined(__i386__) \
|| defined(__X86) || defined(_M_IX86) \ || defined(__X86) || defined(_M_IX86) \
|| defined(_M_X64) || defined(__x86_64__) \ || defined(_M_X64) || defined(__x86_64__) \
|| defined(alpha) || defined(__alpha) || defined(__alpha__) \ || defined(alpha) || defined(__alpha) || defined(__alpha__) \
|| defined(_M_ALPHA) \ || defined(_M_ALPHA) \
|| defined(ARM) || defined(_ARM) || defined(__arm__) \ || defined(ARM) || defined(_ARM) || defined(__arm__) \
|| defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|| defined(_WIN32_WCE) || defined(__NT__) \ || defined(_WIN32_WCE) || defined(__NT__) \
|| defined(__MIPSEL__) || defined(__MIPSEL__)
#define SOPHIST_endian SOPHIST_little_endian #define SOPHIST_endian SOPHIST_little_endian
#else #else
#define SOPHIST_endian SOPHIST_big_endian #define SOPHIST_endian SOPHIST_big_endian
#endif #endif
#endif /* __INCLUDE_SOPHIST_H__ */ #endif /* __INCLUDE_SOPHIST_H__ */

View File

@ -0,0 +1,139 @@
#include <efsw/FileSystem.hpp>
#include <efsw/System.hpp>
#include <efsw/efsw.hpp>
#include <iostream>
#include <signal.h>
bool STOP = false;
void sigend( int ) {
std::cout << std::endl << "Bye bye" << std::endl;
STOP = true;
}
/// Processes a file action
class UpdateListener : public efsw::FileWatchListener {
public:
UpdateListener() {}
std::string getActionName( efsw::Action action ) {
switch ( action ) {
case efsw::Actions::Add:
return "Add";
case efsw::Actions::Modified:
return "Modified";
case efsw::Actions::Delete:
return "Delete";
case efsw::Actions::Moved:
return "Moved";
default:
return "Bad Action";
}
}
void handleFileAction( efsw::WatchID watchid, const std::string& dir,
const std::string& filename, efsw::Action action,
std::string oldFilename = "" ) override {
std::cout << "Watch ID " << watchid << " DIR ("
<< dir + ") FILE (" +
( oldFilename.empty() ? "" : "from file " + oldFilename + " to " ) +
filename + ") has event "
<< getActionName( action ) << std::endl;
}
};
efsw::WatchID handleWatchID( efsw::WatchID watchid ) {
switch ( watchid ) {
case efsw::Errors::FileNotFound:
case efsw::Errors::FileRepeated:
case efsw::Errors::FileOutOfScope:
case efsw::Errors::FileRemote:
case efsw::Errors::WatcherFailed:
case efsw::Errors::Unspecified: {
std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
break;
}
default: {
std::cout << "Added WatchID: " << watchid << std::endl;
}
}
return watchid;
}
int main( int argc, char** argv ) {
signal( SIGABRT, sigend );
signal( SIGINT, sigend );
signal( SIGTERM, sigend );
std::cout << "Press ^C to exit demo" << std::endl;
bool commonTest = true;
bool useGeneric = false;
std::string path;
if ( argc >= 2 ) {
path = std::string( argv[1] );
if ( efsw::FileSystem::isDirectory( path ) ) {
commonTest = false;
}
if ( argc >= 3 ) {
if ( std::string( argv[2] ) == "true" ) {
useGeneric = true;
}
}
}
UpdateListener* ul = new UpdateListener();
/// create the file watcher object
efsw::FileWatcher fileWatcher( useGeneric );
fileWatcher.followSymlinks( false );
fileWatcher.allowOutOfScopeLinks( false );
if ( commonTest ) {
std::string CurPath( efsw::System::getProcessPath() );
std::cout << "CurPath: " << CurPath.c_str() << std::endl;
/// starts watching
fileWatcher.watch();
/// add a watch to the system
handleWatchID( fileWatcher.addWatch( CurPath + "test", ul, true ) );
/// adds another watch after started watching...
efsw::System::sleep( 100 );
efsw::WatchID watchID =
handleWatchID( fileWatcher.addWatch( CurPath + "test2", ul, true ) );
/// delete the watch
if ( watchID > 0 ) {
efsw::System::sleep( 1000 );
fileWatcher.removeWatch( watchID );
}
} else {
if ( fileWatcher.addWatch( path, ul, true ) > 0 ) {
fileWatcher.watch();
std::cout << "Watching directory: " << path.c_str() << std::endl;
if ( useGeneric ) {
std::cout << "Using generic backend watcher" << std::endl;
}
} else {
std::cout << "Error trying to watch directory: " << path.c_str() << std::endl;
std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
}
}
while ( !STOP ) {
efsw::System::sleep( 100 );
}
return 0;
}