diff options
78 files changed, 4670 insertions, 5291 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt index a90a5b78584..ecb19b5b6f8 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -8,9 +8,9 @@ Boost Process (Proposed for boost, but its not an official part of it yet. Used http://www.highscore.de/boost/process0.5/ Version: 0.5 -efws (Entropia File System Watcher - crossplatform file system watcher) - https://bitbucket.org/SpartanJ/efsw - Version: 1.0.0 e6afbec564e249771046c714b0c7f2154e4c7fef +efsw (Entropia File System Watcher - crossplatform file system watcher) + https://github.com/SpartanJ/efsw + Version: 1.3.1+ 36c1c7004a34b6f40719f0830bcfb10325415451 fmt (a small, safe and fast formatting library) https://github.com/fmtlib/fmt diff --git a/dep/efsw/.hg_archival.txt b/dep/efsw/.hg_archival.txt deleted file mode 100644 index f590482107c..00000000000 --- a/dep/efsw/.hg_archival.txt +++ /dev/null @@ -1,6 +0,0 @@ -repo: 78c2ea8c48b213ee0078d6326a1dd719d0844764 -node: e6afbec564e249771046c714b0c7f2154e4c7fef -branch: default -latesttag: 1.0.0 -latesttagdistance: 12 -changessincelatesttag: 12 diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt index 03f6c153115..9817525931c 100644 --- a/dep/efsw/CMakeLists.txt +++ b/dep/efsw/CMakeLists.txt @@ -1,68 +1,109 @@ if (BUILD_SHARED_LIBS) - set(SRCS + set(EFSW_CPP_SOURCE + src/efsw/Atomic.hpp + src/efsw/base.hpp src/efsw/Debug.cpp + src/efsw/Debug.hpp src/efsw/DirectorySnapshot.cpp + src/efsw/DirectorySnapshot.hpp src/efsw/DirectorySnapshotDiff.cpp + src/efsw/DirectorySnapshotDiff.hpp src/efsw/DirWatcherGeneric.cpp + src/efsw/DirWatcherGeneric.hpp src/efsw/FileInfo.cpp + src/efsw/FileInfo.hpp src/efsw/FileSystem.cpp + src/efsw/FileSystem.hpp src/efsw/FileWatcher.cpp src/efsw/FileWatcherCWrapper.cpp src/efsw/FileWatcherGeneric.cpp + src/efsw/FileWatcherGeneric.hpp src/efsw/FileWatcherImpl.cpp + src/efsw/FileWatcherImpl.hpp + src/efsw/Lock.hpp src/efsw/Log.cpp src/efsw/Mutex.cpp + src/efsw/Mutex.hpp + src/efsw/sophist.h src/efsw/String.cpp + src/efsw/String.hpp src/efsw/System.cpp + src/efsw/System.hpp src/efsw/Thread.cpp + src/efsw/Thread.hpp + src/efsw/Utf.hpp src/efsw/Watcher.cpp - src/efsw/WatcherGeneric.cpp) + src/efsw/Watcher.hpp + src/efsw/WatcherGeneric.cpp + src/efsw/WatcherGeneric.hpp + src/efsw/platform/platformimpl.hpp + ) if (WIN32) - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/platform/win/FileSystemImpl.cpp + src/efsw/platform/win/FileSystemImpl.hpp src/efsw/platform/win/MutexImpl.cpp + src/efsw/platform/win/MutexImpl.hpp src/efsw/platform/win/SystemImpl.cpp - src/efsw/platform/win/ThreadImpl.cpp) + src/efsw/platform/win/SystemImpl.hpp + src/efsw/platform/win/ThreadImpl.cpp + src/efsw/platform/win/ThreadImpl.hpp) else () - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/platform/posix/FileSystemImpl.cpp + src/efsw/platform/posix/FileSystemImpl.hpp src/efsw/platform/posix/MutexImpl.cpp + src/efsw/platform/posix/MutexImpl.hpp src/efsw/platform/posix/SystemImpl.cpp - src/efsw/platform/posix/ThreadImpl.cpp) + src/efsw/platform/posix/SystemImpl.hpp + src/efsw/platform/posix/ThreadImpl.cpp + src/efsw/platform/posix/ThreadImpl.hpp) endif() if (APPLE) - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/FileWatcherFSEvents.cpp + src/efsw/FileWatcherFSEvents.hpp src/efsw/FileWatcherKqueue.cpp + src/efsw/FileWatcherKqueue.hpp src/efsw/WatcherFSEvents.cpp - src/efsw/WatcherKqueue.cpp) - - exec_program(uname ARGS -v OUTPUT_VARIABLE OSX_VERSION) - string(REGEX MATCH "[0-9]+" OSX_VERSION ${OSX_VERSION}) - if (NOT OSX_VERSION GREATER 9) - set(OPTIONAL_COMPILE_DEFINITIONS "-DEFSW_FSEVENTS_NOT_SUPPORTED") - endif() + src/efsw/WatcherFSEvents.hpp + src/efsw/WatcherKqueue.cpp + src/efsw/WatcherKqueue.hpp) set(OPTIONAL_LINK_LIBRARIES "-framework CoreFoundation" "-framework CoreServices") elseif (WIN32) - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/FileWatcherWin32.cpp - src/efsw/WatcherWin32.cpp) + src/efsw/FileWatcherWin32.hpp + src/efsw/WatcherWin32.cpp + src/efsw/WatcherWin32.hpp) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/FileWatcherInotify.cpp - src/efsw/WatcherInotify.cpp) - if (NOT EXISTS "/usr/include/sys/inotify.h" AND NOT EXISTS "/usr/local/include/sys/inotify.h") + src/efsw/FileWatcherInotify.hpp + src/efsw/WatcherInotify.cpp + src/efsw/WatcherInotify.hpp) + find_path(EFSW_INOTIFY_H + NAMES + sys/inotify.h + NO_CACHE + ) + if (EFSW_INOTIFY_H STREQUAL "EFSW_INOTIFY_H-NOTFOUND") + list (APPEND EFSW_CPP_SOURCE + src/efsw/inotify-nosys.h + ) set(OPTIONAL_COMPILE_DEFINITIONS "-DEFSW_INOTIFY_NOSYS") endif() elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - list (APPEND SRCS + list (APPEND EFSW_CPP_SOURCE src/efsw/FileWatcherKqueue.cpp - src/efsw/WatcherKqueue.cpp) + src/efsw/FileWatcherKqueue.hpp + src/efsw/WatcherKqueue.cpp + src/efsw/WatcherKqueue.hpp) endif() - add_library(efsw STATIC ${SRCS}) + add_library(efsw STATIC ${EFSW_CPP_SOURCE}) target_include_directories(efsw PUBLIC diff --git a/dep/efsw/LICENSE b/dep/efsw/LICENSE index ac8ac28988d..37f354a1952 100644 --- a/dep/efsw/LICENSE +++ b/dep/efsw/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012 Martín Lucas Golini +Copyright (c) 2020 Martín Lucas Golini Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,4 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) -http://code.google.com/p/simplefilewatcher/ also MIT licensed.
\ No newline at end of file +http://code.google.com/p/simplefilewatcher/ also MIT licensed. diff --git a/dep/efsw/README.md b/dep/efsw/README.md index f653088d575..1c719403005 100644 --- a/dep/efsw/README.md +++ b/dep/efsw/README.md @@ -1,5 +1,8 @@ -Entropia File System Watcher +Entropia File System Watcher  ============================ + +[](https://github.com/SpartanJ/efsw/actions?query=workflow%3Abuild) + **efsw** is a C++ cross-platform file system watcher and notifier. **efsw** monitors the file system asynchronously for changes to files and directories by watching a list of specified paths, and raises events when a directory or file change. @@ -19,8 +22,8 @@ Entropia File System Watcher * OS-independent generic watcher (polling the disk for directory snapshots and comparing them periodically) -If any of the backend fails to start by any reason, it will fallback to the OS-independent implementation. -This should never happen, except for the Kqueue implementation, see `Platform limitations and clarifications`. +If any of the backend fails to start for any reason, it will fallback to the OS-independent implementation. +This should never happen, except for the Kqueue implementation; see `Platform limitations and clarifications`. **Code License** -------------- @@ -31,39 +34,41 @@ This should never happen, except for the Kqueue implementation, see `Platform li ```c++ // Inherits from the abstract listener class, and implements the the file action handler -class UpdateListener : public efsw::FileWatchListener -{ -public: - UpdateListener() {} - - void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" ) - { - switch( action ) - { - case efsw::Actions::Add: - std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Added" << std::endl; - break; - case efsw::Actions::Delete: - std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Delete" << std::endl; - break; - case efsw::Actions::Modified: - std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Modified" << std::endl; - break; - case efsw::Actions::Moved: - std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Moved from (" << oldFilename << ")" << std::endl; - break; - default: - std::cout << "Should never happen!" << std::endl; - } - } +class UpdateListener : public efsw::FileWatchListener { + public: + void handleFileAction( efsw::WatchID watchid, const std::string& dir, + const std::string& filename, efsw::Action action, + std::string oldFilename ) override { + switch ( action ) { + case efsw::Actions::Add: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Added" + << std::endl; + break; + case efsw::Actions::Delete: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Delete" + << std::endl; + break; + case efsw::Actions::Modified: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Modified" + << std::endl; + break; + case efsw::Actions::Moved: + std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Moved from (" + << oldFilename << ")" << std::endl; + break; + default: + std::cout << "Should never happen!" << std::endl; + } + } }; // Create the file system watcher instance -// efsw::FileWatcher allow a first boolean parameter that indicates if it should start with the generic file watcher instead of the platform specific backend -efsw::FileWatcher * fileWatcher = new efsw::FileWatcher(); +// efsw::FileWatcher allow a first boolean parameter that indicates if it should start with the +// generic file watcher instead of the platform specific backend +efsw::FileWatcher* fileWatcher = new efsw::FileWatcher(); // Create the instance of your efsw::FileWatcherListener implementation -UpdateListener * listener = new UpdateListener(); +UpdateListener* listener = new UpdateListener(); // Add a folder to watch, and get the efsw::WatchID // It will watch the /tmp folder recursively ( the third parameter indicates that is recursive ) @@ -73,11 +78,16 @@ efsw::WatchID watchID = fileWatcher->addWatch( "/tmp", listener, true ); // Adds another directory to watch. This time as non-recursive. efsw::WatchID watchID2 = fileWatcher->addWatch( "/usr", listener, false ); +// For Windows, adds another watch, specifying to use a bigger buffer, to not miss events +// (do not use for network locations, see efsw.hpp for details). +efsw::WatchID watchID3 = fileWatcher->addWatch( "c:\\temp", listener, true, { (BufferSize, 128*1024) } ); + // Start watching asynchronously the directories fileWatcher->watch(); // Remove the second watcher added -// You can also call removeWatch by passing the watch path ( it must end with an slash or backslash in windows, since that's how internally it's saved ) +// You can also call removeWatch by passing the watch path ( it must end with an slash or backslash +// in windows, since that's how internally it's saved ) fileWatcher->removeWatch( watchID2 ); ``` @@ -87,21 +97,21 @@ None :) **Compiling** ------------ -To generate project files you will need to [download and install](http://industriousone.com/premake/download) [Premake](http://industriousone.com/what-premake) +To generate project files you will need to [download and install](https://premake.github.io/download) [Premake](https://premake.github.io/docs/What-Is-Premake) -Then you can generate the project for your platform just going to the project directory where the premake4.lua file is located and then execute: +Then you can generate the project for your platform by just going to the project directory where the premake4.lua file is located and executing: -`premake4 gmake` to generate project Makefiles, then `cd make/*YOURPLATFORM*/`, and finally `make` or `make config=release` ( it will generate the static lib, the shared lib and the test application ). +`premake5 gmake2` to generate project Makefiles, then `cd make/*YOURPLATFORM*/`, and finally `make` or `make config=release_x86_64` ( it will generate the static lib, the shared lib and the test application ). -or +or -`premake4 vs2010` to generate Visual Studio 2010 project. +`premake5 vs2022` to generate Visual Studio 2022 project. or -`premake4 xcode4` to generate Xcode 4 project. +`premake5 xcode4` to generate Xcode 4 project. -There is also a cmake file that i don't oficially support but it works just fine, provided by [Mohammed Nafees](https://bitbucket.org/binaryking). +There is also a cmake file that I don't officially support but it works just fine, provided by [Mohammed Nafees](https://github.com/mnafees) and improved by [Eugene Shalygin](https://github.com/zeule). **Platform limitations and clarifications** ------------------------------------------- @@ -112,21 +122,21 @@ handleFileAction returns UTF-8 strings in all platforms. Windows and FSEvents Mac OS X implementation can't follow symlinks ( it will ignore followSymlinks() and allowOutOfScopeLinks() ). -Kqueue implementation is limited by the maximun number of file descriptors allowed per process by the OS, in the case of reaching the file descriptors limit ( in BSD around 18000 and in OS X around 10240 ) it will fallback to the generic file watcher. +Kqueue implementation is limited by the maximum number of file descriptors allowed per process by the OS. In the case of reaching the file descriptors limit ( in BSD around 18000 and in OS X around 10240 ), it will fallback to the generic file watcher. -OS X will only use Kqueue if OS X version is below to 10.5, and this implementation needs to be compiled separately from the OS X >= 10.5 implementation. Since there's no way to compile FSEvents backend in OS X below 10.5. +OS X will use only Kqueue if the OS X version is below 10.5. This implementation needs to be compiled separately from the OS X >= 10.5 implementation, since there's no way to compile FSEvents backend in OS X below 10.5. -FSEvents for OS X Lion and beyond in some cases will generate more actions that in reality ocurred, since fine-grained implementation of FSEvents doesn't give the order of the actions retrieved, in some cases i need to guess/aproximate the order of them. +FSEvents for OS X Lion and beyond in some cases will generate more actions than in reality ocurred, since fine-grained implementation of FSEvents doesn't give the order of the actions retrieved. In some cases I need to guess/approximate the order of them. Generic watcher relies on the inode information to detect file and directories renames/move. Since Windows has no concept of inodes as Unix platforms do, there is no current reliable way of determining file/directory movement on Windows without help from the Windows API ( this is replaced with Add/Delete events ). -Linux versions below 2.6.13 are not supported, since inotify wasn't implemented yet. I'm not interested in support older kernels, since i don't see the point. If someone needs this open an issue in the issue tracker and i may consider implenent a dnotify backend. +Linux versions below 2.6.13 are not supported, since inotify wasn't implemented yet. I'm not interested in supporting older kernels, since I don't see the point. If someone needs this, open an issue in the issue tracker and I may consider implementing a dnotify backend. -OS-independent watcher, Kqueue and FSEvents for OS X below 10.5 keep cache of the directories structures, to be able to detect changes in the directories. This means that there's a memory overhead for this backends. +OS-independent watcher, Kqueue and FSEvents for OS X below 10.5 keep cache of the directories structures, to be able to detect changes in the directories. This means that there's a memory overhead for these backends. **Useful information** -------------------- -The project also comes with a C API wrapper, contributed by [Sepul Sepehr Taghdisian](https://bitbucket.org/sepul). +The project also comes with a C API wrapper, contributed by [Sepul Sepehr Taghdisian](https://github.com/septag). There's a string manipulation class not exposed in the efsw header ( efsw::String ) that can be used to make string encoding conversion. diff --git a/dep/efsw/include/efsw/efsw.h b/dep/efsw/include/efsw/efsw.h index 28e63e2139e..ecb9ec41c26 100644 --- a/dep/efsw/include/efsw/efsw.h +++ b/dep/efsw/include/efsw/efsw.h @@ -80,7 +80,22 @@ enum efsw_error EFSW_OUTOFSCOPE = -3, EFSW_NOTREADABLE = -4, EFSW_REMOTE = -5, - EFSW_UNSPECIFIED = -6 + EFSW_WATCHER_FAILED = -6, + EFSW_UNSPECIFIED = -7 +}; + +enum efsw_option +{ + /// 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 + /// 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 + /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) + EFSW_OPT_WIN_BUFFER_SIZE = 1, + /// 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 + /// FILE_NOTIFY_CHANGE_* flags. + EFSW_OPT_WIN_NOTIFY_FILTER = 2 }; /// Basic interface for listening for file events. @@ -94,6 +109,11 @@ typedef void (*efsw_pfn_fileaction_callback) ( void* param ); +typedef struct { + enum efsw_option option; + int value; +} efsw_watcher_option; + /** * Creates a new file-watcher * @param generic_mode Force the use of the Generic file watcher @@ -103,15 +123,24 @@ efsw_watcher EFSW_API efsw_create(int generic_mode); /// Release the file-watcher and unwatch any directories void EFSW_API efsw_release(efsw_watcher watcher); -/// Retreive last error occured by file-watcher +/// Retrieve last error occured by file-watcher EFSW_API const char* efsw_getlasterror(); -/// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. -/// For backwards compatibility. +/// Reset file-watcher last error +EFSW_API void efsw_clearlasterror(); + +/// Add a directory watch /// On error returns WatchID with Error type. efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory, efsw_pfn_fileaction_callback callback_fn, int recursive, void* param); +/// Add a directory watch, specifying options +/// @param options Pointer to an array of watcher options +/// @param nr_options Number of options referenced by \p options +efsw_watchid EFSW_API efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory, + efsw_pfn_fileaction_callback callback_fn, int recursive, efsw_watcher_option *options, + int options_number, void* param); + /// Remove a directory watch. This is a brute force search O(nlogn). void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory); diff --git a/dep/efsw/include/efsw/efsw.hpp b/dep/efsw/include/efsw/efsw.hpp index 72ae1a61d7c..cb78ef3797f 100644 --- a/dep/efsw/include/efsw/efsw.hpp +++ b/dep/efsw/include/efsw/efsw.hpp @@ -28,34 +28,37 @@ #ifndef ESFW_HPP #define ESFW_HPP +#include <vector> #include <string> -#include <list> - -#if defined(_WIN32) - #ifdef EFSW_DYNAMIC - // Windows platforms - #ifdef EFSW_EXPORTS - // From DLL side, we must export - #define EFSW_API __declspec(dllexport) - #else - // From client application side, we must import - #define EFSW_API __declspec(dllimport) - #endif - #else - // No specific directive needed for static build - #ifndef EFSW_API - #define EFSW_API - #endif - #endif +#include <vector> + +#if defined( _WIN32 ) +#ifdef EFSW_DYNAMIC +// Windows platforms +#ifdef EFSW_EXPORTS +// From DLL side, we must export +#define EFSW_API __declspec( dllexport ) #else - #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) - #define EFSW_API __attribute__ ((visibility("default"))) - #endif - - // Other platforms don't need to define anything - #ifndef EFSW_API - #define EFSW_API - #endif +// From client application side, we must import +#define EFSW_API __declspec( dllimport ) +#endif +#else +// No specific directive needed for static build +#ifndef EFSW_API +#define EFSW_API +#endif +#endif +#else +#if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) +#ifndef EFSW_API +#define EFSW_API __attribute__( ( visibility( "default" ) ) ) +#endif +#endif + +// Other platforms don't need to define anything +#ifndef EFSW_API +#define EFSW_API +#endif #endif namespace efsw { @@ -66,128 +69,174 @@ typedef long WatchID; // forward declarations class FileWatcherImpl; class FileWatchListener; +class WatcherOption; /// Actions to listen for. Rename will send two events, one for /// the deletion of the old file, and one for the creation of the /// new file. namespace Actions { - enum Action - { - /// Sent when a file is created or renamed - Add = 1, - /// Sent when a file is deleted or renamed - Delete = 2, - /// Sent when a file is modified - Modified = 3, - /// Sent when a file is moved - Moved = 4 - }; +enum Action { + /// Sent when a file is created or renamed + Add = 1, + /// Sent when a file is deleted or renamed + Delete = 2, + /// Sent when a file is modified + Modified = 3, + /// Sent when a file is moved + Moved = 4 +}; } typedef Actions::Action Action; /// Errors log namespace namespace Errors { -enum Error -{ - FileNotFound = -1, - FileRepeated = -2, - FileOutOfScope = -3, - FileNotReadable = -4, - FileRemote = -5, /** Directory in remote file system ( create a generic FileWatcher instance to watch this directory ). */ - Unspecified = -6 +enum Error { + NoError = 0, + FileNotFound = -1, + FileRepeated = -2, + FileOutOfScope = -3, + FileNotReadable = -4, + /// Directory in remote file system + /// ( create a generic FileWatcher instance to watch this directory ). + FileRemote = -5, + /// File system watcher failed to watch for changes. + WatcherFailed = -6, + Unspecified = -7 }; -class EFSW_API Log -{ - public: - /// @return The last error logged - static std::string getLastErrorLog(); +class EFSW_API Log { + public: + /// @return The last error logged + static std::string getLastErrorLog(); + + /// @return The code of the last error logged + static Error getLastErrorCode(); + + /// Reset last error + static void clearLastError(); - /// Creates an error of the type specified - static Error createLastError( Error err, std::string log ); + /// Creates an error of the type specified + static Error createLastError( Error err, std::string log ); }; -} +} // namespace Errors typedef Errors::Error Error; +/// Optional file watcher settings. +namespace Options { +enum Option { + /// 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 + /// 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 + /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) + WinBufferSize = 1, + /// 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 + /// FILE_NOTIFY_CHANGE_* flags. + WinNotifyFilter = 2 +}; +} +typedef Options::Option Option; + /// Listens to files and directories and dispatches events /// to notify the listener of files and directories changes. /// @class FileWatcher -class EFSW_API FileWatcher -{ - public: - /// Default constructor, will use the default platform file watcher - FileWatcher(); - - /// Constructor that lets you force the use of the Generic File Watcher - explicit FileWatcher( bool useGenericFileWatcher ); - - virtual ~FileWatcher(); - - /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. - /// For backwards compatibility. - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher); - - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); - - /// Remove a directory watch. This is a brute force search O(nlogn). - void removeWatch(const std::string& directory); - - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); - - /// Starts watching ( in other thread ) - void watch(); - - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - - /** Allow recursive watchers to follow symbolic links to other directories - * followSymlinks is disabled by default - */ - void followSymlinks( bool follow ); - - /** @return If can follow symbolic links to directorioes */ - const bool& followSymlinks() const; - - /** When enable this it will allow symlinks to watch recursively out of the pointed directory. - * follorSymlinks must be enabled to this work. - * 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 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 this behavior. - * allowOutOfScopeLinks are disabled by default. - */ - void allowOutOfScopeLinks( bool allow ); - - /// @return Returns if out of scope links are allowed - const bool& allowOutOfScopeLinks() const; - private: - /// The implementation - FileWatcherImpl * mImpl; - bool mFollowSymlinks; - bool mOutOfScopeLinks; +class EFSW_API FileWatcher { + public: + /// Default constructor, will use the default platform file watcher + FileWatcher(); + + /// Constructor that lets you force the use of the Generic File Watcher + explicit FileWatcher( bool useGenericFileWatcher ); + + virtual ~FileWatcher(); + + /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. + /// For backwards compatibility. + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher ); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); + + /// Add a directory watch, allowing customization with options + /// @param directory The folder to be watched + /// @param watcher The listener to receive events + /// @param recursive Set this to true to include subdirectories + /// @param options Allows customization of a watcher + /// @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, + const std::vector<WatcherOption> &options ); + + /// Remove a directory watch. This is a brute force search O(nlogn). + void removeWatch( const std::string& directory ); + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ); + + /// Starts watching ( in other thread ) + void watch(); + + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories(); + + /** Allow recursive watchers to follow symbolic links to other directories + * followSymlinks is disabled by default + */ + void followSymlinks( bool follow ); + + /** @return If can follow symbolic links to directorioes */ + const bool& followSymlinks() const; + + /** When enable this it will allow symlinks to watch recursively out of the pointed directory. + * follorSymlinks must be enabled to this work. + * 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 + * 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 + * this behavior. allowOutOfScopeLinks are disabled by default. + */ + void allowOutOfScopeLinks( bool allow ); + + /// @return Returns if out of scope links are allowed + const bool& allowOutOfScopeLinks() const; + + private: + /// The implementation + FileWatcherImpl* mImpl; + bool mFollowSymlinks; + bool mOutOfScopeLinks; }; /// Basic interface for listening for file events. /// @class FileWatchListener -class FileWatchListener -{ - public: - /// Handles the action file action - /// @param watchid The watch id for the directory - /// @param dir The directory - /// @param filename The filename that was accessed (not full path) - /// @param action Action that was performed - /// @param oldFilename The name of the file or directory moved - virtual void handleFileAction(WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" ) = 0; +class FileWatchListener { + public: + virtual ~FileWatchListener() {} + + /// Handles the action file action + /// @param watchid The watch id for the directory + /// @param dir The directory + /// @param filename The filename that was accessed (not full path) + /// @param action Action that was performed + /// @param oldFilename The name of the file or directory moved + virtual void handleFileAction( WatchID watchid, const std::string& dir, + const std::string& filename, Action action, + std::string oldFilename = "" ) = 0; +}; +/// Optional, typically platform specific parameter for customization of a watcher. +/// @class WatcherOption +class WatcherOption { + public: + WatcherOption(Option option, int value) : mOption(option), mValue(value) {}; + Option mOption; + int mValue; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/Atomic.hpp b/dep/efsw/src/efsw/Atomic.hpp new file mode 100644 index 00000000000..9015c60038b --- /dev/null +++ b/dep/efsw/src/efsw/Atomic.hpp @@ -0,0 +1,33 @@ +#ifndef EFSW_ATOMIC_BOOL_HPP +#define EFSW_ATOMIC_BOOL_HPP + +#include <efsw/base.hpp> + +#include <atomic> + +namespace efsw { + +template <typename T> class Atomic { + public: + explicit Atomic( T set = false ) : set_( set ) {} + + Atomic& operator=( T set ) { + set_.store( set, std::memory_order_release ); + return *this; + } + + explicit operator T() const { + return set_.load( std::memory_order_acquire ); + } + + T load() const { + return set_.load( std::memory_order_acquire ); + } + + private: + std::atomic<T> set_; +}; + +} // namespace efsw + +#endif diff --git a/dep/efsw/src/efsw/Debug.cpp b/dep/efsw/src/efsw/Debug.cpp index 9c4ee02e5b6..18cfd315bdc 100644 --- a/dep/efsw/src/efsw/Debug.cpp +++ b/dep/efsw/src/efsw/Debug.cpp @@ -3,83 +3,79 @@ #ifdef EFSW_COMPILER_MSVC #define WIN32_LEAN_AND_MEAN -#include <windows.h> #include <crtdbg.h> +#include <windows.h> #endif #include <cassert> -#include <cstdio> #include <cstdarg> +#include <cstdio> namespace efsw { #ifdef DEBUG -void efREPORT_ASSERT( const char * File, int Line, const char * Exp ) -{ - #ifdef EFSW_COMPILER_MSVC - _CrtDbgReport( _CRT_ASSERT, File, Line, "", Exp); - - DebugBreak(); - #else - std::cout << "ASSERT: " << Exp << " file: " << File << " line: " << Line << std::endl; - - #if defined(EFSW_COMPILER_GCC) && defined(EFSW_32BIT) && !defined(EFSW_ARM) - asm("int3"); - #else - assert( false ); - #endif - #endif +void efREPORT_ASSERT( const char* File, int Line, const char* Exp ) { +#ifdef EFSW_COMPILER_MSVC + _CrtDbgReport( _CRT_ASSERT, File, Line, "", Exp ); + + DebugBreak(); +#else + std::cout << "ASSERT: " << Exp << " file: " << File << " line: " << Line << std::endl; + +#if defined( EFSW_COMPILER_GCC ) && defined( EFSW_32BIT ) && !defined( EFSW_ARM ) + asm( "int3" ); +#else + assert( false ); +#endif +#endif } -void efPRINT( const char * format, ... ) -{ - char buf[2048]; - va_list args; +void efPRINT( const char* format, ... ) { + char buf[2048]; + va_list args; va_start( args, format ); - #ifdef EFSW_COMPILER_MSVC - _vsnprintf_s( buf, sizeof( buf ), sizeof( buf ) / sizeof( buf[0]), format, args ); - #else - vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args ); - #endif +#ifdef EFSW_COMPILER_MSVC + _vsnprintf_s( buf, sizeof( buf ), sizeof( buf ) / sizeof( buf[0] ), format, args ); +#else + vsnprintf( buf, sizeof( buf ) / sizeof( buf[0] ), format, args ); +#endif va_end( args ); - #ifdef EFSW_COMPILER_MSVC - OutputDebugStringA( buf ); - #else - std::cout << buf; - #endif +#ifdef EFSW_COMPILER_MSVC + OutputDebugStringA( buf ); +#else + std::cout << buf; +#endif } -void efPRINTC( unsigned int cond, const char * format, ...) -{ +void efPRINTC( unsigned int cond, const char* format, ... ) { if ( 0 == cond ) return; - char buf[2048]; - va_list args; + char buf[2048]; + va_list args; va_start( args, format ); - #ifdef EFSW_COMPILER_MSVC - _vsnprintf_s( buf, efARRAY_SIZE( buf ), efARRAY_SIZE( buf ), format, args ); - #else - vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args ); - #endif +#ifdef EFSW_COMPILER_MSVC + _vsnprintf_s( buf, efARRAY_SIZE( buf ), efARRAY_SIZE( buf ), format, args ); +#else + vsnprintf( buf, sizeof( buf ) / sizeof( buf[0] ), format, args ); +#endif va_end( args ); - #ifdef EFSW_COMPILER_MSVC - OutputDebugStringA( buf ); - #else - std::cout << buf; - #endif +#ifdef EFSW_COMPILER_MSVC + OutputDebugStringA( buf ); +#else + std::cout << buf; +#endif } #endif -} - +} // namespace efsw diff --git a/dep/efsw/src/efsw/Debug.hpp b/dep/efsw/src/efsw/Debug.hpp index 75d6dce0466..78d35573b62 100644 --- a/dep/efsw/src/efsw/Debug.hpp +++ b/dep/efsw/src/efsw/Debug.hpp @@ -7,13 +7,19 @@ namespace efsw { #ifdef DEBUG -void efREPORT_ASSERT( const char * File, const int Line, const char * Exp ); +void efREPORT_ASSERT( const char* File, const int Line, const char* Exp ); -#define efASSERT( expr ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #expr ); } -#define efASSERTM( expr, msg ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #msg ); } +#define efASSERT( expr ) \ + if ( !( expr ) ) { \ + efREPORT_ASSERT( __FILE__, __LINE__, #expr ); \ + } +#define efASSERTM( expr, msg ) \ + if ( !( expr ) ) { \ + efREPORT_ASSERT( __FILE__, __LINE__, #msg ); \ + } -void efPRINT ( const char * format, ... ); -void efPRINTC ( unsigned int cond, const char * format, ... ); +void efPRINT( const char* format, ... ); +void efPRINTC( unsigned int cond, const char* format, ... ); #else @@ -21,30 +27,34 @@ void efPRINTC ( unsigned int cond, const char * format, ... ); #define efASSERTM( expr, msg ) #ifndef EFSW_COMPILER_MSVC - #define efPRINT( format, args... ) {} - #define efPRINTC( cond, format, args... ) {} +#define efPRINT( format, args... ) \ + {} +#define efPRINTC( cond, format, args... ) \ + {} #else - #define efPRINT - #define efPRINTC +#define efPRINT +#define efPRINTC #endif #endif #ifdef EFSW_VERBOSE - #define efDEBUG efPRINT - #define efDEBUGC efPRINTC +#define efDEBUG efPRINT +#define efDEBUGC efPRINTC #else - #ifndef EFSW_COMPILER_MSVC - #define efDEBUG( format, args... ) {} - #define efDEBUGC( cond, format, args... ) {} - #else - #define efDEBUG - #define efDEBUGC - #endif +#ifndef EFSW_COMPILER_MSVC +#define efDEBUG( format, args... ) \ + {} +#define efDEBUGC( cond, format, args... ) \ + {} +#else +#define efDEBUG +#define efDEBUGC +#endif #endif -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.cpp b/dep/efsw/src/efsw/DirWatcherGeneric.cpp index a5751148863..8b6bc8a99ab 100644 --- a/dep/efsw/src/efsw/DirWatcherGeneric.cpp +++ b/dep/efsw/src/efsw/DirWatcherGeneric.cpp @@ -1,67 +1,53 @@ +#include <efsw/Debug.hpp> #include <efsw/DirWatcherGeneric.hpp> #include <efsw/FileSystem.hpp> -#include <efsw/Debug.hpp> #include <efsw/String.hpp> namespace efsw { -DirWatcherGeneric::DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles ) : - Parent( parent ), - Watch( ws ), - Recursive( recursive ), - Deleted( false ) -{ +DirWatcherGeneric::DirWatcherGeneric( DirWatcherGeneric* parent, WatcherGeneric* ws, + const std::string& directory, bool recursive, + bool reportNewFiles ) : + Parent( parent ), Watch( ws ), Recursive( recursive ), Deleted( false ) { resetDirectory( directory ); - if ( !reportNewFiles ) - { + if ( !reportNewFiles ) { DirSnap.scan(); - } - else - { + } else { DirectorySnapshotDiff Diff = DirSnap.scan(); - if ( Diff.changed() ) - { + if ( Diff.changed() ) { FileInfoList::iterator it; - DiffIterator( FilesCreated ) - { + DiffIterator( FilesCreated ) { handleAction( ( *it ).Filepath, Actions::Add ); } } } } -DirWatcherGeneric::~DirWatcherGeneric() -{ +DirWatcherGeneric::~DirWatcherGeneric() { /// If the directory was deleted mark the files as deleted - if ( Deleted ) - { + if ( Deleted ) { DirectorySnapshotDiff Diff = DirSnap.scan(); - if ( !DirSnap.exists() ) - { + if ( !DirSnap.exists() ) { FileInfoList::iterator it; - DiffIterator( FilesDeleted ) - { - handleAction( (*it).Filepath, Actions::Delete ); + DiffIterator( FilesDeleted ) { + handleAction( ( *it ).Filepath, Actions::Delete ); } - DiffIterator( DirsDeleted ) - { - handleAction( (*it).Filepath, Actions::Delete ); + DiffIterator( DirsDeleted ) { + handleAction( ( *it ).Filepath, Actions::Delete ); } } } DirWatchMap::iterator it = Directories.begin(); - for ( ; it != Directories.end(); ++it ) - { - if ( Deleted ) - { + for ( ; it != Directories.end(); ++it ) { + if ( Deleted ) { /// If the directory was deleted, mark the flag for file deletion it->second->Deleted = true; } @@ -70,24 +56,22 @@ DirWatcherGeneric::~DirWatcherGeneric() } } -void DirWatcherGeneric::resetDirectory( std::string directory ) -{ +void DirWatcherGeneric::resetDirectory( std::string directory ) { std::string dir( directory ); /// Is this a recursive watch? - if ( Watch->Directory != directory ) - { - if ( !( directory.size() && ( directory.at(0) == FileSystem::getOSSlash() || directory.at( directory.size() - 1 ) == FileSystem::getOSSlash() ) ) ) - { + if ( Watch->Directory != directory ) { + if ( !( directory.size() && + ( directory.at( 0 ) == FileSystem::getOSSlash() || + directory.at( directory.size() - 1 ) == FileSystem::getOSSlash() ) ) ) { /// Get the real directory - if ( NULL != Parent ) - { - FileSystem::dirAddSlashAtEnd(directory); + if ( NULL != Parent ) { + std::string parentPath( Parent->DirSnap.DirectoryInfo.Filepath ); + FileSystem::dirAddSlashAtEnd( parentPath ); + FileSystem::dirAddSlashAtEnd( directory ); - dir = Parent->DirSnap.DirectoryInfo.Filepath + directory; - } - else - { + dir = parentPath + directory; + } else { efDEBUG( "resetDirectory(): Parent is NULL. Fatal error." ); } } @@ -96,161 +80,140 @@ void DirWatcherGeneric::resetDirectory( std::string directory ) DirSnap.setDirectoryInfo( dir ); } -void DirWatcherGeneric::handleAction( const std::string &filename, unsigned long action, std::string oldFilename) -{ - Watch->Listener->handleFileAction( Watch->ID, DirSnap.DirectoryInfo.Filepath, FileSystem::fileNameFromPath( filename ), (Action)action, oldFilename ); +void DirWatcherGeneric::handleAction( const std::string& filename, unsigned long action, + std::string oldFilename ) { + Watch->Listener->handleFileAction( Watch->ID, DirSnap.DirectoryInfo.Filepath, + FileSystem::fileNameFromPath( filename ), (Action)action, + oldFilename ); } -void DirWatcherGeneric::addChilds( bool reportNewFiles ) -{ - if ( Recursive ) - { +void DirWatcherGeneric::addChilds( bool reportNewFiles ) { + if ( Recursive ) { /// Create the subdirectories watchers std::string dir; - for ( FileInfoMap::iterator it = DirSnap.Files.begin(); it != DirSnap.Files.end(); it++ ) - { - if ( it->second.isDirectory() && it->second.isReadable() && !FileSystem::isRemoteFS( it->second.Filepath ) ) - { + for ( FileInfoMap::iterator it = DirSnap.Files.begin(); it != DirSnap.Files.end(); it++ ) { + if ( it->second.isDirectory() && it->second.isReadable() && + !FileSystem::isRemoteFS( it->second.Filepath ) ) { /// Check if the directory is a symbolic link std::string curPath; std::string link( FileSystem::getLinkRealPath( it->second.Filepath, curPath ) ); dir = it->first; - if ( "" != link ) - { + if ( "" != link ) { /// Avoid adding symlinks directories if it's now enabled - if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) - { + if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) { continue; } /// If it's a symlink check if the realpath exists as a watcher, or /// if the path is outside the current dir - if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) ) - { + if ( Watch->WatcherImpl->pathInWatches( link ) || + Watch->pathInWatches( link ) || + !Watch->WatcherImpl->linkAllowed( curPath, link ) ) { continue; - } - else - { + } else { dir = link; } - } - else - { - if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) - { + } else { + if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) { continue; } } - if ( reportNewFiles ) - { + if ( reportNewFiles ) { handleAction( dir, Actions::Add ); } - Directories[dir] = new DirWatcherGeneric( this, Watch, dir, Recursive, reportNewFiles ); + Directories[dir] = + new DirWatcherGeneric( this, Watch, dir, Recursive, reportNewFiles ); - Directories[dir]->addChilds( reportNewFiles ); + Directories[dir]->addChilds( reportNewFiles ); } } } } -void DirWatcherGeneric::watch( bool reportOwnChange ) -{ +void DirWatcherGeneric::watch( bool reportOwnChange ) { DirectorySnapshotDiff Diff = DirSnap.scan(); - if ( reportOwnChange && Diff.DirChanged && NULL != Parent ) - { - Watch->Listener->handleFileAction( Watch->ID, FileSystem::pathRemoveFileName( DirSnap.DirectoryInfo.Filepath ), FileSystem::fileNameFromPath( DirSnap.DirectoryInfo.Filepath ), Actions::Modified ); + if ( reportOwnChange && Diff.DirChanged && NULL != Parent ) { + Watch->Listener->handleFileAction( + Watch->ID, FileSystem::pathRemoveFileName( DirSnap.DirectoryInfo.Filepath ), + FileSystem::fileNameFromPath( DirSnap.DirectoryInfo.Filepath ), Actions::Modified ); } - if ( Diff.changed() ) - { + if ( Diff.changed() ) { FileInfoList::iterator it; MovedList::iterator mit; /// Files - DiffIterator( FilesCreated ) - { - handleAction( (*it).Filepath, Actions::Add ); + DiffIterator( FilesCreated ) { + handleAction( ( *it ).Filepath, Actions::Add ); } - DiffIterator( FilesModified ) - { - handleAction( (*it).Filepath, Actions::Modified ); + DiffIterator( FilesModified ) { + handleAction( ( *it ).Filepath, Actions::Modified ); } - DiffIterator( FilesDeleted ) - { - handleAction( (*it).Filepath, Actions::Delete ); + DiffIterator( FilesDeleted ) { + handleAction( ( *it ).Filepath, Actions::Delete ); } - DiffMovedIterator( FilesMoved ) - { - handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); + DiffMovedIterator( FilesMoved ) { + handleAction( ( *mit ).second.Filepath, Actions::Moved, ( *mit ).first ); } /// Directories - DiffIterator( DirsCreated ) - { - createDirectory( (*it).Filepath ); + DiffIterator( DirsCreated ) { + createDirectory( ( *it ).Filepath ); } - DiffIterator( DirsModified ) - { - handleAction( (*it).Filepath, Actions::Modified ); + DiffIterator( DirsModified ) { + handleAction( ( *it ).Filepath, Actions::Modified ); } - DiffIterator( DirsDeleted ) - { - handleAction( (*it).Filepath, Actions::Delete ); - removeDirectory( (*it).Filepath ); + DiffIterator( DirsDeleted ) { + handleAction( ( *it ).Filepath, Actions::Delete ); + removeDirectory( ( *it ).Filepath ); } - DiffMovedIterator( DirsMoved ) - { - handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); - moveDirectory( (*mit).first, (*mit).second.Filepath ); + DiffMovedIterator( DirsMoved ) { + handleAction( ( *mit ).second.Filepath, Actions::Moved, ( *mit ).first ); + moveDirectory( ( *mit ).first, ( *mit ).second.Filepath ); } } /// Process the subdirectories looking for changes - for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); ++dit ) - { + for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); ++dit ) { /// Just watch dit->second->watch(); } } -void DirWatcherGeneric::watchDir( std::string &dir ) -{ - DirWatcherGeneric * watcher = Watch->WatcherImpl->mFileWatcher->allowOutOfScopeLinks() ? - findDirWatcher( dir ) : - findDirWatcherFast( dir ); +void DirWatcherGeneric::watchDir( std::string& dir ) { + DirWatcherGeneric* watcher = Watch->WatcherImpl->mFileWatcher->allowOutOfScopeLinks() + ? findDirWatcher( dir ) + : findDirWatcherFast( dir ); - if ( NULL != watcher ) - { + if ( NULL != watcher ) { watcher->watch( true ); } } -DirWatcherGeneric * DirWatcherGeneric::findDirWatcherFast( std::string dir ) -{ +DirWatcherGeneric* DirWatcherGeneric::findDirWatcherFast( std::string dir ) { // remove the common base ( dir should always start with the same base as the watcher ) efASSERT( !dir.empty() ); efASSERT( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() ); - efASSERT( DirSnap.DirectoryInfo.Filepath == dir.substr( 0, DirSnap.DirectoryInfo.Filepath.size() ) ); + efASSERT( DirSnap.DirectoryInfo.Filepath == + dir.substr( 0, DirSnap.DirectoryInfo.Filepath.size() ) ); - if ( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() ) - { + if ( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() ) { dir = dir.substr( DirSnap.DirectoryInfo.Filepath.size() - 1 ); } - if ( dir.size() == 1 ) - { + if ( dir.size() == 1 ) { efASSERT( dir[0] == FileSystem::getOSSlash() ); return this; } @@ -258,22 +221,18 @@ DirWatcherGeneric * DirWatcherGeneric::findDirWatcherFast( std::string dir ) size_t level = 0; std::vector<std::string> dirv = String::split( dir, FileSystem::getOSSlash(), false ); - DirWatcherGeneric * watcher = this; + DirWatcherGeneric* watcher = this; - while ( level < dirv.size() ) - { + while ( level < dirv.size() ) { // search the dir level in the current watcher - DirWatchMap::iterator it = watcher->Directories.find( dirv[ level ] ); + DirWatchMap::iterator it = watcher->Directories.find( dirv[level] ); // found? continue with the next level - if ( it != watcher->Directories.end() ) - { + if ( it != watcher->Directories.end() ) { watcher = it->second; level++; - } - else - { + } else { // couldn't found the folder level? // directory not watched return NULL; @@ -283,22 +242,16 @@ DirWatcherGeneric * DirWatcherGeneric::findDirWatcherFast( std::string dir ) return watcher; } -DirWatcherGeneric * DirWatcherGeneric::findDirWatcher( std::string dir ) -{ - if ( DirSnap.DirectoryInfo.Filepath == dir ) - { +DirWatcherGeneric* DirWatcherGeneric::findDirWatcher( std::string dir ) { + if ( DirSnap.DirectoryInfo.Filepath == dir ) { return this; - } - else - { - DirWatcherGeneric * watcher = NULL; + } else { + DirWatcherGeneric* watcher = NULL; - for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) - { + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) { watcher = it->second->findDirWatcher( dir ); - if ( NULL != watcher ) - { + if ( NULL != watcher ) { return watcher; } } @@ -307,22 +260,22 @@ DirWatcherGeneric * DirWatcherGeneric::findDirWatcher( std::string dir ) return NULL; } -DirWatcherGeneric * DirWatcherGeneric::createDirectory( std::string newdir ) -{ +DirWatcherGeneric* DirWatcherGeneric::createDirectory( std::string newdir ) { FileSystem::dirRemoveSlashAtEnd( newdir ); newdir = FileSystem::fileNameFromPath( newdir ); - DirWatcherGeneric * dw = NULL; + DirWatcherGeneric* dw = NULL; /// Check if the directory is a symbolic link - std::string dir( DirSnap.DirectoryInfo.Filepath + newdir ); + std::string parentPath( DirSnap.DirectoryInfo.Filepath ); + FileSystem::dirAddSlashAtEnd( parentPath ); + std::string dir( parentPath + newdir ); FileSystem::dirAddSlashAtEnd( dir ); FileInfo fi( dir ); - if ( !fi.isDirectory() || !fi.isReadable() || FileSystem::isRemoteFS( dir ) ) - { + if ( !fi.isDirectory() || !fi.isReadable() || FileSystem::isRemoteFS( dir ) ) { return NULL; } @@ -330,57 +283,48 @@ DirWatcherGeneric * DirWatcherGeneric::createDirectory( std::string newdir ) std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); bool skip = false; - if ( "" != link ) - { + if ( "" != link ) { /// Avoid adding symlinks directories if it's now enabled - if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) - { + if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() ) { skip = true; } /// If it's a symlink check if the realpath exists as a watcher, or /// if the path is outside the current dir - if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) ) - { + if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || + !Watch->WatcherImpl->linkAllowed( curPath, link ) ) { skip = true; - } - else - { + } else { dir = link; } - } - else - { - if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) - { + } else { + if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) ) { skip = true; } } - if ( !skip ) - { + if ( !skip ) { handleAction( newdir, Actions::Add ); /// Creates the new directory watcher of the subfolder and check for new files dw = new DirWatcherGeneric( this, Watch, dir, Recursive ); - + dw->addChilds(); dw->watch(); /// Add it to the list of directories - Directories[ newdir ] = dw; + Directories[newdir] = dw; } return dw; } -void DirWatcherGeneric::removeDirectory( std::string dir ) -{ +void DirWatcherGeneric::removeDirectory( std::string dir ) { FileSystem::dirRemoveSlashAtEnd( dir ); dir = FileSystem::fileNameFromPath( dir ); - DirWatcherGeneric * dw = NULL; + DirWatcherGeneric* dw = NULL; DirWatchMap::iterator dit; /// Folder deleted @@ -388,8 +332,7 @@ void DirWatcherGeneric::removeDirectory( std::string dir ) /// Search the folder, it should exists dit = Directories.find( dir ); - if ( dit != Directories.end() ) - { + if ( dit != Directories.end() ) { dw = dit->second; /// Flag it as deleted so it fire the event for every file inside deleted @@ -403,49 +346,43 @@ void DirWatcherGeneric::removeDirectory( std::string dir ) } } -void DirWatcherGeneric::moveDirectory( std::string oldDir, std::string newDir ) -{ +void DirWatcherGeneric::moveDirectory( std::string oldDir, std::string newDir ) { FileSystem::dirRemoveSlashAtEnd( oldDir ); oldDir = FileSystem::fileNameFromPath( oldDir ); FileSystem::dirRemoveSlashAtEnd( newDir ); newDir = FileSystem::fileNameFromPath( newDir ); - DirWatcherGeneric * dw = NULL; + DirWatcherGeneric* dw = NULL; DirWatchMap::iterator dit; /// Directory existed? dit = Directories.find( oldDir ); - if ( dit != Directories.end() ) - { + if ( dit != Directories.end() ) { dw = dit->second; /// Remove the directory from the map Directories.erase( dit->first ); - Directories[ newDir ] = dw; + Directories[newDir] = dw; dw->resetDirectory( newDir ); } } -bool DirWatcherGeneric::pathInWatches( std::string path ) -{ - if ( DirSnap.DirectoryInfo.Filepath == path ) - { +bool DirWatcherGeneric::pathInWatches( std::string path ) { + if ( DirSnap.DirectoryInfo.Filepath == path ) { return true; } - for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) - { - if ( it->second->pathInWatches( path ) ) - { - return true; - } + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) { + if ( it->second->pathInWatches( path ) ) { + return true; + } } return false; } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.hpp b/dep/efsw/src/efsw/DirWatcherGeneric.hpp index a7581904422..ca52de7f22b 100644 --- a/dep/efsw/src/efsw/DirWatcherGeneric.hpp +++ b/dep/efsw/src/efsw/DirWatcherGeneric.hpp @@ -1,55 +1,57 @@ #ifndef EFSW_DIRWATCHERGENERIC_HPP #define EFSW_DIRWATCHERGENERIC_HPP -#include <efsw/WatcherGeneric.hpp> -#include <efsw/FileInfo.hpp> #include <efsw/DirectorySnapshot.hpp> +#include <efsw/FileInfo.hpp> +#include <efsw/WatcherGeneric.hpp> #include <map> namespace efsw { -class DirWatcherGeneric -{ - public: - typedef std::map<std::string, DirWatcherGeneric*> DirWatchMap; +class DirWatcherGeneric { + public: + typedef std::map<std::string, DirWatcherGeneric*> DirWatchMap; + + DirWatcherGeneric* Parent; + WatcherGeneric* Watch; + DirectorySnapshot DirSnap; + DirWatchMap Directories; + bool Recursive; - DirWatcherGeneric * Parent; - WatcherGeneric * Watch; - DirectorySnapshot DirSnap; - DirWatchMap Directories; - bool Recursive; + DirWatcherGeneric( DirWatcherGeneric* parent, WatcherGeneric* ws, const std::string& directory, + bool recursive, bool reportNewFiles = false ); - DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles = false ); + ~DirWatcherGeneric(); - ~DirWatcherGeneric(); + void watch( bool reportOwnChange = false ); - void watch( bool reportOwnChange = false ); + void watchDir( std::string& dir ); - void watchDir( std::string& dir ); + static bool isDir( const std::string& directory ); - static bool isDir( const std::string& directory ); + bool pathInWatches( std::string path ); - bool pathInWatches( std::string path ); + void addChilds( bool reportNewFiles = true ); - void addChilds( bool reportNewFiles = true ); + DirWatcherGeneric* findDirWatcher( std::string dir ); - DirWatcherGeneric * findDirWatcher( std::string dir ); + DirWatcherGeneric* findDirWatcherFast( std::string dir ); - DirWatcherGeneric * findDirWatcherFast( std::string dir ); - protected: - bool Deleted; + protected: + bool Deleted; - DirWatcherGeneric * createDirectory( std::string newdir ); + DirWatcherGeneric* createDirectory( std::string newdir ); - void removeDirectory( std::string dir ); + void removeDirectory( std::string dir ); - void moveDirectory( std::string oldDir, std::string newDir ); + void moveDirectory( std::string oldDir, std::string newDir ); - void resetDirectory( std::string directory ); + void resetDirectory( std::string directory ); - void handleAction( const std::string& filename, unsigned long action, std::string oldFilename = ""); + void handleAction( const std::string& filename, unsigned long action, + std::string oldFilename = "" ); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/DirectorySnapshot.cpp b/dep/efsw/src/efsw/DirectorySnapshot.cpp index e0680483e6b..f78475f546f 100644 --- a/dep/efsw/src/efsw/DirectorySnapshot.cpp +++ b/dep/efsw/src/efsw/DirectorySnapshot.cpp @@ -3,44 +3,32 @@ namespace efsw { -DirectorySnapshot::DirectorySnapshot() -{ -} +DirectorySnapshot::DirectorySnapshot() {} -DirectorySnapshot::DirectorySnapshot( std::string directory ) -{ +DirectorySnapshot::DirectorySnapshot( std::string directory ) { init( directory ); } -DirectorySnapshot::~DirectorySnapshot() -{ -} +DirectorySnapshot::~DirectorySnapshot() {} -void DirectorySnapshot::init( std::string directory ) -{ +void DirectorySnapshot::init( std::string directory ) { setDirectoryInfo( directory ); initFiles(); } -bool DirectorySnapshot::exists() -{ +bool DirectorySnapshot::exists() { return DirectoryInfo.exists(); } -void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) -{ +void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) { FileInfo fi; - for ( FileInfoMap::iterator it = Files.begin(); it != Files.end(); it++ ) - { + for ( FileInfoMap::iterator it = Files.begin(); it != Files.end(); it++ ) { fi = it->second; - if ( fi.isDirectory() ) - { + if ( fi.isDirectory() ) { Diff.DirsDeleted.push_back( fi ); - } - else - { + } else { Diff.FilesDeleted.push_back( fi ); } } @@ -48,51 +36,44 @@ void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) Files.clear(); } -void DirectorySnapshot::setDirectoryInfo( std::string directory ) -{ +void DirectorySnapshot::setDirectoryInfo( std::string directory ) { DirectoryInfo = FileInfo( directory ); } -void DirectorySnapshot::initFiles() -{ +void DirectorySnapshot::initFiles() { Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); FileInfoMap::iterator it = Files.begin(); - std::list<std::string> eraseFiles; + std::vector<std::string> eraseFiles; /// Remove all non regular files and non directories - for ( ; it != Files.end(); it++ ) - { - if ( !it->second.isRegularFile() && !it->second.isDirectory() ) - { + for ( ; it != Files.end(); it++ ) { + if ( !it->second.isRegularFile() && !it->second.isDirectory() ) { eraseFiles.push_back( it->first ); } } - for ( std::list<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); eit++ ) - { + for ( std::vector<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); + eit++ ) { Files.erase( *eit ); } } -DirectorySnapshotDiff DirectorySnapshot::scan() -{ - DirectorySnapshotDiff Diff; +DirectorySnapshotDiff DirectorySnapshot::scan() { + DirectorySnapshotDiff Diff; Diff.clear(); FileInfo curFI( DirectoryInfo.Filepath ); - Diff.DirChanged = DirectoryInfo != curFI; + Diff.DirChanged = DirectoryInfo != curFI; - if ( Diff.DirChanged ) - { + if ( Diff.DirChanged ) { DirectoryInfo = curFI; } /// If the directory was erased, create the events for files and directories deletion - if ( !curFI.exists() ) - { + if ( !curFI.exists() ) { deleteAll( Diff ); return Diff; @@ -100,8 +81,7 @@ DirectorySnapshotDiff DirectorySnapshot::scan() FileInfoMap files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); - if ( files.empty() && Files.empty() ) - { + if ( files.empty() && Files.empty() ) { return Diff; } @@ -110,52 +90,43 @@ DirectorySnapshotDiff DirectorySnapshot::scan() FileInfoMap::iterator it; FileInfoMap::iterator fiIt; - if ( Diff.DirChanged ) - { + if ( Diff.DirChanged ) { FilesCpy = Files; } - for ( it = files.begin(); it != files.end(); it++ ) - { - fi = it->second; + for ( it = files.begin(); it != files.end(); it++ ) { + fi = it->second; /// File existed before? fiIt = Files.find( it->first ); - if ( fiIt != Files.end() ) - { + if ( fiIt != Files.end() ) { /// Erase from the file list copy FilesCpy.erase( it->first ); /// File changed? - if ( (*fiIt).second != fi ) - { + if ( ( *fiIt ).second != fi ) { /// Update the new file info - Files[ it->first ] = fi; + Files[it->first] = fi; /// handle modified event - if ( fi.isDirectory() ) - { + if ( fi.isDirectory() ) { Diff.DirsModified.push_back( fi ); - } - else - { + } else { Diff.FilesModified.push_back( fi ); } } } /// Only add regular files or directories - else if ( fi.isRegularFile() || fi.isDirectory() ) - { + else if ( fi.isRegularFile() || fi.isDirectory() ) { /// New file found - Files[ it->first ] = fi; + Files[it->first] = fi; FileInfoMap::iterator fit; std::string oldFile = ""; /// Check if the same inode already existed - if ( ( fit = nodeInFiles( fi ) ) != Files.end() ) - { + if ( ( fit = nodeInFiles( fi ) ) != Files.end() ) { oldFile = fit->first; /// Avoid firing a Delete event @@ -164,45 +135,32 @@ DirectorySnapshotDiff DirectorySnapshot::scan() /// Delete the old file name Files.erase( fit->first ); - if ( fi.isDirectory() ) - { + if ( fi.isDirectory() ) { Diff.DirsMoved.push_back( std::make_pair( oldFile, fi ) ); - } - else - { + } else { Diff.FilesMoved.push_back( std::make_pair( oldFile, fi ) ); } - } - else - { - if ( fi.isDirectory() ) - { + } else { + if ( fi.isDirectory() ) { Diff.DirsCreated.push_back( fi ); - } - else - { + } else { Diff.FilesCreated.push_back( fi ); } } } } - if ( !Diff.DirChanged ) - { + if ( !Diff.DirChanged ) { return Diff; } /// The files or directories that remains were deleted - for ( it = FilesCpy.begin(); it != FilesCpy.end(); it++ ) - { + for ( it = FilesCpy.begin(); it != FilesCpy.end(); it++ ) { fi = it->second; - if ( fi.isDirectory() ) - { + if ( fi.isDirectory() ) { Diff.DirsDeleted.push_back( fi ); - } - else - { + } else { Diff.FilesDeleted.push_back( fi ); } @@ -213,16 +171,12 @@ DirectorySnapshotDiff DirectorySnapshot::scan() return Diff; } -FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi ) -{ +FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi ) { FileInfoMap::iterator it; - if ( FileInfo::inodeSupported() ) - { - for ( it = Files.begin(); it != Files.end(); it++ ) - { - if ( it->second.sameInode( fi ) && it->second.Filepath != fi.Filepath ) - { + if ( FileInfo::inodeSupported() ) { + for ( it = Files.begin(); it != Files.end(); it++ ) { + if ( it->second.sameInode( fi ) && it->second.Filepath != fi.Filepath ) { return it; } } @@ -231,33 +185,28 @@ FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi ) return Files.end(); } -void DirectorySnapshot::addFile( std::string path ) -{ +void DirectorySnapshot::addFile( std::string path ) { std::string name( FileSystem::fileNameFromPath( path ) ); - Files[ name ] = FileInfo( path ); + Files[name] = FileInfo( path ); } -void DirectorySnapshot::removeFile( std::string path ) -{ +void DirectorySnapshot::removeFile( std::string path ) { std::string name( FileSystem::fileNameFromPath( path ) ); FileInfoMap::iterator it = Files.find( name ); - if ( Files.end() != it ) - { + if ( Files.end() != it ) { Files.erase( it ); } } -void DirectorySnapshot::moveFile( std::string oldPath, std::string newPath ) -{ +void DirectorySnapshot::moveFile( std::string oldPath, std::string newPath ) { removeFile( oldPath ); addFile( newPath ); } -void DirectorySnapshot::updateFile(std::string path) -{ +void DirectorySnapshot::updateFile( std::string path ) { addFile( path ); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/DirectorySnapshot.hpp b/dep/efsw/src/efsw/DirectorySnapshot.hpp index 1ada66fe980..0e6054293cd 100644 --- a/dep/efsw/src/efsw/DirectorySnapshot.hpp +++ b/dep/efsw/src/efsw/DirectorySnapshot.hpp @@ -5,42 +5,41 @@ namespace efsw { -class DirectorySnapshot -{ - public: - FileInfo DirectoryInfo; - FileInfoMap Files; +class DirectorySnapshot { + public: + FileInfo DirectoryInfo; + FileInfoMap Files; - void setDirectoryInfo( std::string directory ); + void setDirectoryInfo( std::string directory ); - DirectorySnapshot(); + DirectorySnapshot(); - DirectorySnapshot( std::string directory ); + DirectorySnapshot( std::string directory ); - ~DirectorySnapshot(); + ~DirectorySnapshot(); - void init( std::string directory ); + void init( std::string directory ); - bool exists(); + bool exists(); - DirectorySnapshotDiff scan(); + DirectorySnapshotDiff scan(); - FileInfoMap::iterator nodeInFiles( FileInfo& fi ); + FileInfoMap::iterator nodeInFiles( FileInfo& fi ); - void addFile( std::string path ); + void addFile( std::string path ); - void removeFile( std::string path ); + void removeFile( std::string path ); - void moveFile( std::string oldPath, std::string newPath ); + void moveFile( std::string oldPath, std::string newPath ); - void updateFile( std::string path ); - protected: - void initFiles(); + void updateFile( std::string path ); - void deleteAll( DirectorySnapshotDiff &Diff ); + protected: + void initFiles(); + + void deleteAll( DirectorySnapshotDiff& Diff ); }; -} +} // namespace efsw #endif - diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp index eabc6fdbda1..37ee507fdc6 100644 --- a/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp +++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp @@ -2,8 +2,7 @@ namespace efsw { -void DirectorySnapshotDiff::clear() -{ +void DirectorySnapshotDiff::clear() { FilesCreated.clear(); FilesModified.clear(); FilesMoved.clear(); @@ -14,16 +13,10 @@ void DirectorySnapshotDiff::clear() DirsDeleted.clear(); } -bool DirectorySnapshotDiff::changed() -{ - return !FilesCreated.empty() || - !FilesModified.empty() || - !FilesMoved.empty() || - !FilesDeleted.empty() || - !DirsCreated.empty() || - !DirsModified.empty() || - !DirsMoved.empty() || - !DirsDeleted.empty(); +bool DirectorySnapshotDiff::changed() { + return !FilesCreated.empty() || !FilesModified.empty() || !FilesMoved.empty() || + !FilesDeleted.empty() || !DirsCreated.empty() || !DirsModified.empty() || + !DirsMoved.empty() || !DirsDeleted.empty(); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp index 042de9ce02c..26a29ec4436 100644 --- a/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp +++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp @@ -5,31 +5,31 @@ namespace efsw { -class DirectorySnapshotDiff -{ - public: - FileInfoList FilesDeleted; - FileInfoList FilesCreated; - FileInfoList FilesModified; - MovedList FilesMoved; - FileInfoList DirsDeleted; - FileInfoList DirsCreated; - FileInfoList DirsModified; - MovedList DirsMoved; - bool DirChanged; - - void clear(); - - bool changed(); +class DirectorySnapshotDiff { + public: + FileInfoList FilesDeleted; + FileInfoList FilesCreated; + FileInfoList FilesModified; + MovedList FilesMoved; + FileInfoList DirsDeleted; + FileInfoList DirsCreated; + FileInfoList DirsModified; + MovedList DirsMoved; + bool DirChanged; + + void clear(); + + bool changed(); }; -#define DiffIterator( FileInfoListName ) it = Diff.FileInfoListName.begin(); \ - for ( ; it != Diff.FileInfoListName.end(); it++ ) +#define DiffIterator( FileInfoListName ) \ + it = Diff.FileInfoListName.begin(); \ + for ( ; it != Diff.FileInfoListName.end(); it++ ) -#define DiffMovedIterator( MovedListName ) mit = Diff.MovedListName.begin(); \ - for ( ; mit != Diff.MovedListName.end(); mit++ ) +#define DiffMovedIterator( MovedListName ) \ + mit = Diff.MovedListName.begin(); \ + for ( ; mit != Diff.MovedListName.end(); mit++ ) -} +} // namespace efsw #endif - diff --git a/dep/efsw/src/efsw/FileInfo.cpp b/dep/efsw/src/efsw/FileInfo.cpp index f5518225b48..707f617fe41 100644 --- a/dep/efsw/src/efsw/FileInfo.cpp +++ b/dep/efsw/src/efsw/FileInfo.cpp @@ -16,208 +16,175 @@ #include <stdlib.h> #ifdef EFSW_COMPILER_MSVC - #ifndef S_ISDIR - #define S_ISDIR(f) ((f)&_S_IFDIR) - #endif +#ifndef S_ISDIR +#define S_ISDIR( f ) ( (f)&_S_IFDIR ) +#endif - #ifndef S_ISREG - #define S_ISREG(f) ((f)&_S_IFREG) - #endif +#ifndef S_ISREG +#define S_ISREG( f ) ( (f)&_S_IFREG ) +#endif - #ifndef S_ISRDBL - #define S_ISRDBL(f) ((f)&_S_IREAD) - #endif +#ifndef S_ISRDBL +#define S_ISRDBL( f ) ( (f)&_S_IREAD ) +#endif #else - #include <unistd.h> +#include <unistd.h> - #ifndef S_ISRDBL - #define S_ISRDBL(f) ((f)&S_IRUSR) - #endif +#ifndef S_ISRDBL +#define S_ISRDBL( f ) ( (f)&S_IRUSR ) +#endif #endif namespace efsw { -bool FileInfo::exists( const std::string& filePath ) -{ +bool FileInfo::exists( const std::string& filePath ) { FileInfo fi( filePath ); return fi.exists(); } -bool FileInfo::isLink( const std::string& filePath ) -{ +bool FileInfo::isLink( const std::string& filePath ) { FileInfo fi( filePath, true ); return fi.isLink(); } -bool FileInfo::inodeSupported() -{ - #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 +bool FileInfo::inodeSupported() { +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 return true; - #else +#else return false; - #endif +#endif } FileInfo::FileInfo() : - ModificationTime(0), - OwnerId(0), - GroupId(0), - Permissions(0), - Inode(0) -{} + ModificationTime( 0 ), OwnerId( 0 ), GroupId( 0 ), Permissions( 0 ), Inode( 0 ) {} FileInfo::FileInfo( const std::string& filepath ) : Filepath( filepath ), - ModificationTime(0), - OwnerId(0), - GroupId(0), - Permissions(0), - Inode(0) -{ + ModificationTime( 0 ), + OwnerId( 0 ), + GroupId( 0 ), + Permissions( 0 ), + Inode( 0 ) { getInfo(); } FileInfo::FileInfo( const std::string& filepath, bool linkInfo ) : Filepath( filepath ), - ModificationTime(0), - OwnerId(0), - GroupId(0), - Permissions(0), - Inode(0) -{ - if ( linkInfo ) - { + ModificationTime( 0 ), + OwnerId( 0 ), + GroupId( 0 ), + Permissions( 0 ), + Inode( 0 ) { + if ( linkInfo ) { getRealInfo(); - } - else - { + } else { getInfo(); } } -void FileInfo::getInfo() -{ - #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 - if ( Filepath.size() == 3 && Filepath[1] == ':' && Filepath[2] == FileSystem::getOSSlash() ) - { +void FileInfo::getInfo() { +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 + if ( Filepath.size() == 3 && Filepath[1] == ':' && Filepath[2] == FileSystem::getOSSlash() ) { Filepath += FileSystem::getOSSlash(); } - #endif +#endif - /// Why i'm doing this? stat in mingw32 doesn't work for directories if the dir path ends with a path slash + /// Why i'm doing this? stat in mingw32 doesn't work for directories if the dir path ends with a + /// path slash bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); - if ( slashAtEnd ) - { + if ( slashAtEnd ) { FileSystem::dirRemoveSlashAtEnd( Filepath ); } - #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 struct stat st; int res = stat( Filepath.c_str(), &st ); - #else +#else struct _stat st; int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); - #endif - - if ( 0 == res ) - { - ModificationTime = st.st_mtime; - Size = st.st_size; - OwnerId = st.st_uid; - GroupId = st.st_gid; - Permissions = st.st_mode; - Inode = st.st_ino; +#endif + + if ( 0 == res ) { + ModificationTime = st.st_mtime; + Size = st.st_size; + OwnerId = st.st_uid; + GroupId = st.st_gid; + Permissions = st.st_mode; + Inode = st.st_ino; } - if ( slashAtEnd ) - { + if ( slashAtEnd ) { FileSystem::dirAddSlashAtEnd( Filepath ); } } -void FileInfo::getRealInfo() -{ +void FileInfo::getRealInfo() { bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); - if ( slashAtEnd ) - { + if ( slashAtEnd ) { FileSystem::dirRemoveSlashAtEnd( Filepath ); } - #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 struct stat st; int res = lstat( Filepath.c_str(), &st ); - #else +#else struct _stat st; int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); - #endif - - if ( 0 == res ) - { - ModificationTime = st.st_mtime; - Size = st.st_size; - OwnerId = st.st_uid; - GroupId = st.st_gid; - Permissions = st.st_mode; - Inode = st.st_ino; +#endif + + if ( 0 == res ) { + ModificationTime = st.st_mtime; + Size = st.st_size; + OwnerId = st.st_uid; + GroupId = st.st_gid; + Permissions = st.st_mode; + Inode = st.st_ino; } - if ( slashAtEnd ) - { + if ( slashAtEnd ) { FileSystem::dirAddSlashAtEnd( Filepath ); } } -bool FileInfo::operator==( const FileInfo& Other ) const -{ - return ( ModificationTime == Other.ModificationTime && - Size == Other.Size && - OwnerId == Other.OwnerId && - GroupId == Other.GroupId && - Permissions == Other.Permissions && - Inode == Other.Inode - ); +bool FileInfo::operator==( const FileInfo& Other ) const { + return ( ModificationTime == Other.ModificationTime && Size == Other.Size && + OwnerId == Other.OwnerId && GroupId == Other.GroupId && + Permissions == Other.Permissions && Inode == Other.Inode ); } -bool FileInfo::isDirectory() const -{ - return 0 != S_ISDIR(Permissions); +bool FileInfo::isDirectory() const { + return 0 != S_ISDIR( Permissions ); } -bool FileInfo::isRegularFile() const -{ - return 0 != S_ISREG(Permissions); +bool FileInfo::isRegularFile() const { + return 0 != S_ISREG( Permissions ); } -bool FileInfo::isReadable() const -{ +bool FileInfo::isReadable() const { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 static bool isRoot = getuid() == 0; - return isRoot || 0 != S_ISRDBL(Permissions); + return isRoot || 0 != S_ISRDBL( Permissions ); #else - return 0 != S_ISRDBL(Permissions); + return 0 != S_ISRDBL( Permissions ); #endif } -bool FileInfo::isLink() const -{ +bool FileInfo::isLink() const { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 - return S_ISLNK(Permissions); + return S_ISLNK( Permissions ); #else return false; #endif } -std::string FileInfo::linksTo() -{ +std::string FileInfo::linksTo() { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 - if ( isLink() ) - { - char * ch = realpath( Filepath.c_str(), NULL); + if ( isLink() ) { + char* ch = realpath( Filepath.c_str(), NULL ); - if ( NULL != ch ) - { + if ( NULL != ch ) { std::string tstr( ch ); free( ch ); @@ -226,16 +193,14 @@ std::string FileInfo::linksTo() } } #endif - return std::string(""); + return std::string( "" ); } -bool FileInfo::exists() -{ +bool FileInfo::exists() { bool slashAtEnd = FileSystem::slashAtEnd( Filepath ); - if ( slashAtEnd ) - { - FileSystem::dirRemoveSlashAtEnd(Filepath); + if ( slashAtEnd ) { + FileSystem::dirRemoveSlashAtEnd( Filepath ); } #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 @@ -246,34 +211,30 @@ bool FileInfo::exists() int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st ); #endif - if (slashAtEnd) - { - FileSystem::dirAddSlashAtEnd(Filepath); + if ( slashAtEnd ) { + FileSystem::dirAddSlashAtEnd( Filepath ); } return 0 == res; } -FileInfo& FileInfo::operator=( const FileInfo& Other ) -{ - this->Filepath = Other.Filepath; - this->Size = Other.Size; - this->ModificationTime = Other.ModificationTime; - this->GroupId = Other.GroupId; - this->OwnerId = Other.OwnerId; - this->Permissions = Other.Permissions; - this->Inode = Other.Inode; +FileInfo& FileInfo::operator=( const FileInfo& Other ) { + this->Filepath = Other.Filepath; + this->Size = Other.Size; + this->ModificationTime = Other.ModificationTime; + this->GroupId = Other.GroupId; + this->OwnerId = Other.OwnerId; + this->Permissions = Other.Permissions; + this->Inode = Other.Inode; return *this; } -bool FileInfo::sameInode( const FileInfo& Other ) const -{ +bool FileInfo::sameInode( const FileInfo& Other ) const { return inodeSupported() && Inode == Other.Inode; } -bool FileInfo::operator!=( const FileInfo& Other ) const -{ - return !(*this == Other); +bool FileInfo::operator!=( const FileInfo& Other ) const { + return !( *this == Other ); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/FileInfo.hpp b/dep/efsw/src/efsw/FileInfo.hpp index c86e5749a70..1aca2a87581 100644 --- a/dep/efsw/src/efsw/FileInfo.hpp +++ b/dep/efsw/src/efsw/FileInfo.hpp @@ -2,65 +2,63 @@ #define EFSW_FILEINFO_HPP #include <efsw/base.hpp> -#include <string> +#include <vector> #include <map> -#include <list> +#include <string> namespace efsw { -class FileInfo -{ - public: - static bool exists( const std::string& filePath ); +class FileInfo { + public: + static bool exists( const std::string& filePath ); - static bool isLink( const std::string& filePath ); + static bool isLink( const std::string& filePath ); - static bool inodeSupported(); + static bool inodeSupported(); - FileInfo(); + FileInfo(); - FileInfo( const std::string& filepath ); + FileInfo( const std::string& filepath ); - FileInfo( const std::string& filepath, bool linkInfo ); + FileInfo( const std::string& filepath, bool linkInfo ); - bool operator==( const FileInfo& Other ) const; + bool operator==( const FileInfo& Other ) const; - bool operator!=( const FileInfo& Other ) const; + bool operator!=( const FileInfo& Other ) const; - FileInfo& operator=( const FileInfo& Other ); + FileInfo& operator=( const FileInfo& Other ); - bool isDirectory() const; + bool isDirectory() const; - bool isRegularFile() const; + bool isRegularFile() const; - bool isReadable() const; + bool isReadable() const; - bool sameInode( const FileInfo& Other ) const; + bool sameInode( const FileInfo& Other ) const; - bool isLink() const; + bool isLink() const; - std::string linksTo(); + std::string linksTo(); - bool exists(); + bool exists(); - void getInfo(); + void getInfo(); - void getRealInfo(); + void getRealInfo(); - std::string Filepath; - Uint64 ModificationTime; - Uint64 Size; - Uint32 OwnerId; - Uint32 GroupId; - Uint32 Permissions; - Uint64 Inode; + std::string Filepath; + Uint64 ModificationTime; + Uint64 Size; + Uint32 OwnerId; + Uint32 GroupId; + Uint32 Permissions; + Uint64 Inode; }; -typedef std::map<std::string, FileInfo> FileInfoMap; -typedef std::list<FileInfo> FileInfoList; -typedef std::list< std::pair< std::string, FileInfo> > MovedList; +typedef std::map<std::string, FileInfo> FileInfoMap; +typedef std::vector<FileInfo> FileInfoList; +typedef std::vector<std::pair<std::string, FileInfo>> MovedList; -} +} // namespace efsw #endif - diff --git a/dep/efsw/src/efsw/FileSystem.cpp b/dep/efsw/src/efsw/FileSystem.cpp index 1bca40558c6..b6d2d63ddce 100644 --- a/dep/efsw/src/efsw/FileSystem.cpp +++ b/dep/efsw/src/efsw/FileSystem.cpp @@ -1,3 +1,4 @@ +#include <cstring> #include <efsw/FileSystem.hpp> #include <efsw/platform/platformimpl.hpp> @@ -7,8 +8,7 @@ namespace efsw { -bool FileSystem::isDirectory( const std::string& path ) -{ +bool FileSystem::isDirectory( const std::string& path ) { return Platform::FileSystem::isDirectory( path ); } @@ -18,68 +18,56 @@ FileInfoMap FileSystem::filesInfoFromPath( std::string path ) { return Platform::FileSystem::filesInfoFromPath( path ); } -char FileSystem::getOSSlash() -{ +char FileSystem::getOSSlash() { return Platform::FileSystem::getOSSlash(); } -bool FileSystem::slashAtEnd( std::string &dir ) -{ - return ( dir.size() && dir[ dir.size() - 1 ] == getOSSlash() ); +bool FileSystem::slashAtEnd( std::string& dir ) { + return ( dir.size() && dir[dir.size() - 1] == getOSSlash() ); } -void FileSystem::dirAddSlashAtEnd( std::string& dir ) -{ - if ( dir.size() > 1 && dir[ dir.size() - 1 ] != getOSSlash() ) - { +void FileSystem::dirAddSlashAtEnd( std::string& dir ) { + if ( dir.size() >= 1 && dir[dir.size() - 1] != getOSSlash() ) { dir.push_back( getOSSlash() ); } } -void FileSystem::dirRemoveSlashAtEnd( std::string& dir ) -{ - if ( dir.size() > 1 && dir[ dir.size() - 1 ] == getOSSlash() ) - { +void FileSystem::dirRemoveSlashAtEnd( std::string& dir ) { + if ( dir.size() >= 1 && dir[dir.size() - 1] == getOSSlash() ) { dir.erase( dir.size() - 1 ); } } -std::string FileSystem::fileNameFromPath( std::string filepath ) -{ +std::string FileSystem::fileNameFromPath( std::string filepath ) { dirRemoveSlashAtEnd( filepath ); size_t pos = filepath.find_last_of( getOSSlash() ); - if ( pos != std::string::npos ) - { + if ( pos != std::string::npos ) { return filepath.substr( pos + 1 ); } return filepath; } -std::string FileSystem::pathRemoveFileName( std::string filepath ) -{ +std::string FileSystem::pathRemoveFileName( std::string filepath ) { dirRemoveSlashAtEnd( filepath ); size_t pos = filepath.find_last_of( getOSSlash() ); - if ( pos != std::string::npos ) - { + if ( pos != std::string::npos ) { return filepath.substr( 0, pos + 1 ); } return filepath; } -std::string FileSystem::getLinkRealPath( std::string dir, std::string& curPath ) -{ +std::string FileSystem::getLinkRealPath( std::string dir, std::string& curPath ) { FileSystem::dirRemoveSlashAtEnd( dir ); FileInfo fi( dir, true ); /// Check with lstat and see if it's a link - if ( fi.isLink() ) - { + if ( fi.isLink() ) { /// get the real path of the link std::string link( fi.linksTo() ); @@ -96,39 +84,53 @@ std::string FileSystem::getLinkRealPath( std::string dir, std::string& curPath ) return ""; } -std::string FileSystem::precomposeFileName( const std::string& name ) -{ +std::string FileSystem::precomposeFileName( const std::string& name ) { #if EFSW_OS == EFSW_OS_MACOSX - CFStringRef cfStringRef = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8); - CFMutableStringRef cfMutable = CFStringCreateMutableCopy(NULL, 0, cfStringRef); - - CFStringNormalize(cfMutable,kCFStringNormalizationFormC); - - char c_str[255 + 1]; - CFStringGetCString(cfMutable, c_str, sizeof(c_str)-1, kCFStringEncodingUTF8); - - CFRelease(cfStringRef); - CFRelease(cfMutable); + CFStringRef cfStringRef = + CFStringCreateWithCString( kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8 ); + CFMutableStringRef cfMutable = CFStringCreateMutableCopy( NULL, 0, cfStringRef ); + + CFStringNormalize( cfMutable, kCFStringNormalizationFormC ); + + const char* c_str = CFStringGetCStringPtr( cfMutable, kCFStringEncodingUTF8 ); + if ( c_str != NULL ) { + std::string result( c_str ); + CFRelease( cfStringRef ); + CFRelease( cfMutable ); + return result; + } + CFIndex length = CFStringGetLength( cfMutable ); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ); + if ( maxSize == kCFNotFound ) { + CFRelease( cfStringRef ); + CFRelease( cfMutable ); + return std::string(); + } - return std::string(c_str); + std::string result( maxSize + 1, '\0' ); + if ( CFStringGetCString( cfMutable, &result[0], result.size(), kCFStringEncodingUTF8 ) ) { + result.resize( std::strlen( result.c_str() ) ); + CFRelease( cfStringRef ); + CFRelease( cfMutable ); + } else { + result.clear(); + } + return result; #else return name; #endif } -bool FileSystem::isRemoteFS( const std::string& directory ) -{ +bool FileSystem::isRemoteFS( const std::string& directory ) { return Platform::FileSystem::isRemoteFS( directory ); } -bool FileSystem::changeWorkingDirectory( const std::string& directory ) -{ +bool FileSystem::changeWorkingDirectory( const std::string& directory ) { return Platform::FileSystem::changeWorkingDirectory( directory ); } -std::string FileSystem::getCurrentWorkingDirectory() -{ +std::string FileSystem::getCurrentWorkingDirectory() { return Platform::FileSystem::getCurrentWorkingDirectory(); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/FileSystem.hpp b/dep/efsw/src/efsw/FileSystem.hpp index 07c7ade8baa..6c24386c585 100644 --- a/dep/efsw/src/efsw/FileSystem.hpp +++ b/dep/efsw/src/efsw/FileSystem.hpp @@ -1,44 +1,41 @@ #ifndef EFSW_FILESYSTEM_HPP #define EFSW_FILESYSTEM_HPP -#include <efsw/base.hpp> #include <efsw/FileInfo.hpp> +#include <efsw/base.hpp> #include <map> namespace efsw { -class FileSystem -{ - public: - static bool isDirectory( const std::string& path ); - - static FileInfoMap filesInfoFromPath( std::string path ); +class FileSystem { + public: + static bool isDirectory( const std::string& path ); - static char getOSSlash(); + static FileInfoMap filesInfoFromPath( std::string path ); - static bool slashAtEnd( std::string& dir ); + static char getOSSlash(); - static void dirAddSlashAtEnd( std::string& dir ); + static bool slashAtEnd( std::string& dir ); - static void dirRemoveSlashAtEnd( std::string& dir ); + static void dirAddSlashAtEnd( std::string& dir ); - static std::string fileNameFromPath( std::string filepath ); + static void dirRemoveSlashAtEnd( std::string& dir ); - static std::string pathRemoveFileName( std::string filepath ); + static std::string fileNameFromPath( std::string filepath ); - static void realPath( std::string curdir, std::string& path ); + static std::string pathRemoveFileName( std::string filepath ); - static std::string getLinkRealPath( std::string dir, std::string& curPath ); + static std::string getLinkRealPath( std::string dir, std::string& curPath ); - static std::string precomposeFileName(const std::string& name); + static std::string precomposeFileName( const std::string& name ); - static bool isRemoteFS( const std::string& directory ); + static bool isRemoteFS( const std::string& directory ); - static bool changeWorkingDirectory( const std::string & path ); + static bool changeWorkingDirectory( const std::string& path ); - static std::string getCurrentWorkingDirectory(); + static std::string getCurrentWorkingDirectory(); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcher.cpp b/dep/efsw/src/efsw/FileWatcher.cpp index e33d5ec46fb..ab3ec4bd679 100644 --- a/dep/efsw/src/efsw/FileWatcher.cpp +++ b/dep/efsw/src/efsw/FileWatcher.cpp @@ -1,43 +1,39 @@ -#include <efsw/efsw.hpp> -#include <efsw/FileWatcherImpl.hpp> -#include <efsw/FileWatcherGeneric.hpp> #include <efsw/FileSystem.hpp> +#include <efsw/FileWatcherGeneric.hpp> +#include <efsw/FileWatcherImpl.hpp> +#include <efsw/efsw.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 -# include <efsw/FileWatcherWin32.hpp> -# define FILEWATCHER_IMPL FileWatcherWin32 -# define BACKEND_NAME "Win32" +#include <efsw/FileWatcherWin32.hpp> +#define FILEWATCHER_IMPL FileWatcherWin32 +#define BACKEND_NAME "Win32" #elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY -# include <efsw/FileWatcherInotify.hpp> -# define FILEWATCHER_IMPL FileWatcherInotify -# define BACKEND_NAME "Inotify" +#include <efsw/FileWatcherInotify.hpp> +#define FILEWATCHER_IMPL FileWatcherInotify +#define BACKEND_NAME "Inotify" #elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE -# include <efsw/FileWatcherKqueue.hpp> -# define FILEWATCHER_IMPL FileWatcherKqueue -# define BACKEND_NAME "Kqueue" +#include <efsw/FileWatcherKqueue.hpp> +#define FILEWATCHER_IMPL FileWatcherKqueue +#define BACKEND_NAME "Kqueue" #elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS -# include <efsw/FileWatcherFSEvents.hpp> -# define FILEWATCHER_IMPL FileWatcherFSEvents -# define BACKEND_NAME "FSEvents" +#include <efsw/FileWatcherFSEvents.hpp> +#define FILEWATCHER_IMPL FileWatcherFSEvents +#define BACKEND_NAME "FSEvents" #else -# define FILEWATCHER_IMPL FileWatcherGeneric -# define BACKEND_NAME "Generic" +#define FILEWATCHER_IMPL FileWatcherGeneric +#define BACKEND_NAME "Generic" #endif #include <efsw/Debug.hpp> namespace efsw { -FileWatcher::FileWatcher() : - mFollowSymlinks(false), - mOutOfScopeLinks(false) -{ +FileWatcher::FileWatcher() : mFollowSymlinks( false ), mOutOfScopeLinks( false ) { efDEBUG( "Using backend: %s\n", BACKEND_NAME ); mImpl = new FILEWATCHER_IMPL( this ); - if ( !mImpl->initOK() ) - { + if ( !mImpl->initOK() ) { efSAFE_DELETE( mImpl ); efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); @@ -47,23 +43,17 @@ FileWatcher::FileWatcher() : } FileWatcher::FileWatcher( bool useGenericFileWatcher ) : - mFollowSymlinks(false), - mOutOfScopeLinks(false) -{ - if ( useGenericFileWatcher ) - { + mFollowSymlinks( false ), mOutOfScopeLinks( false ) { + if ( useGenericFileWatcher ) { efDEBUG( "Using backend: Generic\n" ); mImpl = new FileWatcherGeneric( this ); - } - else - { + } else { efDEBUG( "Using backend: %s\n", BACKEND_NAME ); mImpl = new FILEWATCHER_IMPL( this ); - if ( !mImpl->initOK() ) - { + if ( !mImpl->initOK() ) { efSAFE_DELETE( mImpl ); efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); @@ -73,73 +63,58 @@ FileWatcher::FileWatcher( bool useGenericFileWatcher ) : } } -FileWatcher::~FileWatcher() -{ +FileWatcher::~FileWatcher() { efSAFE_DELETE( mImpl ); } -WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher) -{ - if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) - { - return mImpl->addWatch(directory, watcher, false); - } - else - { - return Errors::Log::createLastError( Errors::FileRemote, directory ); - } +WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher ) { + return addWatch( directory, watcher, false, {} ); } -WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) -{ - if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) - { - return mImpl->addWatch(directory, watcher, recursive); - } - else - { +WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive ) { + return addWatch( directory, watcher, recursive, {} ); +} + +WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption>& options ) { + if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) { + return mImpl->addWatch( directory, watcher, recursive, options ); + } else { return Errors::Log::createLastError( Errors::FileRemote, directory ); } } -void FileWatcher::removeWatch(const std::string& directory) -{ - mImpl->removeWatch(directory); +void FileWatcher::removeWatch( const std::string& directory ) { + mImpl->removeWatch( directory ); } -void FileWatcher::removeWatch(WatchID watchid) -{ - mImpl->removeWatch(watchid); +void FileWatcher::removeWatch( WatchID watchid ) { + mImpl->removeWatch( watchid ); } -void FileWatcher::watch() -{ +void FileWatcher::watch() { mImpl->watch(); } -std::list<std::string> FileWatcher::directories() -{ +std::vector<std::string> FileWatcher::directories() { return mImpl->directories(); } -void FileWatcher::followSymlinks( bool follow ) -{ +void FileWatcher::followSymlinks( bool follow ) { mFollowSymlinks = follow; } -const bool& FileWatcher::followSymlinks() const -{ +const bool& FileWatcher::followSymlinks() const { return mFollowSymlinks; } -void FileWatcher::allowOutOfScopeLinks( bool allow ) -{ +void FileWatcher::allowOutOfScopeLinks( bool allow ) { mOutOfScopeLinks = allow; } -const bool& FileWatcher::allowOutOfScopeLinks() const -{ +const bool& FileWatcher::allowOutOfScopeLinks() const { return mOutOfScopeLinks; } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp index 30a36eacc35..860d7d50c8b 100644 --- a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp +++ b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp @@ -2,27 +2,24 @@ #include <efsw/efsw.hpp> #include <vector> -#define TOBOOL(i) ((i) == 0 ? false : true) +#define TOBOOL( i ) ( ( i ) == 0 ? false : true ) /*************************************************************************************************/ -class Watcher_CAPI : public efsw::FileWatchListener -{ -public: +class Watcher_CAPI : public efsw::FileWatchListener { + public: efsw_watcher mWatcher; efsw_pfn_fileaction_callback mFn; void* mParam; -public: - Watcher_CAPI(efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param) : - mWatcher( watcher ), - mFn( fn ), - mParam( param ) - {} - - void handleFileAction(efsw::WatchID watchid, const std::string& dir, const std::string& filename, - efsw::Action action, std::string oldFilename = "") - { - mFn(mWatcher, watchid, dir.c_str(), filename.c_str(), (enum efsw_action)action, - oldFilename.c_str(), mParam ); + + public: + Watcher_CAPI( efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param ) : + mWatcher( watcher ), mFn( fn ), mParam( param ) {} + + void handleFileAction( efsw::WatchID watchid, const std::string& dir, + const std::string& filename, efsw::Action action, + std::string oldFilename = "" ) { + mFn( mWatcher, watchid, dir.c_str(), filename.c_str(), (enum efsw_action)action, + oldFilename.c_str(), mParam ); } }; @@ -31,28 +28,26 @@ public: */ static std::vector<Watcher_CAPI*> g_callbacks; -Watcher_CAPI* find_callback(efsw_watcher watcher, efsw_pfn_fileaction_callback fn) -{ - for (std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); ++i ) - { +Watcher_CAPI* find_callback( efsw_watcher watcher, efsw_pfn_fileaction_callback fn ) { + for ( std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); + ++i ) { Watcher_CAPI* callback = *i; - if (callback->mFn == fn && callback->mWatcher == watcher) + if ( callback->mFn == fn && callback->mWatcher == watcher ) return *i; } return NULL; } -Watcher_CAPI* remove_callback(efsw_watcher watcher) -{ +Watcher_CAPI* remove_callback( efsw_watcher watcher ) { std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); - while (i != g_callbacks.end()) { + while ( i != g_callbacks.end() ) { Watcher_CAPI* callback = *i; - if (callback->mWatcher == watcher) - i = g_callbacks.erase(i); + if ( callback->mWatcher == watcher ) + i = g_callbacks.erase( i ); else ++i; } @@ -60,72 +55,77 @@ Watcher_CAPI* remove_callback(efsw_watcher watcher) return NULL; } - /*************************************************************************************************/ -efsw_watcher efsw_create(int generic_mode) -{ - return (efsw_watcher)new efsw::FileWatcher(TOBOOL(generic_mode)); +efsw_watcher efsw_create( int generic_mode ) { + return ( efsw_watcher ) new efsw::FileWatcher( TOBOOL( generic_mode ) ); } -void efsw_release(efsw_watcher watcher) -{ - remove_callback(watcher); +void efsw_release( efsw_watcher watcher ) { + remove_callback( watcher ); delete (efsw::FileWatcher*)watcher; } -const char* efsw_getlasterror() -{ +const char* efsw_getlasterror() { static std::string log_str; log_str = efsw::Errors::Log::getLastErrorLog(); return log_str.c_str(); } -efsw_watchid efsw_addwatch(efsw_watcher watcher, const char* directory, - efsw_pfn_fileaction_callback callback_fn, int recursive, void * param) -{ - Watcher_CAPI* callback = find_callback(watcher, callback_fn); +EFSW_API void efsw_clearlasterror() { + efsw::Errors::Log::clearLastError(); +} + +efsw_watchid efsw_addwatch( efsw_watcher watcher, const char* directory, + efsw_pfn_fileaction_callback callback_fn, int recursive, void* param ) { + return efsw_addwatch_withoptions( watcher, directory, callback_fn, recursive, 0, 0, param ); +} + +efsw_watchid efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory, + efsw_pfn_fileaction_callback callback_fn, int recursive, + efsw_watcher_option *options, int options_number, + void* param) { + Watcher_CAPI* callback = find_callback( watcher, callback_fn ); - if (callback == NULL) { - callback = new Watcher_CAPI(watcher, callback_fn, param); - g_callbacks.push_back(callback); + if ( callback == NULL ) { + callback = new Watcher_CAPI( watcher, callback_fn, param ); + g_callbacks.push_back( callback ); } - return ((efsw::FileWatcher*)watcher)->addWatch(std::string(directory), callback, - TOBOOL(recursive)); -} + std::vector<efsw::WatcherOption> watcher_options{}; + for ( int i = 0; i < options_number; i++ ) { + efsw_watcher_option* option = &options[i]; + watcher_options.emplace_back( efsw::WatcherOption{ + static_cast<efsw::Option>(option->option), option->value } ); + } -void efsw_removewatch(efsw_watcher watcher, const char* directory) -{ - ((efsw::FileWatcher*)watcher)->removeWatch(std::string(directory)); + return ( (efsw::FileWatcher*)watcher ) + ->addWatch( std::string( directory ), callback, TOBOOL( recursive ), watcher_options ); } -void efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid) -{ - ((efsw::FileWatcher*)watcher)->removeWatch(watchid); +void efsw_removewatch( efsw_watcher watcher, const char* directory ) { + ( (efsw::FileWatcher*)watcher )->removeWatch( std::string( directory ) ); } -void efsw_watch(efsw_watcher watcher) -{ - ((efsw::FileWatcher*)watcher)->watch(); +void efsw_removewatch_byid( efsw_watcher watcher, efsw_watchid watchid ) { + ( (efsw::FileWatcher*)watcher )->removeWatch( watchid ); } -void efsw_follow_symlinks(efsw_watcher watcher, int enable) -{ - ((efsw::FileWatcher*)watcher)->followSymlinks(TOBOOL(enable)); +void efsw_watch( efsw_watcher watcher ) { + ( (efsw::FileWatcher*)watcher )->watch(); } -int efsw_follow_symlinks_isenabled(efsw_watcher watcher) -{ - return (int)((efsw::FileWatcher*)watcher)->followSymlinks(); +void efsw_follow_symlinks( efsw_watcher watcher, int enable ) { + ( (efsw::FileWatcher*)watcher )->followSymlinks( TOBOOL( enable ) ); } -void efsw_allow_outofscopelinks(efsw_watcher watcher, int allow) -{ - ((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks(TOBOOL(allow)); +int efsw_follow_symlinks_isenabled( efsw_watcher watcher ) { + return (int)( (efsw::FileWatcher*)watcher )->followSymlinks(); } -int efsw_outofscopelinks_isallowed(efsw_watcher watcher) -{ - return (int)((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks(); +void efsw_allow_outofscopelinks( efsw_watcher watcher, int allow ) { + ( (efsw::FileWatcher*)watcher )->allowOutOfScopeLinks( TOBOOL( allow ) ); } +int efsw_outofscopelinks_isallowed( efsw_watcher watcher ) { + return (int)( (efsw::FileWatcher*)watcher )->allowOutOfScopeLinks(); +} diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp index 5aac14282c9..0fa745242cf 100644 --- a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp @@ -1,67 +1,58 @@ -#include <efsw/FileWatcherFSEvents.hpp> -#include <efsw/FileSystem.hpp> -#include <efsw/System.hpp> #include <efsw/Debug.hpp> -#include <efsw/String.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/FileWatcherFSEvents.hpp> #include <efsw/Lock.hpp> +#include <efsw/String.hpp> +#include <efsw/System.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS #include <sys/utsname.h> -namespace efsw -{ +namespace efsw { -int getOSXReleaseNumber() -{ +int getOSXReleaseNumber() { static int osxR = -1; - - if ( -1 == osxR ) - { + + if ( -1 == osxR ) { struct utsname os; - + if ( -1 != uname( &os ) ) { std::string release( os.release ); - + size_t pos = release.find_first_of( '.' ); - - if ( pos != std::string::npos ) - { + + if ( pos != std::string::npos ) { release = release.substr( 0, pos ); } - + int rel = 0; - - if ( String::fromString<int>( rel, release ) ) - { + + if ( String::fromString<int>( rel, release ) ) { osxR = rel; } } } - + return osxR; } -bool FileWatcherFSEvents::isGranular() -{ +bool FileWatcherFSEvents::isGranular() { return getOSXReleaseNumber() >= 11; } -void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, - void *userData, - size_t numEvents, - void *eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[] ) -{ - WatcherFSEvents * watcher = static_cast<WatcherFSEvents*>( userData ); +void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, void* userData, + size_t numEvents, void* eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[] ) { + WatcherFSEvents* watcher = static_cast<WatcherFSEvents*>( userData ); std::vector<FSEvent> events; events.reserve( numEvents ); - for ( size_t i = 0; i < numEvents; i++ ) - { - events.push_back( FSEvent( std::string( ((char**)eventPaths)[i] ), (long)eventFlags[i], (Uint64)eventIds[i] ) ); + for ( size_t i = 0; i < numEvents; i++ ) { + events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), (long)eventFlags[i], + (Uint64)eventIds[i] ) ); } watcher->handleActions( events ); @@ -71,60 +62,42 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, efDEBUG( "\n" ); } -FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher * parent ) : - FileWatcherImpl( parent ), - mRunLoopRef( NULL ), - mLastWatchID(0), - mThread( NULL ) -{ +FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) : + FileWatcherImpl( parent ), mLastWatchID( 0 ) { mInitOK = true; - + watch(); } -FileWatcherFSEvents::~FileWatcherFSEvents() -{ +FileWatcherFSEvents::~FileWatcherFSEvents() { mInitOK = false; - efSAFE_DELETE( mThread ); + mWatchCond.notify_all(); WatchMap::iterator iter = mWatches.begin(); - for( ; iter != mWatches.end(); ++iter ) - { - WatcherFSEvents * watch = iter->second; - + for ( ; iter != mWatches.end(); ++iter ) { + WatcherFSEvents* watch = iter->second; + efSAFE_DELETE( watch ); } - - mWatches.clear(); } -WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ) -{ - /// Wait to the RunLoopRef to be ready - while ( NULL == mRunLoopRef ) - { - System::sleep( 1 ); - } - +WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption> &options ) { std::string dir( directory ); FileInfo fi( dir ); - if ( !fi.isDirectory() ) - { + if ( !fi.isDirectory() ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( !fi.isReadable() ) - { + } else if ( !fi.isReadable() ) { return Errors::Log::createLastError( Errors::FileNotReadable, dir ); } FileSystem::dirAddSlashAtEnd( dir ); - if ( pathInWatches( dir ) ) - { + if ( pathInWatches( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); } @@ -132,67 +105,60 @@ WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchLi std::string curPath; std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); - if ( "" != link ) - { + if ( "" != link ) { /// If it's a symlink check if the realpath exists as a watcher, or /// if the path is outside the current dir - if ( pathInWatches( link ) ) - { + if ( pathInWatches( link ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); - } - else if ( !linkAllowed( curPath, link ) ) - { + } else if ( !linkAllowed( curPath, link ) ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); - } - else - { + } else { dir = link; } } - + mLastWatchID++; - WatcherFSEvents * pWatch = new WatcherFSEvents(); - pWatch->Listener = watcher; - pWatch->ID = mLastWatchID; - pWatch->Directory = dir; - pWatch->Recursive = recursive; - pWatch->FWatcher = this; - + WatcherFSEvents* pWatch = new WatcherFSEvents(); + pWatch->Listener = watcher; + pWatch->ID = mLastWatchID; + pWatch->Directory = dir; + pWatch->Recursive = recursive; + pWatch->FWatcher = this; + pWatch->init(); - Lock lock( mWatchesLock ); - mWatches.insert(std::make_pair(mLastWatchID, pWatch)); + { + Lock lock( mWatchesLock ); + mWatches.insert( std::make_pair( mLastWatchID, pWatch ) ); + } + mWatchCond.notify_all(); return pWatch->ID; } -void FileWatcherFSEvents::removeWatch(const std::string& directory) -{ +void FileWatcherFSEvents::removeWatch( const std::string& directory ) { Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); - for(; iter != mWatches.end(); ++iter) - { - if( directory == iter->second->Directory ) - { + for ( ; iter != mWatches.end(); ++iter ) { + if ( directory == iter->second->Directory ) { removeWatch( iter->second->ID ); return; } } } -void FileWatcherFSEvents::removeWatch(WatchID watchid) -{ +void FileWatcherFSEvents::removeWatch( WatchID watchid ) { Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.find( watchid ); - if( iter == mWatches.end() ) + if ( iter == mWatches.end() ) return; - WatcherFSEvents * watch = iter->second; + WatcherFSEvents* watch = iter->second; mWatches.erase( iter ); @@ -201,63 +167,30 @@ void FileWatcherFSEvents::removeWatch(WatchID watchid) efSAFE_DELETE( watch ); } -void FileWatcherFSEvents::watch() -{ - if ( NULL == mThread ) - { - mThread = new Thread( &FileWatcherFSEvents::run, this ); - mThread->launch(); - } -} - -void FileWatcherFSEvents::run() -{ - mRunLoopRef = CFRunLoopGetCurrent(); - - while ( mInitOK ) - { - if ( !mNeedInit.empty() ) - { - for ( std::list<WatcherFSEvents*>::iterator it = mNeedInit.begin(); it != mNeedInit.end(); ++it ) - { - (*it)->initAsync(); - } - - mNeedInit.clear(); - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut ); - } +void FileWatcherFSEvents::watch() {} - CFRunLoopStop( mRunLoopRef ); - mRunLoopRef = NULL; -} - -void FileWatcherFSEvents::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) -{ +void FileWatcherFSEvents::handleAction( Watcher* watch, const std::string& filename, + unsigned long action, std::string oldFilename ) { /// Not used } -std::list<std::string> FileWatcherFSEvents::directories() -{ - std::list<std::string> dirs; +std::vector<std::string> FileWatcherFSEvents::directories() { + std::vector<std::string> dirs; Lock lock( mWatchesLock ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { + dirs.reserve( mWatches.size() ); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { dirs.push_back( std::string( it->second->Directory ) ); } return dirs; } -bool FileWatcherFSEvents::pathInWatches( const std::string& path ) -{ - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - if ( it->second->Directory == path ) - { +bool FileWatcherFSEvents::pathInWatches( const std::string& path ) { + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( it->second->Directory == path ) { return true; } } @@ -265,6 +198,6 @@ bool FileWatcherFSEvents::pathInWatches( const std::string& path ) return false; } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp index 9a2c956ed10..5ad182ed43f 100644 --- a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp @@ -7,98 +7,94 @@ #include <CoreFoundation/CoreFoundation.h> #include <CoreServices/CoreServices.h> +#include <dispatch/dispatch.h> #include <efsw/WatcherFSEvents.hpp> #include <map> -#include <list> #include <vector> +#include <condition_variable> +#include <mutex> -namespace efsw -{ +namespace efsw { /* OSX < 10.7 has no file events */ /* So i declare the events constants */ -enum FSEventEvents -{ - efswFSEventStreamCreateFlagFileEvents = 0x00000010, - efswFSEventStreamEventFlagItemCreated = 0x00000100, - efswFSEventStreamEventFlagItemRemoved = 0x00000200, - efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, - efswFSEventStreamEventFlagItemRenamed = 0x00000800, - efswFSEventStreamEventFlagItemModified = 0x00001000, - efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, - efswFSEventStreamEventFlagItemChangeOwner = 0x00004000, - efswFSEventStreamEventFlagItemXattrMod = 0x00008000, - efswFSEventStreamEventFlagItemIsFile = 0x00010000, - efswFSEventStreamEventFlagItemIsDir = 0x00020000, - efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, - efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | - efswFSEventStreamEventFlagItemModified | - efswFSEventStreamEventFlagItemInodeMetaMod +enum FSEventEvents { + efswFSEventStreamCreateFlagNoDefer = 0x00000002, + efswFSEventStreamCreateFlagFileEvents = 0x00000010, + efswFSEventStreamEventFlagItemCreated = 0x00000100, + efswFSEventStreamEventFlagItemRemoved = 0x00000200, + efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, + efswFSEventStreamEventFlagItemRenamed = 0x00000800, + efswFSEventStreamEventFlagItemModified = 0x00001000, + efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, + efswFSEventStreamEventFlagItemChangeOwner = 0x00004000, + efswFSEventStreamEventFlagItemXattrMod = 0x00008000, + efswFSEventStreamEventFlagItemIsFile = 0x00010000, + efswFSEventStreamEventFlagItemIsDir = 0x00020000, + efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, + efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | + efswFSEventStreamEventFlagItemModified | + efswFSEventStreamEventFlagItemInodeMetaMod }; /// Implementation for Win32 based on ReadDirectoryChangesW. /// @class FileWatcherFSEvents -class FileWatcherFSEvents : public FileWatcherImpl -{ +class FileWatcherFSEvents : public FileWatcherImpl { friend class WatcherFSEvents; - public: - /// @return If FSEvents supports file-level notifications ( true if OS X >= 10.7 ) - static bool isGranular(); - - /// type for a map from WatchID to WatcherWin32 pointer - typedef std::map<WatchID, WatcherFSEvents*> WatchMap; - - FileWatcherFSEvents( FileWatcher * parent ); - - virtual ~FileWatcherFSEvents(); - - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); - - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - void removeWatch(const std::string& directory); - - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); - - /// Updates the watcher. Must be called often. - void watch(); - - /// Handles the action - void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); - - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - protected: - static void FSEventCallback( ConstFSEventStreamRef streamRef, - void *userData, - size_t numEvents, - void *eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[] - ); - - CFRunLoopRef mRunLoopRef; - - /// Vector of WatcherWin32 pointers - WatchMap mWatches; - - /// The last watchid - WatchID mLastWatchID; - - Thread * mThread; - - Mutex mWatchesLock; - - bool pathInWatches( const std::string& path ); - - std::list<WatcherFSEvents*> mNeedInit; - private: - void run(); + + public: + /// @return If FSEvents supports file-level notifications ( true if OS X >= 10.7 ) + static bool isGranular(); + + /// type for a map from WatchID to WatcherWin32 pointer + typedef std::map<WatchID, WatcherFSEvents*> WatchMap; + + FileWatcherFSEvents( FileWatcher* parent ); + + virtual ~FileWatcherFSEvents(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + const std::vector<WatcherOption> &options ) override; + + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch( const std::string& directory ) override; + + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ) override; + + /// Updates the watcher. Must be called often. + void watch() override; + + /// Handles the action + void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) override; + + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories() override; + + protected: + static void FSEventCallback( ConstFSEventStreamRef streamRef, void* userData, size_t numEvents, + void* eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[] ); + + /// Vector of WatcherWin32 pointers + WatchMap mWatches; + + /// The last watchid + WatchID mLastWatchID; + + Mutex mWatchesLock; + + bool pathInWatches( const std::string& path ) override; + + std::mutex mWatchesMutex; + std::condition_variable mWatchCond; + }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.cpp b/dep/efsw/src/efsw/FileWatcherGeneric.cpp index fd423b1476b..3f3c52e47fb 100644 --- a/dep/efsw/src/efsw/FileWatcherGeneric.cpp +++ b/dep/efsw/src/efsw/FileWatcherGeneric.cpp @@ -1,22 +1,17 @@ -#include <efsw/FileWatcherGeneric.hpp> #include <efsw/FileSystem.hpp> -#include <efsw/System.hpp> +#include <efsw/FileWatcherGeneric.hpp> #include <efsw/Lock.hpp> +#include <efsw/System.hpp> -namespace efsw -{ +namespace efsw { -FileWatcherGeneric::FileWatcherGeneric( FileWatcher * parent ) : - FileWatcherImpl( parent ), - mThread( NULL ), - mLastWatchID( 0 ) -{ +FileWatcherGeneric::FileWatcherGeneric( FileWatcher* parent ) : + FileWatcherImpl( parent ), mThread( NULL ), mLastWatchID( 0 ) { mInitOK = true; mIsGeneric = true; } -FileWatcherGeneric::~FileWatcherGeneric() -{ +FileWatcherGeneric::~FileWatcherGeneric() { mInitOK = false; efSAFE_DELETE( mThread ); @@ -24,161 +19,135 @@ FileWatcherGeneric::~FileWatcherGeneric() /// Delete the watches WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - efSAFE_DELETE( (*it) ); + for ( ; it != mWatches.end(); ++it ) { + efSAFE_DELETE( ( *it ) ); } } -WatchID FileWatcherGeneric::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) -{ +WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption>& options ) { std::string dir( directory ); FileSystem::dirAddSlashAtEnd( dir ); FileInfo fi( dir ); - if ( !fi.isDirectory() ) - { + if ( !fi.isDirectory() ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( !fi.isReadable() ) - { + } else if ( !fi.isReadable() ) { return Errors::Log::createLastError( Errors::FileNotReadable, dir ); - } - else if ( pathInWatches( dir ) ) - { + } else if ( pathInWatches( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, dir ); } std::string curPath; std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); - if ( "" != link ) - { - if ( pathInWatches( link ) ) - { + if ( "" != link ) { + if ( pathInWatches( link ) ) { return Errors::Log::createLastError( Errors::FileRepeated, dir ); - } - else if ( !linkAllowed( curPath, link ) ) - { + } else if ( !linkAllowed( curPath, link ) ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); - } - else - { + } else { dir = link; } } mLastWatchID++; - WatcherGeneric * pWatch = new WatcherGeneric( mLastWatchID, dir, watcher, this, recursive ); + WatcherGeneric* pWatch = new WatcherGeneric( mLastWatchID, dir, watcher, this, recursive ); Lock lock( mWatchesLock ); - mWatches.push_back(pWatch); + mWatches.push_back( pWatch ); return pWatch->ID; } -void FileWatcherGeneric::removeWatch( const std::string& directory ) -{ +void FileWatcherGeneric::removeWatch( const std::string& directory ) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - if ( (*it)->Directory == directory ) - { - WatcherGeneric * watch = (*it); + for ( ; it != mWatches.end(); ++it ) { + if ( ( *it )->Directory == directory ) { + WatcherGeneric* watch = ( *it ); Lock lock( mWatchesLock ); mWatches.erase( it ); - efSAFE_DELETE( watch ) ; + efSAFE_DELETE( watch ); return; } } } -void FileWatcherGeneric::removeWatch(WatchID watchid) -{ +void FileWatcherGeneric::removeWatch( WatchID watchid ) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - if ( (*it)->ID == watchid ) - { - WatcherGeneric * watch = (*it); + for ( ; it != mWatches.end(); ++it ) { + if ( ( *it )->ID == watchid ) { + WatcherGeneric* watch = ( *it ); Lock lock( mWatchesLock ); mWatches.erase( it ); - efSAFE_DELETE( watch ) ; + efSAFE_DELETE( watch ); return; } } } -void FileWatcherGeneric::watch() -{ - if ( NULL == mThread ) - { +void FileWatcherGeneric::watch() { + if ( NULL == mThread ) { mThread = new Thread( &FileWatcherGeneric::run, this ); mThread->launch(); } } -void FileWatcherGeneric::run() -{ - do - { +void FileWatcherGeneric::run() { + do { { - Lock lock( mWatchesLock); + Lock lock( mWatchesLock ); WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { + for ( ; it != mWatches.end(); ++it ) { ( *it )->watch(); } } - if ( mInitOK ) System::sleep( 1000 ); + if ( mInitOK ) + System::sleep( 1000 ); } while ( mInitOK ); } -void FileWatcherGeneric::handleAction(Watcher *, const std::string&, unsigned long, std::string) -{ +void FileWatcherGeneric::handleAction( Watcher*, const std::string&, unsigned long, std::string ) { /// Not used } -std::list<std::string> FileWatcherGeneric::directories() -{ - std::list<std::string> dirs; +std::vector<std::string> FileWatcherGeneric::directories() { + std::vector<std::string> dirs; Lock lock( mWatchesLock ); + dirs.reserve( mWatches.size() ); + WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - dirs.push_back( (*it)->Directory ); + for ( ; it != mWatches.end(); ++it ) { + dirs.push_back( ( *it )->Directory ); } return dirs; } -bool FileWatcherGeneric::pathInWatches( const std::string& path ) -{ +bool FileWatcherGeneric::pathInWatches( const std::string& path ) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - if ( (*it)->Directory == path || (*it)->pathInWatches( path ) ) - { + for ( ; it != mWatches.end(); ++it ) { + if ( ( *it )->Directory == path || ( *it )->pathInWatches( path ) ) { return true; } } @@ -186,4 +155,4 @@ bool FileWatcherGeneric::pathInWatches( const std::string& path ) return false; } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.hpp b/dep/efsw/src/efsw/FileWatcherGeneric.hpp index fc9826580ab..47f7e04718d 100644 --- a/dep/efsw/src/efsw/FileWatcherGeneric.hpp +++ b/dep/efsw/src/efsw/FileWatcherGeneric.hpp @@ -1,59 +1,61 @@ #ifndef EFSW_FILEWATCHERGENERIC_HPP #define EFSW_FILEWATCHERGENERIC_HPP +#include <efsw/DirWatcherGeneric.hpp> #include <efsw/FileWatcherImpl.hpp> #include <efsw/WatcherGeneric.hpp> -#include <efsw/DirWatcherGeneric.hpp> -#include <list> +#include <vector> -namespace efsw -{ +namespace efsw { /// Implementation for Generic File Watcher. /// @class FileWatcherGeneric -class FileWatcherGeneric : public FileWatcherImpl -{ - public: - typedef std::list<WatcherGeneric*> WatchList; +class FileWatcherGeneric : public FileWatcherImpl { + public: + typedef std::vector<WatcherGeneric*> WatchList; + + FileWatcherGeneric( FileWatcher* parent ); + + virtual ~FileWatcherGeneric(); - FileWatcherGeneric( FileWatcher * parent ); + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + const std::vector<WatcherOption> &options ) override; - virtual ~FileWatcherGeneric(); + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch( const std::string& directory ) override; - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ) override; - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - void removeWatch(const std::string& directory); + /// Updates the watcher. Must be called often. + void watch() override; - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); + /// Handles the action + void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) override; - /// Updates the watcher. Must be called often. - void watch(); + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories() override; - /// Handles the action - void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + protected: + Thread* mThread; - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - protected: - Thread * mThread; + /// The last watchid + WatchID mLastWatchID; - /// The last watchid - WatchID mLastWatchID; + /// Map of WatchID to WatchStruct pointers + WatchList mWatches; - /// Map of WatchID to WatchStruct pointers - WatchList mWatches; + Mutex mWatchesLock; - Mutex mWatchesLock; + bool pathInWatches( const std::string& path ) override; - bool pathInWatches( const std::string& path ); - private: - void run(); + private: + void run(); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherImpl.cpp b/dep/efsw/src/efsw/FileWatcherImpl.cpp index e6e0fc72a13..f8313daba8d 100644 --- a/dep/efsw/src/efsw/FileWatcherImpl.cpp +++ b/dep/efsw/src/efsw/FileWatcherImpl.cpp @@ -4,26 +4,31 @@ namespace efsw { -FileWatcherImpl::FileWatcherImpl( FileWatcher * parent ) : - mFileWatcher( parent ), - mInitOK( false ), - mIsGeneric( false ) -{ +FileWatcherImpl::FileWatcherImpl( FileWatcher* parent ) : + mFileWatcher( parent ), mInitOK( false ), mIsGeneric( false ) { System::maxFD(); } -FileWatcherImpl::~FileWatcherImpl() -{ -} +FileWatcherImpl::~FileWatcherImpl() {} -bool FileWatcherImpl::initOK() -{ - return mInitOK; +bool FileWatcherImpl::initOK() { + return static_cast<bool>( mInitOK ); } -bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) -{ - return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || -1 != String::strStartsWith( curPath, link ); +bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) { + return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || + -1 != String::strStartsWith( curPath, link ); } +int FileWatcherImpl::getOptionValue( const std::vector<WatcherOption>& options, Option option, + int defaultValue ) { + for ( size_t i = 0; i < options.size(); i++ ) { + if ( options[i].mOption == option ) { + return options[i].mValue; + } + } + + return defaultValue; } + +} // namespace efsw diff --git a/dep/efsw/src/efsw/FileWatcherImpl.hpp b/dep/efsw/src/efsw/FileWatcherImpl.hpp index 8f472bf56c5..d82209c902c 100644 --- a/dep/efsw/src/efsw/FileWatcherImpl.hpp +++ b/dep/efsw/src/efsw/FileWatcherImpl.hpp @@ -1,54 +1,64 @@ #ifndef EFSW_FILEWATCHERIMPL_HPP #define EFSW_FILEWATCHERIMPL_HPP +#include <efsw/Atomic.hpp> +#include <efsw/Mutex.hpp> +#include <efsw/Thread.hpp> +#include <efsw/Watcher.hpp> #include <efsw/base.hpp> #include <efsw/efsw.hpp> -#include <efsw/Watcher.hpp> -#include <efsw/Thread.hpp> -#include <efsw/Mutex.hpp> namespace efsw { -class FileWatcherImpl -{ - public: - FileWatcherImpl( FileWatcher * parent ); +class FileWatcherImpl { + public: + FileWatcherImpl( FileWatcher* parent ); + + virtual ~FileWatcherImpl(); + + /// Add a directory watch + /// On error returns WatchID with Error type. + virtual WatchID addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption>& options = {} ) = 0; - virtual ~FileWatcherImpl(); + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + virtual void removeWatch( const std::string& directory ) = 0; - /// Add a directory watch - /// On error returns WatchID with Error type. - virtual WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) = 0; + /// Remove a directory watch. This is a map lookup O(logn). + virtual void removeWatch( WatchID watchid ) = 0; - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - virtual void removeWatch(const std::string& directory) = 0; + /// Updates the watcher. Must be called often. + virtual void watch() = 0; - /// Remove a directory watch. This is a map lookup O(logn). - virtual void removeWatch(WatchID watchid) = 0; + /// Handles the action + virtual void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) = 0; - /// Updates the watcher. Must be called often. - virtual void watch() = 0; + /// @return Returns a list of the directories that are being watched + virtual std::vector<std::string> directories() = 0; - /// Handles the action - virtual void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = "") = 0; + /// @return true if the backend init successfully + virtual bool initOK(); - /// @return Returns a list of the directories that are being watched - virtual std::list<std::string> directories() = 0; + /// @return If the link is allowed according to the current path and the state of out scope + /// links + virtual bool linkAllowed( const std::string& curPath, const std::string& link ); - /// @return true if the backend init successfully - virtual bool initOK(); + /// Search if a directory already exists in the watches + virtual bool pathInWatches( const std::string& path ) = 0; - /// @return If the link is allowed according to the current path and the state of out scope links - virtual bool linkAllowed( const std::string& curPath, const std::string& link ); + protected: + friend class FileWatcher; + friend class DirWatcherGeneric; - /// Search if a directory already exists in the watches - virtual bool pathInWatches( const std::string& path ) = 0; + FileWatcher* mFileWatcher; + Atomic<bool> mInitOK; + bool mIsGeneric; - FileWatcher * mFileWatcher; - bool mInitOK; - bool mIsGeneric; + int getOptionValue( const std::vector<WatcherOption>& options, Option option, + int defaultValue ); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp index 71ae3bcd97d..29be12b6262 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.cpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp @@ -1,13 +1,14 @@ +#include <algorithm> #include <efsw/FileWatcherInotify.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY -#include <unistd.h> -#include <sys/stat.h> +#include <errno.h> #include <fcntl.h> -#include <string.h> #include <stdio.h> -#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> #ifdef EFSW_INOTIFY_NOSYS #include <efsw/inotify-nosys.h> @@ -15,84 +16,81 @@ #include <sys/inotify.h> #endif -#include <efsw/FileSystem.hpp> -#include <efsw/System.hpp> #include <efsw/Debug.hpp> +#include <efsw/FileSystem.hpp> #include <efsw/Lock.hpp> #include <efsw/String.hpp> +#include <efsw/System.hpp> -#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024) +#define BUFF_SIZE ( ( sizeof( struct inotify_event ) + FILENAME_MAX ) * 1024 ) -namespace efsw -{ +namespace efsw { -FileWatcherInotify::FileWatcherInotify( FileWatcher * parent ) : - FileWatcherImpl( parent ), - mFD(-1), - mThread(NULL) -{ +FileWatcherInotify::FileWatcherInotify( FileWatcher* parent ) : + FileWatcherImpl( parent ), mFD( -1 ), mThread( NULL ), mIsTakingAction( false ) { mFD = inotify_init(); - if (mFD < 0) - { - efDEBUG( "Error: %s\n", strerror(errno) ); - } - else - { + if ( mFD < 0 ) { + efDEBUG( "Error: %s\n", strerror( errno ) ); + } else { mInitOK = true; } } -FileWatcherInotify::~FileWatcherInotify() -{ +FileWatcherInotify::~FileWatcherInotify() { mInitOK = false; + // There is deadlock when release FileWatcherInotify instance since its handAction + // function is still running and hangs in requiring lock without init lock captured. + while ( mIsTakingAction ) { + // It'd use condition-wait instead of sleep. Actually efsw has no such + // implementation so we just skip and sleep while for that to avoid deadlock. + usleep( 1000 ); + }; + Lock initLock( mInitLock ); efSAFE_DELETE( mThread ); - + + Lock l( mWatchesLock ); + Lock l2( mRealWatchesLock ); + WatchMap::iterator iter = mWatches.begin(); WatchMap::iterator end = mWatches.end(); - for(; iter != end; ++iter) - { + for ( ; iter != end; ++iter ) { efSAFE_DELETE( iter->second ); } mWatches.clear(); - if ( mFD != -1 ) - { - close(mFD); + if ( mFD != -1 ) { + close( mFD ); mFD = -1; } } -WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ) -{ +WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption>& ) { + if ( !mInitOK ) + return Errors::Log::createLastError( Errors::Unspecified, directory ); + Lock initLock( mInitLock ); return addWatch( directory, watcher, recursive, NULL ); } -WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent ) -{ +WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, WatcherInotify* parent ) { std::string dir( directory ); FileSystem::dirAddSlashAtEnd( dir ); FileInfo fi( dir ); - if ( !fi.isDirectory() ) - { + if ( !fi.isDirectory() ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( !fi.isReadable() ) - { + } else if ( !fi.isReadable() ) { return Errors::Log::createLastError( Errors::FileNotReadable, dir ); - } - else if ( pathInWatches( dir ) ) - { + } else if ( pathInWatches( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); - } - else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) - { + } else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) { return Errors::Log::createLastError( Errors::FileRemote, dir ); } @@ -100,74 +98,68 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis std::string curPath; std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); - if ( "" != link ) - { + if ( "" != link ) { /// Avoid adding symlinks directories if it's now enabled - if ( NULL != parent && !mFileWatcher->followSymlinks() ) - { + if ( NULL != parent && !mFileWatcher->followSymlinks() ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); } /// If it's a symlink check if the realpath exists as a watcher, or /// if the path is outside the current dir - if ( pathInWatches( link ) ) - { + if ( pathInWatches( link ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); - } - else if ( !linkAllowed( curPath, link ) ) - { + } else if ( !linkAllowed( curPath, link ) ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); - } - else - { + } else { dir = link; } } - int wd = inotify_add_watch (mFD, dir.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | IN_DELETE | IN_MODIFY); + int wd = inotify_add_watch( mFD, dir.c_str(), + IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | + IN_DELETE | IN_MODIFY ); - if ( wd < 0 ) - { - if( errno == ENOENT ) - { + if ( wd < 0 ) { + if ( errno == ENOENT ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else - { - return Errors::Log::createLastError( Errors::Unspecified, std::string(strerror(errno)) ); + } else { + return Errors::Log::createLastError( Errors::Unspecified, + std::string( strerror( errno ) ) ); } } efDEBUG( "Added watch %s with id: %d\n", dir.c_str(), wd ); - WatcherInotify * pWatch = new WatcherInotify(); - pWatch->Listener = watcher; - pWatch->ID = wd; - pWatch->Directory = dir; - pWatch->Recursive = recursive; - pWatch->Parent = parent; + WatcherInotify* pWatch = new WatcherInotify(); + pWatch->Listener = watcher; + pWatch->ID = parent ? parent->ID : wd; + pWatch->InotifyID = wd; + pWatch->Directory = dir; + pWatch->Recursive = recursive; + pWatch->Parent = parent; { Lock lock( mWatchesLock ); - mWatches.insert(std::make_pair(wd, pWatch)); + mWatches.insert( std::make_pair( wd, pWatch ) ); + mWatchesRef[pWatch->Directory] = wd; } - if ( NULL == pWatch->Parent ) - { - mRealWatches[ pWatch->ID ] = pWatch; + if ( NULL == pWatch->Parent ) { + Lock l( mRealWatchesLock ); + mRealWatches[pWatch->InotifyID] = pWatch; } - if ( pWatch->Recursive ) - { + if ( pWatch->Recursive ) { std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory ); std::map<std::string, FileInfo>::iterator it = files.begin(); - for ( ; it != files.end(); ++it ) - { + for ( ; it != files.end(); ++it ) { + if ( !mInitOK ) + break; + const FileInfo& cfi = it->second; - if ( cfi.isDirectory() && cfi.isReadable() ) - { + if ( cfi.isDirectory() && cfi.isReadable() ) { addWatch( cfi.Filepath, watcher, recursive, pWatch ); } } @@ -176,401 +168,395 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis return wd; } -void FileWatcherInotify::removeWatchLocked(WatchID watchid) -{ +void FileWatcherInotify::removeWatchLocked( WatchID watchid ) { WatchMap::iterator iter = mWatches.find( watchid ); + if ( iter == mWatches.end() ) + return; - WatcherInotify * watch = iter->second; + WatcherInotify* watch = iter->second; - if ( watch->Recursive ) - { + for ( std::vector<std::pair<WatcherInotify*, std::string>>::iterator itm = + mMovedOutsideWatches.begin(); + mMovedOutsideWatches.end() != itm; ++itm ) { + if ( itm->first == watch ) { + mMovedOutsideWatches.erase( itm ); + break; + } + } + + if ( watch->Recursive && NULL == watch->Parent ) { WatchMap::iterator it = mWatches.begin(); - std::list<WatchID> eraseWatches; + std::vector<WatchID> eraseWatches; - for(; it != mWatches.end(); ++it) - { - if ( it->second != watch && - it->second->inParentTree( watch ) - ) - { - eraseWatches.push_back( it->second->ID ); - } - } + for ( ; it != mWatches.end(); ++it ) + if ( it->second != watch && it->second->inParentTree( watch ) ) + eraseWatches.push_back( it->second->InotifyID ); - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) - { + for ( std::vector<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); + ++eit ) { removeWatch( *eit ); } } + mWatchesRef.erase( watch->Directory ); mWatches.erase( iter ); - if ( NULL == watch->Parent ) - { - WatchMap::iterator eraseit = mRealWatches.find( watch->ID ); + if ( NULL == watch->Parent ) { + WatchMap::iterator eraseit = mRealWatches.find( watch->InotifyID ); - if ( eraseit != mRealWatches.end() ) - { + if ( eraseit != mRealWatches.end() ) { mRealWatches.erase( eraseit ); } } - int err = inotify_rm_watch(mFD, watchid); + int err = inotify_rm_watch( mFD, watchid ); - if ( err < 0 ) - { - efDEBUG( "Error removing watch %d: %s\n", watchid, strerror(errno) ); - } - else - { + if ( err < 0 ) { + efDEBUG( "Error removing watch %d: %s\n", watchid, strerror( errno ) ); + } else { efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watchid ); } efSAFE_DELETE( watch ); } -void FileWatcherInotify::removeWatch(const std::string& directory) -{ +void FileWatcherInotify::removeWatch( const std::string& directory ) { + if ( !mInitOK ) + return; + Lock initLock( mInitLock ); Lock lock( mWatchesLock ); + Lock l( mRealWatchesLock ); - WatchMap::iterator iter = mWatches.begin(); - - for(; iter != mWatches.end(); ++iter) - { - if( directory == iter->second->Directory ) - { - WatcherInotify * watch = iter->second; - - if ( watch->Recursive ) - { - WatchMap::iterator it = mWatches.begin(); - std::list<WatchID> eraseWatches; - - for(; it != mWatches.end(); ++it) - { - if ( it->second->inParentTree( watch ) ) - { - eraseWatches.push_back( it->second->ID ); - } - } - - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) - { - removeWatchLocked( *eit ); - } - } - - mWatches.erase( iter ); - - if ( NULL == watch->Parent ) - { - WatchMap::iterator eraseit = mRealWatches.find( watch->ID ); - - if ( eraseit != mRealWatches.end() ) - { - mRealWatches.erase( eraseit ); - } - } - - int err = inotify_rm_watch(mFD, watch->ID); - - if ( err < 0 ) - { - efDEBUG( "Error removing watch %d: %s\n", watch->ID, strerror(errno) ); - } - else - { - efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watch->ID ); - } - - efSAFE_DELETE( watch ); + std::unordered_map<std::string, WatchID>::iterator ref = mWatchesRef.find( directory ); + if ( ref == mWatchesRef.end() ) + return; - break; - } - } + removeWatchLocked( ref->second ); } -void FileWatcherInotify::removeWatch( WatchID watchid ) -{ - Lock lock( mWatchesLock ); - - WatchMap::iterator iter = mWatches.find( watchid ); - - if( iter == mWatches.end() ) - { +void FileWatcherInotify::removeWatch( WatchID watchid ) { + if ( !mInitOK ) return; - } - + Lock initLock( mInitLock ); + Lock lock( mWatchesLock ); removeWatchLocked( watchid ); } -void FileWatcherInotify::watch() -{ - if ( NULL == mThread ) - { +void FileWatcherInotify::watch() { + if ( NULL == mThread ) { mThread = new Thread( &FileWatcherInotify::run, this ); mThread->launch(); } } -Watcher * FileWatcherInotify::watcherContainsDirectory( std::string dir ) -{ +Watcher* FileWatcherInotify::watcherContainsDirectory( std::string dir ) { FileSystem::dirRemoveSlashAtEnd( dir ); std::string watcherPath = FileSystem::pathRemoveFileName( dir ); FileSystem::dirAddSlashAtEnd( watcherPath ); + Lock lock( mWatchesLock ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - Watcher * watcher = it->second; - + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + Watcher* watcher = it->second; if ( watcher->Directory == watcherPath ) - { return watcher; - } } return NULL; } -void FileWatcherInotify::run() -{ - static char buff[BUFF_SIZE] = {0}; +void FileWatcherInotify::run() { + char* buff = new char[BUFF_SIZE]; + memset( buff, 0, BUFF_SIZE ); WatchMap::iterator wit; - std::list<WatcherInotify*> movedOutsideWatches; - do - { + WatcherInotify* currentMoveFrom = NULL; + u_int32_t currentMoveCookie = -1; + bool lastWasMovedFrom = false; + std::string prevOldFileName; + + do { fd_set rfds; - FD_ZERO (&rfds); - FD_SET (mFD, &rfds); + FD_ZERO( &rfds ); + FD_SET( mFD, &rfds ); timeval timeout; - timeout.tv_sec=0; - timeout.tv_usec=100000; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; - if( select (FD_SETSIZE, &rfds, NULL, NULL, &timeout) > 0 ) - { + if ( select( FD_SETSIZE, &rfds, NULL, NULL, &timeout ) > 0 ) { ssize_t len; - len = read (mFD, buff, BUFF_SIZE); + len = read( mFD, buff, BUFF_SIZE ); - if (len != -1) - { + if ( len != -1 ) { ssize_t i = 0; - while (i < len) - { - struct inotify_event *pevent = (struct inotify_event *)&buff[i]; + while ( i < len ) { + struct inotify_event* pevent = (struct inotify_event*)&buff[i]; { - Lock lock( mWatchesLock ); + { + Lock lock( mWatchesLock ); - wit = mWatches.find( pevent->wd ); + wit = mWatches.find( pevent->wd ); + } - if ( wit != mWatches.end() ) - { - handleAction(wit->second, pevent->name, pevent->mask); + if ( wit != mWatches.end() ) { + handleAction( wit->second, (char*)pevent->name, pevent->mask ); + + if ( ( pevent->mask & IN_MOVED_TO ) && wit->second == currentMoveFrom && + pevent->cookie == currentMoveCookie ) { + /// make pair success + currentMoveFrom = NULL; + currentMoveCookie = -1; + } else if ( pevent->mask & IN_MOVED_FROM ) { + // Previous event was moved from and current event is moved from + // Treat it as a DELETE or moved ouside watches + if ( lastWasMovedFrom && currentMoveFrom ) { + mMovedOutsideWatches.push_back( + std::make_pair( currentMoveFrom, prevOldFileName ) ); + } + + currentMoveFrom = wit->second; + currentMoveCookie = pevent->cookie; + } else { + /// Keep track of the IN_MOVED_FROM events to know + /// if the IN_MOVED_TO event is also fired + if ( currentMoveFrom ) { + mMovedOutsideWatches.push_back( + std::make_pair( currentMoveFrom, prevOldFileName ) ); + } - /// Keep track of the IN_MOVED_FROM events to know if the IN_MOVED_TO event is also fired - if ( !wit->second->OldFileName.empty() ) - { - movedOutsideWatches.push_back( wit->second ); + currentMoveFrom = NULL; + currentMoveCookie = -1; } } + + lastWasMovedFrom = ( pevent->mask & IN_MOVED_FROM ) != 0; + if ( pevent->mask & IN_MOVED_FROM ) + prevOldFileName = std::string( (char*)pevent->name ); } - i += sizeof(struct inotify_event) + pevent->len; + i += sizeof( struct inotify_event ) + pevent->len; } + } + } else { + // Here means no event received + // If last event is IN_MOVED_FROM, we assume no IN_MOVED_TO + if ( currentMoveFrom ) { + mMovedOutsideWatches.push_back( + std::make_pair( currentMoveFrom, currentMoveFrom->OldFileName ) ); + } - if ( !movedOutsideWatches.empty() ) - { - /// In case that the IN_MOVED_TO is never fired means that the file was moved to other folder - for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); ++it ) - { - Watcher * watch = (*it); - - if ( !watch->OldFileName.empty() ) - { - /// Check if the file move was a folder already being watched - std::list<Watcher*> eraseWatches; - - for(; wit != mWatches.end(); ++wit) - { - Watcher * oldWatch = wit->second; + currentMoveFrom = NULL; + currentMoveCookie = -1; + } - if ( oldWatch != watch && - -1 != String::strStartsWith( watch->Directory + watch->OldFileName + "/", oldWatch->Directory ) ) - { - eraseWatches.push_back( oldWatch ); - } - } + if ( !mMovedOutsideWatches.empty() ) { + // We need to make a copy since the element mMovedOutsideWatches could be modified + // during the iteration. + std::vector<std::pair<WatcherInotify*, std::string>> movedOutsideWatches( + mMovedOutsideWatches ); + + /// In case that the IN_MOVED_TO is never fired means that the file was moved to other + /// folder + for ( std::vector<std::pair<WatcherInotify*, std::string>>::iterator it = + movedOutsideWatches.begin(); + it != movedOutsideWatches.end(); ++it ) { + + // Skip if the watch has already being removed + if ( mMovedOutsideWatches.size() != movedOutsideWatches.size() ) { + bool found = false; + for ( std::vector<std::pair<WatcherInotify*, std::string>>::iterator itm = + mMovedOutsideWatches.begin(); + mMovedOutsideWatches.end() != itm; ++itm ) { + if ( itm->first == it->first ) { + found = true; + break; + } + } + if ( !found ) + continue; + } - /// Remove invalid watches - eraseWatches.sort(); + Watcher* watch = ( *it ).first; + const std::string& oldFileName = ( *it ).second; - for ( std::list<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); eit != eraseWatches.rend(); ++eit ) - { - Watcher * rmWatch = *eit; + /// Check if the file move was a folder already being watched + std::vector<Watcher*> eraseWatches; - /// Create Delete event for removed watches that have been moved too - if ( Watcher * cntWatch = watcherContainsDirectory( rmWatch->Directory ) ) - { - handleAction( cntWatch, FileSystem::fileNameFromPath( rmWatch->Directory ), IN_DELETE ); - } + { + Lock lock( mWatchesLock ); - removeWatch( rmWatch->ID ); - } + for ( ; wit != mWatches.end(); ++wit ) { + Watcher* oldWatch = wit->second; - /// Remove the OldFileName - watch->OldFileName = ""; + if ( oldWatch != watch && + -1 != String::strStartsWith( watch->Directory + oldFileName + "/", + oldWatch->Directory ) ) { + eraseWatches.push_back( oldWatch ); } } + } - movedOutsideWatches.clear(); + /// Remove invalid watches + std::stable_sort( eraseWatches.begin(), eraseWatches.end(), + []( const Watcher* left, const Watcher* right ) { + return left->Directory < right->Directory; + } ); + + if ( eraseWatches.empty() ) { + handleAction( watch, oldFileName, IN_DELETE ); + } else { + for ( std::vector<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); + eit != eraseWatches.rend(); ++eit ) { + Watcher* rmWatch = *eit; + + /// Create Delete event for removed watches that have been moved too + if ( Watcher* cntWatch = watcherContainsDirectory( rmWatch->Directory ) ) { + handleAction( cntWatch, + FileSystem::fileNameFromPath( rmWatch->Directory ), + IN_DELETE ); + } + } } } + + mMovedOutsideWatches.clear(); } - } while( mInitOK ); + } while ( mInitOK ); + + delete[] buff; } -void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) -{ +void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) { FileSystem::dirAddSlashAtEnd( fpath ); /// If the watcher is recursive, checks if the new file is a folder, and creates a watcher - if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) - { + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { bool found = false; - /// First check if exists - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { - if ( it->second->Directory == fpath ) - { - found = true; - break; + Lock lock( mWatchesLock ); + + /// First check if exists + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( it->second->Directory == fpath ) { + found = true; + break; + } } } - if ( !found ) - { - addWatch( fpath, watch->Listener, watch->Recursive, static_cast<WatcherInotify*>( watch ) ); + if ( !found ) { + addWatch( fpath, watch->Listener, watch->Recursive, + static_cast<WatcherInotify*>( watch ) ); } } } -void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string ) -{ - if ( !watch || !watch->Listener ) - { +void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, + unsigned long action, std::string ) { + if ( !watch || !watch->Listener || !mInitOK ) { return; } + mIsTakingAction = true; + Lock initLock( mInitLock ); std::string fpath( watch->Directory + filename ); - if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) - { - watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified ); - } - else if( IN_MOVED_TO & action ) - { - /// If OldFileName doesn't exist means that the file has been moved from other folder, so we just send the Add event - if ( watch->OldFileName.empty() ) - { - watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add ); + if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) ) { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, + Actions::Modified ); + } else if ( IN_MOVED_TO & action ) { + /// If OldFileName doesn't exist means that the file has been moved from other folder, so we + /// just send the Add event + if ( watch->OldFileName.empty() ) { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, + Actions::Add ); - watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified ); + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, + Actions::Modified ); checkForNewWatcher( watch, fpath ); - } - else - { - watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Moved, watch->OldFileName ); + } else { + watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, + Actions::Moved, watch->OldFileName ); } - if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) - { + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { /// Update the new directory path std::string opath( watch->Directory + watch->OldFileName ); FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( fpath ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - if ( it->second->Directory == opath && it->second->DirInfo.Inode == FileInfo( opath ).Inode ) - { - it->second->Directory = fpath; - it->second->DirInfo = FileInfo( fpath ); + Lock lock( mWatchesLock ); - break; + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( it->second->Directory == opath ) { + it->second->Directory = fpath; + it->second->DirInfo = FileInfo( fpath ); + } else if ( -1 != String::strStartsWith( opath, it->second->Directory ) ) { + it->second->Directory = fpath + it->second->Directory.substr( opath.size() ); + it->second->DirInfo.Filepath = it->second->Directory; } } } watch->OldFileName = ""; - } - else if( IN_CREATE & action ) - { + } else if ( IN_CREATE & action ) { watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add ); checkForNewWatcher( watch, fpath ); - } - else if ( IN_MOVED_FROM & action ) - { + } else if ( IN_MOVED_FROM & action ) { watch->OldFileName = filename; - } - else if( IN_DELETE & action ) - { + } else if ( IN_DELETE & action ) { watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Delete ); FileSystem::dirAddSlashAtEnd( fpath ); /// If the file erased is a directory and recursive is enabled, removes the directory erased - if ( watch->Recursive ) - { - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - if ( it->second->Directory == fpath ) - { - removeWatch( it->second->ID ); + if ( watch->Recursive ) { + Lock l( mWatchesLock ); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( it->second->Directory == fpath ) { + removeWatchLocked( it->second->InotifyID ); break; } } } } + mIsTakingAction = false; } -std::list<std::string> FileWatcherInotify::directories() -{ - std::list<std::string> dirs; +std::vector<std::string> FileWatcherInotify::directories() { + std::vector<std::string> dirs; - Lock lock( mWatchesLock ); + Lock l( mRealWatchesLock ); + + dirs.reserve( mRealWatches.size() ); WatchMap::iterator it = mRealWatches.begin(); for ( ; it != mRealWatches.end(); ++it ) - { dirs.push_back( it->second->Directory ); - } return dirs; } -bool FileWatcherInotify::pathInWatches( const std::string& path ) -{ +bool FileWatcherInotify::pathInWatches( const std::string& path ) { + Lock l( mRealWatchesLock ); + /// Search in the real watches, since it must allow adding a watch already watched as a subdir WatchMap::iterator it = mRealWatches.begin(); for ( ; it != mRealWatches.end(); ++it ) - { if ( it->second->Directory == path ) - { return true; - } - } return false; } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherInotify.hpp b/dep/efsw/src/efsw/FileWatcherInotify.hpp index b68314050a1..84174a0676a 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.hpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.hpp @@ -7,68 +7,79 @@ #include <efsw/WatcherInotify.hpp> #include <map> +#include <unordered_map> +#include <vector> -namespace efsw -{ +namespace efsw { /// Implementation for Linux based on inotify. /// @class FileWatcherInotify -class FileWatcherInotify : public FileWatcherImpl -{ - public: - /// type for a map from WatchID to WatchStruct pointer - typedef std::map<WatchID, WatcherInotify*> WatchMap; +class FileWatcherInotify : public FileWatcherImpl { + public: + /// type for a map from WatchID to WatchStruct pointer + typedef std::map<WatchID, WatcherInotify*> WatchMap; - FileWatcherInotify( FileWatcher * parent ); + FileWatcherInotify( FileWatcher* parent ); - virtual ~FileWatcherInotify(); + virtual ~FileWatcherInotify(); - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + const std::vector<WatcherOption>& options ) override; - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - void removeWatch(const std::string& directory); + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch( const std::string& directory ) override; - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ) override; - /// Updates the watcher. Must be called often. - void watch(); + /// Updates the watcher. Must be called often. + void watch() override; - /// Handles the action - void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + /// Handles the action + void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) override; - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - protected: - /// Map of WatchID to WatchStruct pointers - WatchMap mWatches; + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories() override; - /// User added watches - WatchMap mRealWatches; + protected: + /// Map of WatchID to WatchStruct pointers + WatchMap mWatches; - /// inotify file descriptor - int mFD; + /// User added watches + WatchMap mRealWatches; - Thread * mThread; + std::unordered_map<std::string, WatchID> mWatchesRef; - Mutex mWatchesLock; + /// inotify file descriptor + int mFD; - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent = NULL ); + Thread* mThread; - bool pathInWatches( const std::string& path ); - private: - void run(); + Mutex mWatchesLock; + Mutex mRealWatchesLock; + Mutex mInitLock; + bool mIsTakingAction; + std::vector<std::pair<WatcherInotify*, std::string>> mMovedOutsideWatches; - void removeWatchLocked(WatchID watchid); + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + WatcherInotify* parent = NULL ); - void checkForNewWatcher( Watcher* watch, std::string fpath ); + bool pathInWatches( const std::string& path ) override; - Watcher * watcherContainsDirectory( std::string dir ); + private: + void run(); + + void removeWatchLocked( WatchID watchid ); + + void checkForNewWatcher( Watcher* watch, std::string fpath ); + + Watcher* watcherContainsDirectory( std::string dir ); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.cpp b/dep/efsw/src/efsw/FileWatcherKqueue.cpp index 3373a68d0ce..32ef3dc82c8 100644 --- a/dep/efsw/src/efsw/FileWatcherKqueue.cpp +++ b/dep/efsw/src/efsw/FileWatcherKqueue.cpp @@ -2,42 +2,38 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS -#include <sys/time.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> #include <dirent.h> -#include <string.h> +#include <efsw/Debug.hpp> #include <efsw/FileSystem.hpp> +#include <efsw/Lock.hpp> #include <efsw/System.hpp> -#include <efsw/Debug.hpp> #include <efsw/WatcherGeneric.hpp> -#include <efsw/Lock.hpp> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <unistd.h> -namespace efsw -{ +namespace efsw { -FileWatcherKqueue::FileWatcherKqueue( FileWatcher * parent ) : +FileWatcherKqueue::FileWatcherKqueue( FileWatcher* parent ) : FileWatcherImpl( parent ), - mLastWatchID(0), + mLastWatchID( 0 ), mThread( NULL ), mFileDescriptorCount( 1 ), - mAddingWatcher( false ) -{ - mTimeOut.tv_sec = 0; - mTimeOut.tv_nsec = 0; - mInitOK = true; + mAddingWatcher( false ) { + mTimeOut.tv_sec = 0; + mTimeOut.tv_nsec = 0; + mInitOK = true; } -FileWatcherKqueue::~FileWatcherKqueue() -{ +FileWatcherKqueue::~FileWatcherKqueue() { WatchMap::iterator iter = mWatches.begin(); - for(; iter != mWatches.end(); ++iter) - { + for ( ; iter != mWatches.end(); ++iter ) { efSAFE_DELETE( iter->second ); } @@ -48,8 +44,8 @@ FileWatcherKqueue::~FileWatcherKqueue() efSAFE_DELETE( mThread ); } -WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) -{ +WatchID FileWatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption>& options ) { static bool s_ug = false; std::string dir( directory ); @@ -58,55 +54,43 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe FileInfo fi( dir ); - if ( !fi.isDirectory() ) - { + if ( !fi.isDirectory() ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( !fi.isReadable() ) - { + } else if ( !fi.isReadable() ) { return Errors::Log::createLastError( Errors::FileNotReadable, dir ); - } - else if ( pathInWatches( dir ) ) - { + } else if ( pathInWatches( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); } std::string curPath; std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); - if ( "" != link ) - { - if ( pathInWatches( link ) ) - { + if ( "" != link ) { + if ( pathInWatches( link ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); - } - else if ( !linkAllowed( curPath, link ) ) - { + } else if ( !linkAllowed( curPath, link ) ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); - } - else - { + } else { dir = link; } } - /// Check first if are enough file descriptors available to create another kqueue watcher, otherwise it creates a generic watcher - if ( availablesFD() ) - { + /// Check first if are enough file descriptors available to create another kqueue watcher, + /// otherwise it creates a generic watcher + if ( availablesFD() ) { mAddingWatcher = true; - WatcherKqueue * watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this ); + WatcherKqueue* watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this ); { Lock lock( mWatchesLock ); - mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatches.insert( std::make_pair( mLastWatchID, watch ) ); } watch->addAll(); // if failed to open the directory... erase the watcher - if ( !watch->initOK() ) - { + if ( !watch->initOK() ) { int le = watch->lastErrno(); mWatches.erase( watch->ID ); @@ -116,129 +100,111 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe mLastWatchID--; // Probably the folder has too many files, create a generic watcher - if ( EACCES != le ) - { - WatcherGeneric * genericWatch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); + if ( EACCES != le ) { + WatcherGeneric* genericWatch = + new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); Lock lock( mWatchesLock ); - mWatches.insert(std::make_pair(mLastWatchID, genericWatch)); - } - else - { + mWatches.insert( std::make_pair( mLastWatchID, genericWatch ) ); + } else { return Errors::Log::createLastError( Errors::Unspecified, link ); } } mAddingWatcher = false; - } - else - { - if ( !s_ug ) - { - efDEBUG( "Started using generic watcher, file descriptor limit reached: %ld\n", mFileDescriptorCount ); + } else { + if ( !s_ug ) { + efDEBUG( "Started using generic watcher, file descriptor limit reached: %ld\n", + mFileDescriptorCount ); s_ug = true; } - WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); + WatcherGeneric* watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); Lock lock( mWatchesLock ); - mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatches.insert( std::make_pair( mLastWatchID, watch ) ); } return mLastWatchID; } -void FileWatcherKqueue::removeWatch(const std::string& directory) -{ +void FileWatcherKqueue::removeWatch( const std::string& directory ) { Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); - for(; iter != mWatches.end(); ++iter) - { - if(directory == iter->second->Directory) - { - removeWatch(iter->first); + for ( ; iter != mWatches.end(); ++iter ) { + if ( directory == iter->second->Directory ) { + removeWatch( iter->first ); return; } } } -void FileWatcherKqueue::removeWatch(WatchID watchid) -{ +void FileWatcherKqueue::removeWatch( WatchID watchid ) { Lock lock( mWatchesLock ); - WatchMap::iterator iter = mWatches.find(watchid); + WatchMap::iterator iter = mWatches.find( watchid ); - if(iter == mWatches.end()) + if ( iter == mWatches.end() ) return; Watcher* watch = iter->second; - mWatches.erase(iter); + mWatches.erase( iter ); efSAFE_DELETE( watch ); } -bool FileWatcherKqueue::isAddingWatcher() const -{ +bool FileWatcherKqueue::isAddingWatcher() const { return mAddingWatcher; } -void FileWatcherKqueue::watch() -{ - if ( NULL == mThread ) - { +void FileWatcherKqueue::watch() { + if ( NULL == mThread ) { mThread = new Thread( &FileWatcherKqueue::run, this ); mThread->launch(); } } -void FileWatcherKqueue::run() -{ - do - { +void FileWatcherKqueue::run() { + do { { Lock lock( mWatchesLock ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { it->second->watch(); } } System::sleep( 500 ); - } while( mInitOK ); + } while ( mInitOK ); } -void FileWatcherKqueue::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) -{ -} +void FileWatcherKqueue::handleAction( Watcher* watch, const std::string& filename, + unsigned long action, std::string oldFilename ) {} -std::list<std::string> FileWatcherKqueue::directories() -{ - std::list<std::string> dirs; +std::vector<std::string> FileWatcherKqueue::directories() { + std::vector<std::string> dirs; Lock lock( mWatchesLock ); + dirs.reserve( mWatches.size() ); + WatchMap::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { + for ( ; it != mWatches.end(); ++it ) { dirs.push_back( it->second->Directory ); } return dirs; } -bool FileWatcherKqueue::pathInWatches( const std::string& path ) -{ +bool FileWatcherKqueue::pathInWatches( const std::string& path ) { WatchMap::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); ++it ) - { - if ( it->second->Directory == path ) - { + for ( ; it != mWatches.end(); ++it ) { + if ( it->second->Directory == path ) { return true; } } @@ -246,21 +212,18 @@ bool FileWatcherKqueue::pathInWatches( const std::string& path ) return false; } -void FileWatcherKqueue::addFD() -{ +void FileWatcherKqueue::addFD() { mFileDescriptorCount++; } -void FileWatcherKqueue::removeFD() -{ +void FileWatcherKqueue::removeFD() { mFileDescriptorCount--; } -bool FileWatcherKqueue::availablesFD() -{ +bool FileWatcherKqueue::availablesFD() { return mFileDescriptorCount <= (Int64)System::getMaxFD() - 500; } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.hpp b/dep/efsw/src/efsw/FileWatcherKqueue.hpp index 0a2431e3777..ff5327b23fb 100644 --- a/dep/efsw/src/efsw/FileWatcherKqueue.hpp +++ b/dep/efsw/src/efsw/FileWatcherKqueue.hpp @@ -7,71 +7,74 @@ #include <efsw/WatcherKqueue.hpp> -namespace efsw -{ +namespace efsw { /// Implementation for OSX based on kqueue. /// @class FileWatcherKqueue -class FileWatcherKqueue : public FileWatcherImpl -{ +class FileWatcherKqueue : public FileWatcherImpl { friend class WatcherKqueue; - public: - FileWatcherKqueue( FileWatcher * parent ); - virtual ~FileWatcherKqueue(); + public: + FileWatcherKqueue( FileWatcher* parent ); - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + virtual ~FileWatcherKqueue(); - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - void removeWatch(const std::string& directory); + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + const std::vector<WatcherOption> &options ) override; - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch( const std::string& directory ) override; - /// Updates the watcher. Must be called often. - void watch(); + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ) override; - /// Handles the action - void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + /// Updates the watcher. Must be called often. + void watch() override; - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - protected: - /// Map of WatchID to WatchStruct pointers - WatchMap mWatches; + /// Handles the action + void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) override; - /// time out data - struct timespec mTimeOut; + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories() override; - /// WatchID allocator - int mLastWatchID; + protected: + /// Map of WatchID to WatchStruct pointers + WatchMap mWatches; - Thread * mThread; + /// time out data + struct timespec mTimeOut; - Mutex mWatchesLock; + /// WatchID allocator + int mLastWatchID; - std::list<WatchID> mRemoveList; + Thread* mThread; - long mFileDescriptorCount; + Mutex mWatchesLock; - bool mAddingWatcher; + std::vector<WatchID> mRemoveList; - bool isAddingWatcher() const; + long mFileDescriptorCount; - bool pathInWatches( const std::string& path ); + bool mAddingWatcher; - void addFD(); + bool isAddingWatcher() const; - void removeFD(); + bool pathInWatches( const std::string& path ) override; - bool availablesFD(); - private: - void run(); + void addFD(); + + void removeFD(); + + bool availablesFD(); + + private: + void run(); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp index 317506fb3e3..37f43cc27da 100644 --- a/dep/efsw/src/efsw/FileWatcherWin32.cpp +++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp @@ -1,41 +1,43 @@ -#include <efsw/FileWatcherWin32.hpp> #include <efsw/FileSystem.hpp> -#include <efsw/System.hpp> -#include <efsw/String.hpp> +#include <efsw/FileWatcherWin32.hpp> #include <efsw/Lock.hpp> +#include <efsw/String.hpp> +#include <efsw/System.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 -namespace efsw -{ +namespace efsw { -FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) : - FileWatcherImpl( parent ), - mLastWatchID(0), - mThread( NULL ) -{ - mInitOK = true; +FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : + FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) { + mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ); + if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) + mInitOK = true; } -FileWatcherWin32::~FileWatcherWin32() -{ +FileWatcherWin32::~FileWatcherWin32() { mInitOK = false; + + if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) { + PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL ); + } + efSAFE_DELETE( mThread ); + removeAllWatches(); + + CloseHandle( mIOCP ); } -WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) -{ +WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, const std::vector<WatcherOption> &options ) { std::string dir( directory ); FileInfo fi( dir ); - if ( !fi.isDirectory() ) - { + if ( !fi.isDirectory() ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( !fi.isReadable() ) - { + } else if ( !fi.isReadable() ) { return Errors::Log::createLastError( Errors::FileNotReadable, dir ); } @@ -43,22 +45,22 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen Lock lock( mWatchesLock ); - if ( pathInWatches( dir ) ) - { + if ( pathInWatches( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, dir ); } WatchID watchid = ++mLastWatchID; - WatcherStructWin32 * watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), recursive, FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_SIZE - ); + DWORD bufferSize = static_cast<DWORD>( getOptionValue(options, Option::WinBufferSize, 63 * 1024) ); + DWORD notifyFilter = static_cast<DWORD>( getOptionValue(options, Option::WinNotifyFilter, + FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_SIZE) ); - if( NULL == watch ) - { + WatcherStructWin32* watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), + recursive, bufferSize, notifyFilter, mIOCP ); + + if ( NULL == watch ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); } @@ -66,241 +68,191 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen watch->Watch->ID = watchid; watch->Watch->Watch = this; watch->Watch->Listener = watcher; - watch->Watch->DirName = new char[dir.length()+1]; - strcpy(watch->Watch->DirName, dir.c_str()); + watch->Watch->DirName = new char[dir.length() + 1]; + strcpy( watch->Watch->DirName, dir.c_str() ); - mWatchesNew.insert( watch ); mWatches.insert( watch ); return watchid; } -void FileWatcherWin32::removeWatch(const std::string& directory) -{ +void FileWatcherWin32::removeWatch( const std::string& directory ) { Lock lock( mWatchesLock ); Watches::iterator iter = mWatches.begin(); - for(; iter != mWatches.end(); ++iter) - { - if(directory == (*iter)->Watch->DirName) - { - removeWatch(*iter); + for ( ; iter != mWatches.end(); ++iter ) { + if ( directory == ( *iter )->Watch->DirName ) { + removeWatch( *iter ); break; } } } -void FileWatcherWin32::removeWatch(WatchID watchid) -{ +void FileWatcherWin32::removeWatch( WatchID watchid ) { Lock lock( mWatchesLock ); Watches::iterator iter = mWatches.begin(); - for(; iter != mWatches.end(); ++iter) - { + for ( ; iter != mWatches.end(); ++iter ) { // Find the watch ID - if ( (*iter)->Watch->ID == watchid ) - { - removeWatch(*iter); + if ( ( *iter )->Watch->ID == watchid ) { + removeWatch( *iter ); return; } } } -void FileWatcherWin32::removeWatch(WatcherStructWin32* watch) -{ - mWatchesRemoved.insert(watch); - - if( NULL == mThread ) - { - removeWatches(); - } -} - -void FileWatcherWin32::removeWatches() -{ +void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { Lock lock( mWatchesLock ); - Watches::iterator remWatchIter = mWatchesRemoved.begin(); - - for( ; remWatchIter != mWatchesRemoved.end(); ++remWatchIter ) - { - Watches::iterator iter = mWatches.find(*remWatchIter); - - if( iter != mWatches.end() ) - { - DestroyWatch(*iter); - - mWatches.erase( iter ); - } - - iter = mWatchesNew.find(*remWatchIter); - - if( iter != mWatchesNew.end() ) - { - mWatchesNew.erase( iter ); - } - } - - mWatchesRemoved.clear(); + DestroyWatch( watch ); + mWatches.erase( watch ); } -void FileWatcherWin32::watch() -{ - if ( NULL == mThread ) - { +void FileWatcherWin32::watch() { + if ( NULL == mThread ) { mThread = new Thread( &FileWatcherWin32::run, this ); mThread->launch(); } } -void FileWatcherWin32::removeAllWatches() -{ +void FileWatcherWin32::removeAllWatches() { Lock lock( mWatchesLock ); Watches::iterator iter = mWatches.begin(); - for( ; iter != mWatches.end(); ++iter ) - { - DestroyWatch((*iter)); + for ( ; iter != mWatches.end(); ++iter ) { + DestroyWatch( ( *iter ) ); } mWatches.clear(); - mWatchesRemoved.clear(); - mWatchesNew.clear(); } -void FileWatcherWin32::run() -{ - do - { - if ( !mWatches.empty() ) - { - { - Lock lock( mWatchesLock ); - - for( Watches::iterator iter = mWatches.begin() ; iter != mWatches.end(); ++iter ) - { - WatcherStructWin32 * watch = *iter; - - if ( HasOverlappedIoCompleted( &watch->Overlapped ) ) - { - DWORD bytes; - - if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) - { - WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); - } - } +void FileWatcherWin32::run() { + do { + if ( mInitOK && !mWatches.empty() ) { + DWORD numOfBytes = 0; + OVERLAPPED* ov = NULL; + ULONG_PTR compKey = 0; + BOOL res = FALSE; + + while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov, + INFINITE ) ) != FALSE ) { + if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) { + break; + } else { + Lock lock( mWatchesLock ); + WatchCallback( numOfBytes, ov ); } } - - if ( mInitOK ) - { - System::sleep( 10 ); - } - } - else - { - // Wait for a new handle to be added + } else { System::sleep( 10 ); } - - removeWatches(); - - for ( Watches::iterator it = mWatchesNew.begin(); it != mWatchesNew.end(); ++it ) - { - RefreshWatch(*it); - } - - mWatchesNew.clear(); } while ( mInitOK ); removeAllWatches(); } -void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) -{ +void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename, + unsigned long action, std::string /*oldFilename*/ ) { Action fwAction; - switch(action) - { - case FILE_ACTION_RENAMED_OLD_NAME: - watch->OldFileName = filename; - return; - case FILE_ACTION_ADDED: - fwAction = Actions::Add; - break; - case FILE_ACTION_RENAMED_NEW_NAME: - { - fwAction = Actions::Moved; - - std::string fpath( watch->Directory + filename ); - - // Update the directory path - if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) - { - // Update the new directory path - std::string opath( watch->Directory + watch->OldFileName ); - FileSystem::dirAddSlashAtEnd( opath ); - FileSystem::dirAddSlashAtEnd( fpath ); - - for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - if ( (*it)->Watch->Directory == opath ) - { - (*it)->Watch->Directory = fpath; + switch ( action ) { + case FILE_ACTION_RENAMED_OLD_NAME: + watch->OldFileName = filename; + return; + case FILE_ACTION_ADDED: + fwAction = Actions::Add; + break; + case FILE_ACTION_RENAMED_NEW_NAME: { + fwAction = Actions::Moved; + + std::string fpath( watch->Directory + filename ); - break; + // Update the directory path + if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { + // Update the new directory path + std::string opath( watch->Directory + watch->OldFileName ); + FileSystem::dirAddSlashAtEnd( opath ); + FileSystem::dirAddSlashAtEnd( fpath ); + + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( ( *it )->Watch->Directory == opath ) { + ( *it )->Watch->Directory = fpath; + + break; + } } } - } - watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction, watch->OldFileName); - return; - } - case FILE_ACTION_REMOVED: - fwAction = Actions::Delete; - break; - case FILE_ACTION_MODIFIED: - fwAction = Actions::Modified; - break; + std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); + std::string realFilename = filename; + std::size_t sepPos = filename.find_last_of( "/\\" ); + std::string oldFolderPath = + static_cast<WatcherWin32*>( watch )->DirName + + watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) ); + + if ( sepPos != std::string::npos ) { + folderPath += + filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); + realFilename = filename.substr( sepPos + 1 ); + } + + if ( folderPath == oldFolderPath ) { + watch->Listener->handleFileAction( + watch->ID, folderPath, realFilename, fwAction, + FileSystem::fileNameFromPath( watch->OldFileName ) ); + } else { + watch->Listener->handleFileAction( watch->ID, + static_cast<WatcherWin32*>( watch )->DirName, + filename, fwAction, watch->OldFileName ); + } + return; + } + case FILE_ACTION_REMOVED: + fwAction = Actions::Delete; + break; + case FILE_ACTION_MODIFIED: + fwAction = Actions::Modified; + break; + default: + return; }; std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); 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 ) - { - folderPath += filename.substr( 0, sepPos ); + if ( sepPos != std::string::npos ) { + folderPath += filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); realFilename = filename.substr( sepPos + 1 ); } - watch->Listener->handleFileAction(watch->ID, folderPath, realFilename, fwAction); + FileSystem::dirAddSlashAtEnd( folderPath ); + + watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction ); } -std::list<std::string> FileWatcherWin32::directories() -{ - std::list<std::string> dirs; +std::vector<std::string> FileWatcherWin32::directories() { + std::vector<std::string> dirs; Lock lock( mWatchesLock ); - for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - dirs.push_back( std::string( (*it)->Watch->DirName ) ); + dirs.reserve( mWatches.size() ); + + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + dirs.push_back( std::string( ( *it )->Watch->DirName ) ); } return dirs; } -bool FileWatcherWin32::pathInWatches( const std::string& path ) -{ - for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { - if ( (*it)->Watch->DirName == path ) - { +bool FileWatcherWin32::pathInWatches( const std::string& path ) { + Lock lock( mWatchesLock ); + + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { + if ( ( *it )->Watch->DirName == path ) { return true; } } @@ -308,6 +260,6 @@ bool FileWatcherWin32::pathInWatches( const std::string& path ) return false; } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/FileWatcherWin32.hpp b/dep/efsw/src/efsw/FileWatcherWin32.hpp index 983ee1853d0..de3f9538dcd 100644 --- a/dep/efsw/src/efsw/FileWatcherWin32.hpp +++ b/dep/efsw/src/efsw/FileWatcherWin32.hpp @@ -6,68 +6,65 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #include <efsw/WatcherWin32.hpp> -#include <set> #include <map> +#include <set> +#include <vector> -namespace efsw -{ +namespace efsw { /// Implementation for Win32 based on ReadDirectoryChangesW. /// @class FileWatcherWin32 -class FileWatcherWin32 : public FileWatcherImpl -{ - public: - /// type for a map from WatchID to WatcherWin32 pointer - typedef std::set<WatcherStructWin32*> Watches; - - FileWatcherWin32( FileWatcher * parent ); +class FileWatcherWin32 : public FileWatcherImpl { + public: + /// type for a map from WatchID to WatcherWin32 pointer + typedef std::set<WatcherStructWin32*> Watches; - virtual ~FileWatcherWin32(); + FileWatcherWin32( FileWatcher* parent ); - /// Add a directory watch - /// On error returns WatchID with Error type. - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive); + virtual ~FileWatcherWin32(); - /// Remove a directory watch. This is a brute force lazy search O(nlogn). - void removeWatch(const std::string& directory); + /// Add a directory watch + /// On error returns WatchID with Error type. + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + const std::vector<WatcherOption> &options ) override; - /// Remove a directory watch. This is a map lookup O(logn). - void removeWatch(WatchID watchid); + /// Remove a directory watch. This is a brute force lazy search O(nlogn). + void removeWatch( const std::string& directory ) override; - /// Updates the watcher. Must be called often. - void watch(); + /// Remove a directory watch. This is a map lookup O(logn). + void removeWatch( WatchID watchid ) override; - /// Handles the action - void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = ""); + /// Updates the watcher. Must be called often. + void watch() override; - /// @return Returns a list of the directories that are being watched - std::list<std::string> directories(); - protected: - Watches mWatches; - Watches mWatchesRemoved; - Watches mWatchesNew; + /// Handles the action + void handleAction( Watcher* watch, const std::string& filename, unsigned long action, + std::string oldFilename = "" ) override; - /// The last watchid - WatchID mLastWatchID; + /// @return Returns a list of the directories that are being watched + std::vector<std::string> directories() override; - Thread * mThread; + protected: + HANDLE mIOCP; + Watches mWatches; - Mutex mWatchesLock; + /// The last watchid + WatchID mLastWatchID; + Thread* mThread; + Mutex mWatchesLock; - bool pathInWatches( const std::string& path ); + bool pathInWatches( const std::string& path ) override; - /// Remove all directory watches. - void removeAllWatches(); + /// Remove all directory watches. + void removeAllWatches(); - /// Remove needed directory watches. - void removeWatches(); + void removeWatch( WatcherStructWin32* watch ); - void removeWatch(WatcherStructWin32* watch); - private: - void run(); + private: + void run(); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/Lock.hpp b/dep/efsw/src/efsw/Lock.hpp index 5dbf11e39ce..e8c522abf0d 100644 --- a/dep/efsw/src/efsw/Lock.hpp +++ b/dep/efsw/src/efsw/Lock.hpp @@ -7,21 +7,15 @@ namespace efsw { /** Simple mutex class */ class Lock { - public: - explicit Lock( Mutex& mutex ) : - mMutex( mutex ) - { - mMutex.lock(); - } + public: + explicit Lock( Mutex& mutex ) : mMutex( mutex ) { mMutex.lock(); } - ~Lock() - { - mMutex.unlock(); - } - private: - Mutex& mMutex; + ~Lock() { mMutex.unlock(); } + + private: + Mutex& mMutex; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/Log.cpp b/dep/efsw/src/efsw/Log.cpp index 8e2860ac099..6f32df7c64a 100644 --- a/dep/efsw/src/efsw/Log.cpp +++ b/dep/efsw/src/efsw/Log.cpp @@ -1,27 +1,49 @@ #include <efsw/efsw.hpp> +#include <efsw/Debug.hpp> namespace efsw { namespace Errors { -static std::string LastError; +static std::string LastError = ""; +static Error LastErrorCode = NoError; -std::string Log::getLastErrorLog() -{ +std::string Log::getLastErrorLog() { return LastError; } -Error Log::createLastError( Error err, std::string log ) -{ - switch ( err ) - { - case FileNotFound: LastError = "File not found ( " + log + " )"; break; - case FileRepeated: LastError = "File reapeated in watches ( " + log + " )"; break; - case FileOutOfScope: LastError = "Symlink file out of scope ( " + log + " )"; break; - case FileRemote: LastError = "File is located in a remote file system, use a generic watcher. ( " + log + " )"; break; +Error Log::getLastErrorCode() { + return LastErrorCode; +} + +void Log::clearLastError() { + LastErrorCode = NoError; + LastError = ""; +} + +Error Log::createLastError( Error err, std::string log ) { + switch ( err ) { + case FileNotFound: + LastError = "File not found ( " + log + " )"; + break; + case FileRepeated: + LastError = "File repeated in watches ( " + log + " )"; + break; + case FileOutOfScope: + LastError = "Symlink file out of scope ( " + log + " )"; + break; + case FileRemote: + LastError = + "File is located in a remote file system, use a generic watcher. ( " + log + " )"; + break; + case WatcherFailed: + LastError = "File system watcher failed ( " + log + " )"; + break; case Unspecified: - default: LastError = log; + default: + LastError = log; } + efDEBUG( "%s\n", LastError.c_str() ); return err; } -}} +}} // namespace efsw::Errors diff --git a/dep/efsw/src/efsw/Mutex.cpp b/dep/efsw/src/efsw/Mutex.cpp index b34ba066ee9..c961db18124 100644 --- a/dep/efsw/src/efsw/Mutex.cpp +++ b/dep/efsw/src/efsw/Mutex.cpp @@ -3,24 +3,18 @@ namespace efsw { -Mutex::Mutex() : - mMutexImpl( new Platform::MutexImpl() ) -{ -} +Mutex::Mutex() : mMutexImpl( new Platform::MutexImpl() ) {} -Mutex::~Mutex() -{ +Mutex::~Mutex() { efSAFE_DELETE( mMutexImpl ); } -void Mutex::lock() -{ +void Mutex::lock() { mMutexImpl->lock(); } -void Mutex::unlock() -{ +void Mutex::unlock() { mMutexImpl->unlock(); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/Mutex.hpp b/dep/efsw/src/efsw/Mutex.hpp index e6e89def175..d98ad17c237 100644 --- a/dep/efsw/src/efsw/Mutex.hpp +++ b/dep/efsw/src/efsw/Mutex.hpp @@ -5,24 +5,27 @@ namespace efsw { -namespace Platform { class MutexImpl; } +namespace Platform { +class MutexImpl; +} /** Simple mutex class */ class Mutex { - public: - Mutex(); + public: + Mutex(); + + ~Mutex(); - ~Mutex(); + /** Lock the mutex */ + void lock(); - /** Lock the mutex */ - void lock(); + /** Unlock the mutex */ + void unlock(); - /** Unlock the mutex */ - void unlock(); - private: - Platform::MutexImpl * mMutexImpl; + private: + Platform::MutexImpl* mMutexImpl; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/String.cpp b/dep/efsw/src/efsw/String.cpp index f703d25cb35..8c9a3cc6cac 100644 --- a/dep/efsw/src/efsw/String.cpp +++ b/dep/efsw/src/efsw/String.cpp @@ -1,84 +1,66 @@ -#include <iterator> #include <efsw/String.hpp> #include <efsw/Utf.hpp> +#include <iterator> namespace efsw { const std::size_t String::InvalidPos = StringType::npos; -std::vector < std::string > String::split ( const std::string& str, const char& splitchar, const bool& pushEmptyString ) -{ - std::vector < std::string > tmp; +std::vector<std::string> String::split( const std::string& str, const char& splitchar, + const bool& pushEmptyString ) { + std::vector<std::string> tmp; std::string tmpstr; - for ( size_t i = 0; i < str.size(); i++ ) - { - if ( str[i] == splitchar ) - { - if ( pushEmptyString || tmpstr.size() ) - { - tmp.push_back(tmpstr); + for ( size_t i = 0; i < str.size(); i++ ) { + if ( str[i] == splitchar ) { + if ( pushEmptyString || tmpstr.size() ) { + tmp.push_back( tmpstr ); tmpstr = ""; } - } - else - { + } else { tmpstr += str[i]; } } - if ( tmpstr.size() ) - { + if ( tmpstr.size() ) { tmp.push_back( tmpstr ); } return tmp; } -std::vector < String > String::split ( const String& str, const Uint32& splitchar, const bool& pushEmptyString ) -{ - std::vector < String > tmp; +std::vector<String> String::split( const String& str, const Uint32& splitchar, + const bool& pushEmptyString ) { + std::vector<String> tmp; String tmpstr; - for ( size_t i = 0; i < str.size(); i++ ) - { - if ( str[i] == splitchar ) - { - if ( pushEmptyString || tmpstr.size() ) - { - tmp.push_back(tmpstr); + for ( size_t i = 0; i < str.size(); i++ ) { + if ( str[i] == splitchar ) { + if ( pushEmptyString || tmpstr.size() ) { + tmp.push_back( tmpstr ); tmpstr = ""; } - } - else - { + } else { tmpstr += str[i]; } } - if ( tmpstr.size() ) - { + if ( tmpstr.size() ) { tmp.push_back( tmpstr ); } return tmp; } -int String::strStartsWith( const std::string& start, const std::string& str ) -{ - int pos = -1; - size_t size = start.size(); +int String::strStartsWith( const std::string& start, const std::string& str ) { + int pos = -1; + size_t size = start.size(); - if ( str.size() >= size ) - { - for ( std::size_t i = 0; i < size; i++ ) - { - if ( start[i] == str[i] ) - { + if ( str.size() >= size ) { + for ( std::size_t i = 0; i < size; i++ ) { + if ( start[i] == str[i] ) { pos = (int)i; - } - else - { + } else { pos = -1; break; } @@ -88,21 +70,15 @@ int String::strStartsWith( const std::string& start, const std::string& str ) return pos; } -int String::strStartsWith( const String& start, const String& str ) -{ - int pos = -1; - size_t size = start.size(); +int String::strStartsWith( const String& start, const String& str ) { + int pos = -1; + size_t size = start.size(); - if ( str.size() >= size ) - { - for ( std::size_t i = 0; i < size; i++ ) - { - if ( start[i] == str[i] ) - { + if ( str.size() >= size ) { + for ( std::size_t i = 0; i < size; i++ ) { + if ( start[i] == str[i] ) { pos = (int)i; - } - else - { + } else { pos = -1; break; } @@ -112,37 +88,30 @@ int String::strStartsWith( const String& start, const String& str ) return pos; } -String::String() -{ -} +String::String() {} -String::String(char ansiChar, const std::locale& locale) -{ - mString += Utf32::DecodeAnsi(ansiChar, locale); +String::String( char ansiChar, const std::locale& locale ) { + mString += Utf32::DecodeAnsi( ansiChar, locale ); } #ifndef EFSW_NO_WIDECHAR -String::String(wchar_t wideChar) -{ - mString += Utf32::DecodeWide(wideChar); +String::String( wchar_t wideChar ) { + mString += Utf32::DecodeWide( wideChar ); } #endif -String::String(StringBaseType utf32Char) -{ +String::String( StringBaseType utf32Char ) { mString += utf32Char; } String::String( const char* uf8String ) { - if (uf8String) - { - std::size_t length = strlen(uf8String); + if ( uf8String ) { + std::size_t length = strlen( uf8String ); - if (length > 0) - { - mString.reserve(length + 1); + if ( length > 0 ) { + mString.reserve( length + 1 ); - Utf8::ToUtf32(uf8String, uf8String + length, std::back_inserter(mString)); + Utf8::ToUtf32( uf8String, uf8String + length, std::back_inserter( mString ) ); } } } @@ -153,64 +122,49 @@ String::String( const std::string& utf8String ) { Utf8::ToUtf32( utf8String.begin(), utf8String.end(), std::back_inserter( mString ) ); } -String::String(const char* ansiString, const std::locale& locale) -{ - if (ansiString) - { - std::size_t length = strlen(ansiString); - if (length > 0) - { - mString.reserve(length + 1); - Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(mString), locale); +String::String( const char* ansiString, const std::locale& locale ) { + if ( ansiString ) { + std::size_t length = strlen( ansiString ); + if ( length > 0 ) { + mString.reserve( length + 1 ); + Utf32::FromAnsi( ansiString, ansiString + length, std::back_inserter( mString ), + locale ); } } } -String::String(const std::string& ansiString, const std::locale& locale) -{ - mString.reserve(ansiString.length() + 1); - Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(mString), locale); +String::String( const std::string& ansiString, const std::locale& locale ) { + mString.reserve( ansiString.length() + 1 ); + Utf32::FromAnsi( ansiString.begin(), ansiString.end(), std::back_inserter( mString ), locale ); } #ifndef EFSW_NO_WIDECHAR -String::String(const wchar_t* wideString) -{ - if (wideString) - { - std::size_t length = std::wcslen(wideString); - if (length > 0) - { - mString.reserve(length + 1); - Utf32::FromWide(wideString, wideString + length, std::back_inserter(mString)); +String::String( const wchar_t* wideString ) { + if ( wideString ) { + std::size_t length = std::wcslen( wideString ); + if ( length > 0 ) { + mString.reserve( length + 1 ); + Utf32::FromWide( wideString, wideString + length, std::back_inserter( mString ) ); } } } -String::String(const std::wstring& wideString) -{ - mString.reserve(wideString.length() + 1); - Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(mString)); +String::String( const std::wstring& wideString ) { + mString.reserve( wideString.length() + 1 ); + Utf32::FromWide( wideString.begin(), wideString.end(), std::back_inserter( mString ) ); } #endif -String::String(const StringBaseType* utf32String) -{ - if (utf32String) +String::String( const StringBaseType* utf32String ) { + if ( utf32String ) mString = utf32String; } -String::String(const StringType& utf32String) : -mString(utf32String) -{ -} +String::String( const StringType& utf32String ) : mString( utf32String ) {} -String::String(const String& str) : -mString(str.mString) -{ -} +String::String( const String& str ) : mString( str.mString ) {} -String String::fromUtf8( const std::string& utf8String ) -{ +String String::fromUtf8( const std::string& utf8String ) { String::StringType utf32; utf32.reserve( utf8String.length() + 1 ); @@ -220,32 +174,29 @@ String String::fromUtf8( const std::string& utf8String ) return String( utf32 ); } -String::operator std::string() const -{ +String::operator std::string() const { return toAnsiString(); } -std::string String::toAnsiString(const std::locale& locale) const -{ +std::string String::toAnsiString( const std::locale& locale ) const { // Prepare the output string std::string output; - output.reserve(mString.length() + 1); + output.reserve( mString.length() + 1 ); // Convert - Utf32::ToAnsi(mString.begin(), mString.end(), std::back_inserter(output), 0, locale); + Utf32::ToAnsi( mString.begin(), mString.end(), std::back_inserter( output ), 0, locale ); return output; } #ifndef EFSW_NO_WIDECHAR -std::wstring String::toWideString() const -{ +std::wstring String::toWideString() const { // Prepare the output string std::wstring output; - output.reserve(mString.length() + 1); + output.reserve( mString.length() + 1 ); // Convert - Utf32::ToWide(mString.begin(), mString.end(), std::back_inserter(output), 0); + Utf32::ToWide( mString.begin(), mString.end(), std::back_inserter( output ), 0 ); return output; } @@ -254,103 +205,85 @@ std::wstring String::toWideString() const std::string String::toUtf8() const { // Prepare the output string std::string output; - output.reserve(mString.length() + 1); + output.reserve( mString.length() + 1 ); // Convert - Utf32::toUtf8(mString.begin(), mString.end(), std::back_inserter(output) ); + Utf32::toUtf8( mString.begin(), mString.end(), std::back_inserter( output ) ); return output; } -String& String::operator =(const String& right) -{ +String& String::operator=( const String& right ) { mString = right.mString; return *this; } -String& String::operator =( const StringBaseType& right ) -{ +String& String::operator=( const StringBaseType& right ) { mString = right; return *this; } -String& String::operator +=(const String& right) -{ +String& String::operator+=( const String& right ) { mString += right.mString; return *this; } -String& String::operator +=( const StringBaseType& right ) -{ +String& String::operator+=( const StringBaseType& right ) { mString += right; return *this; } - -String::StringBaseType String::operator [](std::size_t index) const -{ +String::StringBaseType String::operator[]( std::size_t index ) const { return mString[index]; } -String::StringBaseType& String::operator [](std::size_t index) -{ +String::StringBaseType& String::operator[]( std::size_t index ) { return mString[index]; } -String::StringBaseType String::at( std::size_t index ) const -{ +String::StringBaseType String::at( std::size_t index ) const { return mString.at( index ); } -void String::push_back( StringBaseType c ) -{ +void String::push_back( StringBaseType c ) { mString.push_back( c ); } -void String::swap ( String& str ) -{ +void String::swap( String& str ) { mString.swap( str.mString ); } -void String::clear() -{ +void String::clear() { mString.clear(); } -std::size_t String::size() const -{ +std::size_t String::size() const { return mString.size(); } -std::size_t String::length() const -{ +std::size_t String::length() const { return mString.length(); } -bool String::empty() const -{ +bool String::empty() const { return mString.empty(); } -void String::erase(std::size_t position, std::size_t count) -{ - mString.erase(position, count); +void String::erase( std::size_t position, std::size_t count ) { + mString.erase( position, count ); } -String& String::insert(std::size_t position, const String& str) -{ - mString.insert(position, str.mString); +String& String::insert( std::size_t position, const String& str ) { + mString.insert( position, str.mString ); return *this; } -String& String::insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n ) -{ +String& String::insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n ) { mString.insert( pos1, str.mString, pos2, n ); return *this; } -String& String::insert ( size_t pos1, const char* s, size_t n ) -{ +String& String::insert( size_t pos1, const char* s, size_t n ) { String tmp( s ); mString.insert( pos1, tmp.data(), n ); @@ -358,14 +291,12 @@ String& String::insert ( size_t pos1, const char* s, size_t n ) return *this; } -String& String::insert ( size_t pos1, size_t n, char c ) -{ +String& String::insert( size_t pos1, size_t n, char c ) { mString.insert( pos1, n, c ); return *this; } -String& String::insert ( size_t pos1, const char* s ) -{ +String& String::insert( size_t pos1, const char* s ) { String tmp( s ); mString.insert( pos1, tmp.data() ); @@ -373,105 +304,85 @@ String& String::insert ( size_t pos1, const char* s ) return *this; } -String::Iterator String::insert ( Iterator p, char c ) -{ +String::Iterator String::insert( Iterator p, char c ) { return mString.insert( p, c ); } -void String::insert ( Iterator p, size_t n, char c ) -{ +void String::insert( Iterator p, size_t n, char c ) { mString.insert( p, n, c ); } -const String::StringBaseType* String::c_str() const -{ +const String::StringBaseType* String::c_str() const { return mString.c_str(); } -const String::StringBaseType* String::data() const -{ +const String::StringBaseType* String::data() const { return mString.data(); } -String::Iterator String::begin() -{ +String::Iterator String::begin() { return mString.begin(); } -String::ConstIterator String::begin() const -{ +String::ConstIterator String::begin() const { return mString.begin(); } -String::Iterator String::end() -{ +String::Iterator String::end() { return mString.end(); } -String::ConstIterator String::end() const -{ +String::ConstIterator String::end() const { return mString.end(); } -String::ReverseIterator String::rbegin() -{ +String::ReverseIterator String::rbegin() { return mString.rbegin(); } -String::ConstReverseIterator String::rbegin() const -{ +String::ConstReverseIterator String::rbegin() const { return mString.rbegin(); } -String::ReverseIterator String::rend() -{ +String::ReverseIterator String::rend() { return mString.rend(); } -String::ConstReverseIterator String::rend() const -{ +String::ConstReverseIterator String::rend() const { return mString.rend(); } -void String::resize( std::size_t n, StringBaseType c ) -{ +void String::resize( std::size_t n, StringBaseType c ) { mString.resize( n, c ); } -void String::resize( std::size_t n ) -{ +void String::resize( std::size_t n ) { mString.resize( n ); } -std::size_t String::max_size() const -{ +std::size_t String::max_size() const { return mString.max_size(); } -void String::reserve( size_t res_arg ) -{ +void String::reserve( size_t res_arg ) { mString.reserve( res_arg ); } -std::size_t String::capacity() const -{ +std::size_t String::capacity() const { return mString.capacity(); } -String& String::assign ( const String& str ) -{ +String& String::assign( const String& str ) { mString.assign( str.mString ); return *this; } -String& String::assign ( const String& str, size_t pos, size_t n ) -{ +String& String::assign( const String& str, size_t pos, size_t n ) { mString.assign( str.mString, pos, n ); return *this; } -String& String::assign ( const char* s, size_t n ) -{ +String& String::assign( const char* s, size_t n ) { String tmp( s ); mString.assign( tmp.mString ); @@ -479,8 +390,7 @@ String& String::assign ( const char* s, size_t n ) return *this; } -String& String::assign ( const char* s ) -{ +String& String::assign( const char* s ) { String tmp( s ); mString.assign( tmp.mString ); @@ -488,29 +398,25 @@ String& String::assign ( const char* s ) return *this; } -String& String::assign ( size_t n, char c ) -{ +String& String::assign( size_t n, char c ) { mString.assign( n, c ); return *this; } -String& String::append ( const String& str ) -{ +String& String::append( const String& str ) { mString.append( str.mString ); return *this; } -String& String::append ( const String& str, size_t pos, size_t n ) -{ +String& String::append( const String& str, size_t pos, size_t n ) { mString.append( str.mString, pos, n ); return *this; } -String& String::append ( const char* s, size_t n ) -{ +String& String::append( const char* s, size_t n ) { String tmp( s ); mString.append( tmp.mString ); @@ -518,8 +424,7 @@ String& String::append ( const char* s, size_t n ) return *this; } -String& String::append ( const char* s ) -{ +String& String::append( const char* s ) { String tmp( s ); mString.append( tmp.mString ); @@ -527,43 +432,37 @@ String& String::append ( const char* s ) return *this; } -String& String::append ( size_t n, char c ) -{ +String& String::append( size_t n, char c ) { mString.append( n, c ); return *this; } -String& String::append ( std::size_t n, StringBaseType c ) -{ +String& String::append( std::size_t n, StringBaseType c ) { mString.append( n, c ); return *this; } -String& String::replace ( size_t pos1, size_t n1, const String& str ) -{ +String& String::replace( size_t pos1, size_t n1, const String& str ) { mString.replace( pos1, n1, str.mString ); return *this; } -String& String::replace ( Iterator i1, Iterator i2, const String& str ) -{ +String& String::replace( Iterator i1, Iterator i2, const String& str ) { mString.replace( i1, i2, str.mString ); return *this; } -String& String::replace ( size_t pos1, size_t n1, const String& str, size_t pos2, size_t n2 ) -{ +String& String::replace( size_t pos1, size_t n1, const String& str, size_t pos2, size_t n2 ) { mString.replace( pos1, n1, str.mString, pos2, n2 ); return *this; } -String& String::replace ( size_t pos1, size_t n1, const char* s, size_t n2 ) -{ +String& String::replace( size_t pos1, size_t n1, const char* s, size_t n2 ) { String tmp( s ); mString.replace( pos1, n1, tmp.data(), n2 ); @@ -571,8 +470,7 @@ String& String::replace ( size_t pos1, size_t n1, const char* s, size_t n2 ) return *this; } -String& String::replace ( Iterator i1, Iterator i2, const char* s, size_t n2 ) -{ +String& String::replace( Iterator i1, Iterator i2, const char* s, size_t n2 ) { String tmp( s ); mString.replace( i1, i2, tmp.data(), n2 ); @@ -580,8 +478,7 @@ String& String::replace ( Iterator i1, Iterator i2, const char* s, size_t n2 ) return *this; } -String& String::replace ( size_t pos1, size_t n1, const char* s ) -{ +String& String::replace( size_t pos1, size_t n1, const char* s ) { String tmp( s ); mString.replace( pos1, n1, tmp.mString ); @@ -589,8 +486,7 @@ String& String::replace ( size_t pos1, size_t n1, const char* s ) return *this; } -String& String::replace ( Iterator i1, Iterator i2, const char* s ) -{ +String& String::replace( Iterator i1, Iterator i2, const char* s ) { String tmp( s ); mString.replace( i1, i2, tmp.mString ); @@ -598,216 +494,176 @@ String& String::replace ( Iterator i1, Iterator i2, const char* s ) return *this; } -String& String::replace ( size_t pos1, size_t n1, size_t n2, char c ) -{ +String& String::replace( size_t pos1, size_t n1, size_t n2, char c ) { mString.replace( pos1, n1, n2, (StringBaseType)c ); return *this; } -String& String::replace ( Iterator i1, Iterator i2, size_t n2, char c ) -{ +String& String::replace( Iterator i1, Iterator i2, size_t n2, char c ) { mString.replace( i1, i2, n2, (StringBaseType)c ); return *this; } -std::size_t String::find( const String& str, std::size_t start ) const -{ +std::size_t String::find( const String& str, std::size_t start ) const { return mString.find( str.mString, start ); } -std::size_t String::find ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::find( const char* s, std::size_t pos, std::size_t n ) const { return find( String( s ), pos ); } -std::size_t String::find ( const char* s, std::size_t pos ) const -{ +std::size_t String::find( const char* s, std::size_t pos ) const { return find( String( s ), pos ); } -size_t String::find ( char c, std::size_t pos ) const -{ +size_t String::find( char c, std::size_t pos ) const { return mString.find( (StringBaseType)c, pos ); } -std::size_t String::rfind ( const String& str, std::size_t pos ) const -{ +std::size_t String::rfind( const String& str, std::size_t pos ) const { return mString.rfind( str.mString, pos ); } -std::size_t String::rfind ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::rfind( const char* s, std::size_t pos, std::size_t n ) const { return rfind( String( s ), pos ); } -std::size_t String::rfind ( const char* s, std::size_t pos ) const -{ +std::size_t String::rfind( const char* s, std::size_t pos ) const { return rfind( String( s ), pos ); } -std::size_t String::rfind ( char c, std::size_t pos ) const -{ +std::size_t String::rfind( char c, std::size_t pos ) const { return mString.rfind( c, pos ); } -std::size_t String::copy ( StringBaseType* s, std::size_t n, std::size_t pos ) const -{ +std::size_t String::copy( StringBaseType* s, std::size_t n, std::size_t pos ) const { return mString.copy( s, n, pos ); } -String String::substr ( std::size_t pos, std::size_t n ) const -{ +String String::substr( std::size_t pos, std::size_t n ) const { return String( mString.substr( pos, n ) ); } -int String::compare ( const String& str ) const -{ +int String::compare( const String& str ) const { return mString.compare( str.mString ); } -int String::compare ( const char* s ) const -{ +int String::compare( const char* s ) const { return compare( String( s ) ); } -int String::compare ( std::size_t pos1, std::size_t n1, const String& str ) const -{ +int String::compare( std::size_t pos1, std::size_t n1, const String& str ) const { return mString.compare( pos1, n1, str.mString ); } -int String::compare ( std::size_t pos1, std::size_t n1, const char* s) const -{ +int String::compare( std::size_t pos1, std::size_t n1, const char* s ) const { return compare( pos1, n1, String( s ) ); } -int String::compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const -{ +int String::compare( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, + std::size_t n2 ) const { return mString.compare( pos1, n1, str.mString, pos2, n2 ); } -int String::compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const -{ +int String::compare( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 ) const { return compare( pos1, n1, String( s ), 0, n2 ); } -std::size_t String::find_first_of ( const String& str, std::size_t pos ) const -{ +std::size_t String::find_first_of( const String& str, std::size_t pos ) const { return mString.find_first_of( str.mString, pos ); } -std::size_t String::find_first_of ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::find_first_of( const char* s, std::size_t pos, std::size_t n ) const { return find_first_of( String( s ), pos ); } -std::size_t String::find_first_of ( const char* s, std::size_t pos ) const -{ +std::size_t String::find_first_of( const char* s, std::size_t pos ) const { return find_first_of( String( s ), pos ); } -std::size_t String::find_first_of ( StringBaseType c, std::size_t pos ) const -{ +std::size_t String::find_first_of( StringBaseType c, std::size_t pos ) const { return mString.find_first_of( c, pos ); } -std::size_t String::find_last_of ( const String& str, std::size_t pos ) const -{ +std::size_t String::find_last_of( const String& str, std::size_t pos ) const { return mString.find_last_of( str.mString, pos ); } -std::size_t String::find_last_of ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::find_last_of( const char* s, std::size_t pos, std::size_t n ) const { return find_last_of( String( s ), pos ); } -std::size_t String::find_last_of ( const char* s, std::size_t pos ) const -{ +std::size_t String::find_last_of( const char* s, std::size_t pos ) const { return find_last_of( String( s ), pos ); } -std::size_t String::find_last_of ( StringBaseType c, std::size_t pos) const -{ +std::size_t String::find_last_of( StringBaseType c, std::size_t pos ) const { return mString.find_last_of( c, pos ); } -std::size_t String::find_first_not_of ( const String& str, std::size_t pos ) const -{ +std::size_t String::find_first_not_of( const String& str, std::size_t pos ) const { return mString.find_first_not_of( str.mString, pos ); } -std::size_t String::find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::find_first_not_of( const char* s, std::size_t pos, std::size_t n ) const { return find_first_not_of( String( s ), pos ); } -std::size_t String::find_first_not_of ( const char* s, std::size_t pos ) const -{ +std::size_t String::find_first_not_of( const char* s, std::size_t pos ) const { return find_first_not_of( String( s ), pos ); } -std::size_t String::find_first_not_of ( StringBaseType c, std::size_t pos ) const -{ +std::size_t String::find_first_not_of( StringBaseType c, std::size_t pos ) const { return mString.find_first_not_of( c, pos ); } -std::size_t String::find_last_not_of ( const String& str, std::size_t pos ) const -{ +std::size_t String::find_last_not_of( const String& str, std::size_t pos ) const { return mString.find_last_not_of( str.mString, pos ); } -std::size_t String::find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const -{ +std::size_t String::find_last_not_of( const char* s, std::size_t pos, std::size_t n ) const { return find_last_not_of( String( s ), pos ); } -std::size_t String::find_last_not_of ( const char* s, std::size_t pos ) const -{ +std::size_t String::find_last_not_of( const char* s, std::size_t pos ) const { return find_last_not_of( String( s ), pos ); } -std::size_t String::find_last_not_of ( StringBaseType c, std::size_t pos ) const -{ +std::size_t String::find_last_not_of( StringBaseType c, std::size_t pos ) const { return mString.find_last_not_of( c, pos ); } -bool operator ==(const String& left, const String& right) -{ +bool operator==( const String& left, const String& right ) { return left.mString == right.mString; } -bool operator !=(const String& left, const String& right) -{ - return !(left == right); +bool operator!=( const String& left, const String& right ) { + return !( left == right ); } -bool operator <(const String& left, const String& right) -{ +bool operator<( const String& left, const String& right ) { return left.mString < right.mString; } -bool operator >(const String& left, const String& right) -{ +bool operator>( const String& left, const String& right ) { return right < left; } -bool operator <=(const String& left, const String& right) -{ - return !(right < left); +bool operator<=( const String& left, const String& right ) { + return !( right < left ); } -bool operator >=(const String& left, const String& right) -{ - return !(left < right); +bool operator>=( const String& left, const String& right ) { + return !( left < right ); } -String operator +(const String& left, const String& right) -{ +String operator+( const String& left, const String& right ) { String string = left; string += right; return string; } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/String.hpp b/dep/efsw/src/efsw/String.hpp index ce7e3b75f89..65bce3328c2 100644 --- a/dep/efsw/src/efsw/String.hpp +++ b/dep/efsw/src/efsw/String.hpp @@ -1,39 +1,39 @@ /** NOTE: -* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php ) -* The class was modified to fit efsw own needs. This is not the original implementation from SFML2. -* Functions and methods are the same that in std::string to facilitate portability. -**/ + * This code is based on the Utf implementation from SFML2. License zlib/png ( + *http://www.sfml-dev.org/license.php ) The class was modified to fit efsw own needs. This is not + *the original implementation from SFML2. Functions and methods are the same that in std::string to + *facilitate portability. + **/ #ifndef EFSW_STRING_HPP #define EFSW_STRING_HPP -#include <efsw/base.hpp> -#include <locale> -#include <string> -#include <cstring> #include <cstdlib> -#include <iostream> +#include <cstring> +#include <efsw/base.hpp> #include <fstream> +#include <iostream> +#include <locale> #include <sstream> +#include <string> #include <vector> namespace efsw { -/** @brief Utility string class that automatically handles conversions between types and encodings **/ -class String -{ - public : - typedef Uint32 StringBaseType; - typedef std::basic_string<StringBaseType> StringType; - typedef StringType::iterator Iterator; //! Iterator type - typedef StringType::const_iterator ConstIterator; //! Constant iterator type - typedef StringType::reverse_iterator ReverseIterator; //! Reverse Iterator type - typedef StringType::const_reverse_iterator ConstReverseIterator; //! Constant iterator type +/** @brief Utility string class that automatically handles conversions between types and encodings + * **/ +class String { + public: + typedef Uint32 StringBaseType; + typedef std::basic_string<StringBaseType> StringType; + typedef StringType::iterator Iterator; //! Iterator type + typedef StringType::const_iterator ConstIterator; //! Constant iterator type + typedef StringType::reverse_iterator ReverseIterator; //! Reverse Iterator type + typedef StringType::const_reverse_iterator ConstReverseIterator; //! Constant iterator type static const std::size_t InvalidPos; ///< Represents an invalid position in the string - template <class T> - static std::string toStr(const T& i) { + template <class T> static std::string toStr( const T& i ) { std::ostringstream ss; ss << i; return ss.str(); @@ -41,23 +41,27 @@ class String /** Converts from a string to type */ template <class T> - static bool fromString(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) { - std::istringstream iss(s); - return !(iss >> f >> t).fail(); + static bool fromString( T& t, const std::string& s, + std::ios_base& ( *f )( std::ios_base& ) = std::dec ) { + std::istringstream iss( s ); + return !( iss >> f >> t ).fail(); } /** Converts from a String to type */ template <class T> - static bool fromString(T& t, const String& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) { + static bool fromString( T& t, const String& s, + std::ios_base& ( *f )( std::ios_base& ) = std::dec ) { std::istringstream iss( s.toUtf8() ); - return !(iss >> f >> t).fail(); + return !( iss >> f >> t ).fail(); } /** Split a string and hold it on a vector */ - static std::vector < std::string > split( const std::string& str, const char& splitchar, const bool& pushEmptyString = false ); + static std::vector<std::string> split( const std::string& str, const char& splitchar, + const bool& pushEmptyString = false ); /** Split a string and hold it on a vector */ - static std::vector < String > split( const String& str, const Uint32& splitchar, const bool& pushEmptyString = false ); + static std::vector<String> split( const String& str, const Uint32& splitchar, + const bool& pushEmptyString = false ); /** Determine if a string starts with the string passed ** @param start The substring expected to start @@ -149,7 +153,6 @@ class String **/ String( const StringType& utf32String ); - /** @brief Copy constructor ** @param str Instance to copy **/ @@ -196,17 +199,17 @@ class String ** @param right Instance to assign ** @return Reference to self **/ - String& operator =(const String& right); + String& operator=( const String& right ); - String& operator =( const StringBaseType& right ); + String& operator=( const StringBaseType& right ); /** @brief Overload of += operator to append an UTF-32 string ** @param right String to append ** @return Reference to self **/ - String& operator +=(const String& right); + String& operator+=( const String& right ); - String& operator +=( const StringBaseType& right ); + String& operator+=( const StringBaseType& right ); /** @brief Overload of [] operator to access a character by its position ** This function provides read-only access to characters. @@ -214,7 +217,7 @@ class String ** @param index Index of the character to get ** @return Character at position \a index **/ - StringBaseType operator [](std::size_t index) const; + StringBaseType operator[]( std::size_t index ) const; /** @brief Overload of [] operator to access a character by its position ** This function provides read and write access to characters. @@ -223,14 +226,15 @@ class String ** @return Reference to the character at position \a index **/ - StringBaseType& operator [](std::size_t index); + StringBaseType& operator[]( std::size_t index ); /** @brief Get character in string - ** Performs a range check, throwing an exception of type out_of_range in case that pos is not an actual position in the string. + ** Performs a range check, throwing an exception of type out_of_range in case that pos is not an + *actual position in the string. ** @return The character at position pos in the string. */ StringBaseType at( std::size_t index ) const; - + /** @brief clear the string ** This function removes all the characters from the string. ** @see empty, erase @@ -242,7 +246,7 @@ class String ** @see empty **/ std::size_t size() const; - + /** @see size() */ std::size_t length() const; @@ -258,8 +262,7 @@ class String ** @param position Position of the first character to erase ** @param count Number of characters to erase **/ - void erase(std::size_t position, std::size_t count = 1); - + void erase( std::size_t position, std::size_t count = 1 ); /** @brief Insert one or more characters into the string ** This function inserts the characters of \a str @@ -267,23 +270,22 @@ class String ** @param position Position of insertion ** @param str Characters to insert **/ - String& insert(std::size_t position, const String& str); + String& insert( std::size_t position, const String& str ); String& insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n ); - String& insert ( std::size_t pos1, const char* s, std::size_t n ); + String& insert( std::size_t pos1, const char* s, std::size_t n ); - String& insert ( std::size_t pos1, const char* s ); + String& insert( std::size_t pos1, const char* s ); - String& insert ( std::size_t pos1, size_t n, char c ); + String& insert( std::size_t pos1, size_t n, char c ); - Iterator insert ( Iterator p, char c ); + Iterator insert( Iterator p, char c ); - void insert ( Iterator p, std::size_t n, char c ); + void insert( Iterator p, std::size_t n, char c ); - template<class InputIterator> - void insert ( Iterator p, InputIterator first, InputIterator last ) - { + template <class InputIterator> + void insert( Iterator p, InputIterator first, InputIterator last ) { mString.insert( p, first, last ); } @@ -296,11 +298,11 @@ class String **/ std::size_t find( const String& str, std::size_t start = 0 ) const; - std::size_t find ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t find( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t find ( const char* s, std::size_t pos = 0 ) const; + std::size_t find( const char* s, std::size_t pos = 0 ) const; - std::size_t find ( char c, std::size_t pos = 0 ) const; + std::size_t find( char c, std::size_t pos = 0 ) const; /** @brief Get a pointer to the C-style array of characters ** This functions provides a read-only access to a @@ -310,11 +312,14 @@ class String ** @return Read-only pointer to the array of characters **/ const StringBaseType* c_str() const; - + /** @brief Get string data - ** Notice that no terminating null character is appended (see member c_str for such a functionality). - ** The returned array points to an internal location which should not be modified directly in the program. - ** Its contents are guaranteed to remain unchanged only until the next call to a non-constant member function of the string object. + ** Notice that no terminating null character is appended (see member c_str for such a + *functionality). + ** The returned array points to an internal location which should not be modified directly in + *the program. + ** Its contents are guaranteed to remain unchanged only until the next call to a non-constant + *member function of the string object. ** @return Pointer to an internal array containing the same content as the string. **/ const StringBaseType* data() const; @@ -348,7 +353,7 @@ class String ** @see begin **/ ConstIterator end() const; - + /** @brief Return an reverse iterator to the beginning of the string ** @return Read-write reverse iterator to the beginning of the string characters ** @see end @@ -370,7 +375,6 @@ class String **/ ReverseIterator rend(); - /** @brief Return an reverse iterator to the beginning of the string ** The end reverse iterator refers to 1 position past the last character; ** thus it represents an invalid character and should never be @@ -379,147 +383,145 @@ class String ** @see begin **/ ConstReverseIterator rend() const; - + /** @brief Resize String */ - void resize ( std::size_t n, StringBaseType c ); - + void resize( std::size_t n, StringBaseType c ); + /** @brief Resize String */ - void resize ( std::size_t n ); - + void resize( std::size_t n ); + /** @return Maximum size of string */ std::size_t max_size() const; - + /** @brief Request a change in capacity */ - void reserve ( size_t res_arg=0 ); - + void reserve( size_t res_arg = 0 ); + /** @return Size of allocated storage */ std::size_t capacity() const; /** @brief Append character to string */ void push_back( StringBaseType c ); - + /** @brief Swap contents with another string */ - void swap ( String& str ); - - String& assign ( const String& str ); + void swap( String& str ); - String& assign ( const String& str, std::size_t pos, std::size_t n ); + String& assign( const String& str ); - String& assign ( const char* s, std::size_t n ); + String& assign( const String& str, std::size_t pos, std::size_t n ); - String& assign ( const char* s ); + String& assign( const char* s, std::size_t n ); - String& assign ( std::size_t n, char c ); + String& assign( const char* s ); - template <class InputIterator> - String& assign ( InputIterator first, InputIterator last ) - { + String& assign( std::size_t n, char c ); + + template <class InputIterator> String& assign( InputIterator first, InputIterator last ) { mString.assign( first, last ); return *this; } - String& append ( const String& str ); + String& append( const String& str ); - String& append ( const String& str, std::size_t pos, std::size_t n ); + String& append( const String& str, std::size_t pos, std::size_t n ); - String& append ( const char* s, std::size_t n ); + String& append( const char* s, std::size_t n ); - String& append ( const char* s ); + String& append( const char* s ); - String& append ( std::size_t n, char c ); + String& append( std::size_t n, char c ); - String& append ( std::size_t n, StringBaseType c ); + String& append( std::size_t n, StringBaseType c ); - template <class InputIterator> - String& append ( InputIterator first, InputIterator last ) - { + template <class InputIterator> String& append( InputIterator first, InputIterator last ) { mString.append( first, last ); return *this; } - String& replace ( std::size_t pos1, std::size_t n1, const String& str ); + String& replace( std::size_t pos1, std::size_t n1, const String& str ); - String& replace ( Iterator i1, Iterator i2, const String& str ); + String& replace( Iterator i1, Iterator i2, const String& str ); - String& replace ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ); + String& replace( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, + std::size_t n2 ); - String& replace ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 ); + String& replace( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 ); - String& replace ( Iterator i1, Iterator i2, const char* s, std::size_t n2 ); + String& replace( Iterator i1, Iterator i2, const char* s, std::size_t n2 ); - String& replace ( std::size_t pos1, std::size_t n1, const char* s ); + String& replace( std::size_t pos1, std::size_t n1, const char* s ); - String& replace ( Iterator i1, Iterator i2, const char* s ); + String& replace( Iterator i1, Iterator i2, const char* s ); - String& replace ( std::size_t pos1, std::size_t n1, std::size_t n2, char c ); + String& replace( std::size_t pos1, std::size_t n1, std::size_t n2, char c ); - String& replace ( Iterator i1, Iterator i2, std::size_t n2, char c ); + String& replace( Iterator i1, Iterator i2, std::size_t n2, char c ); - template<class InputIterator> - String& replace ( Iterator i1, Iterator i2, InputIterator j1, InputIterator j2 ) - { + template <class InputIterator> + String& replace( Iterator i1, Iterator i2, InputIterator j1, InputIterator j2 ) { mString.replace( i1, i2, j1, j2 ); return *this; } - std::size_t rfind ( const String& str, std::size_t pos = StringType::npos ) const; + std::size_t rfind( const String& str, std::size_t pos = StringType::npos ) const; + + std::size_t rfind( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t rfind ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t rfind( const char* s, std::size_t pos = StringType::npos ) const; - std::size_t rfind ( const char* s, std::size_t pos = StringType::npos ) const; + std::size_t rfind( char c, std::size_t pos = StringType::npos ) const; - std::size_t rfind ( char c, std::size_t pos = StringType::npos ) const; + String substr( std::size_t pos = 0, std::size_t n = StringType::npos ) const; - String substr ( std::size_t pos = 0, std::size_t n = StringType::npos ) const; + std::size_t copy( StringBaseType* s, std::size_t n, std::size_t pos = 0 ) const; - std::size_t copy ( StringBaseType* s, std::size_t n, std::size_t pos = 0 ) const; + int compare( const String& str ) const; - int compare ( const String& str ) const; + int compare( const char* s ) const; - int compare ( const char* s ) const; + int compare( std::size_t pos1, std::size_t n1, const String& str ) const; - int compare ( std::size_t pos1, std::size_t n1, const String& str ) const; + int compare( std::size_t pos1, std::size_t n1, const char* s ) const; - int compare ( std::size_t pos1, std::size_t n1, const char* s) const; + int compare( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, + std::size_t n2 ) const; - int compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const; + int compare( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 ) const; - int compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const; + std::size_t find_first_of( const String& str, std::size_t pos = 0 ) const; - std::size_t find_first_of ( const String& str, std::size_t pos = 0 ) const; + std::size_t find_first_of( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t find_first_of ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t find_first_of( const char* s, std::size_t pos = 0 ) const; - std::size_t find_first_of ( const char* s, std::size_t pos = 0 ) const; + std::size_t find_first_of( StringBaseType c, std::size_t pos = 0 ) const; - std::size_t find_first_of ( StringBaseType c, std::size_t pos = 0 ) const; + std::size_t find_last_of( const String& str, std::size_t pos = StringType::npos ) const; - std::size_t find_last_of ( const String& str, std::size_t pos = StringType::npos ) const; + std::size_t find_last_of( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t find_last_of ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t find_last_of( const char* s, std::size_t pos = StringType::npos ) const; - std::size_t find_last_of ( const char* s, std::size_t pos = StringType::npos ) const; + std::size_t find_last_of( StringBaseType c, std::size_t pos = StringType::npos ) const; - std::size_t find_last_of ( StringBaseType c, std::size_t pos = StringType::npos ) const; + std::size_t find_first_not_of( const String& str, std::size_t pos = 0 ) const; - std::size_t find_first_not_of ( const String& str, std::size_t pos = 0 ) const; + std::size_t find_first_not_of( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t find_first_not_of( const char* s, std::size_t pos = 0 ) const; - std::size_t find_first_not_of ( const char* s, std::size_t pos = 0 ) const; + std::size_t find_first_not_of( StringBaseType c, std::size_t pos = 0 ) const; - std::size_t find_first_not_of ( StringBaseType c, std::size_t pos = 0 ) const; + std::size_t find_last_not_of( const String& str, std::size_t pos = StringType::npos ) const; - std::size_t find_last_not_of ( const String& str, std::size_t pos = StringType::npos ) const; + std::size_t find_last_not_of( const char* s, std::size_t pos, std::size_t n ) const; - std::size_t find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const; + std::size_t find_last_not_of( const char* s, std::size_t pos = StringType::npos ) const; - std::size_t find_last_not_of ( const char* s, std::size_t pos = StringType::npos ) const; + std::size_t find_last_not_of( StringBaseType c, std::size_t pos = StringType::npos ) const; - std::size_t find_last_not_of ( StringBaseType c, std::size_t pos = StringType::npos ) const; -private : - friend bool operator ==(const String& left, const String& right); - friend bool operator <(const String& left, const String& right); + private: + friend bool operator==( const String& left, const String& right ); + friend bool operator<( const String& left, const String& right ); StringType mString; ///< Internal string of UTF-32 characters }; @@ -530,7 +532,7 @@ private : ** @param right Right operand (a string) ** @return True if both strings are equal **/ - bool operator ==(const String& left, const String& right); +bool operator==( const String& left, const String& right ); /** @relates String ** @brief Overload of != operator to compare two UTF-32 strings @@ -538,7 +540,7 @@ private : ** @param right Right operand (a string) ** @return True if both strings are different **/ - bool operator !=(const String& left, const String& right); +bool operator!=( const String& left, const String& right ); /** @relates String ** @brief Overload of < operator to compare two UTF-32 strings @@ -546,7 +548,7 @@ private : ** @param right Right operand (a string) ** @return True if \a left is alphabetically lesser than \a right **/ - bool operator <(const String& left, const String& right); +bool operator<( const String& left, const String& right ); /** @relates String ** @brief Overload of > operator to compare two UTF-32 strings @@ -554,7 +556,7 @@ private : ** @param right Right operand (a string) ** @return True if \a left is alphabetically greater than \a right **/ - bool operator >(const String& left, const String& right); +bool operator>( const String& left, const String& right ); /** @relates String ** @brief Overload of <= operator to compare two UTF-32 strings @@ -562,7 +564,7 @@ private : ** @param right Right operand (a string) ** @return True if \a left is alphabetically lesser or equal than \a right **/ - bool operator <=(const String& left, const String& right); +bool operator<=( const String& left, const String& right ); /** @relates String ** @brief Overload of >= operator to compare two UTF-32 strings @@ -570,7 +572,7 @@ private : ** @param right Right operand (a string) ** @return True if \a left is alphabetically greater or equal than \a right **/ - bool operator >=(const String& left, const String& right); +bool operator>=( const String& left, const String& right ); /** @relates String ** @brief Overload of binary + operator to concatenate two strings @@ -578,9 +580,9 @@ private : ** @param right Right operand (a string) ** @return Concatenated string **/ - String operator +( const String& left, const String& right ); +String operator+( const String& left, const String& right ); -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/System.cpp b/dep/efsw/src/efsw/System.cpp index f8767cbc58f..ba68bf4a74f 100644 --- a/dep/efsw/src/efsw/System.cpp +++ b/dep/efsw/src/efsw/System.cpp @@ -3,24 +3,20 @@ namespace efsw { -void System::sleep( const unsigned long& ms ) -{ +void System::sleep( const unsigned long& ms ) { Platform::System::sleep( ms ); } -std::string System::getProcessPath() -{ +std::string System::getProcessPath() { return Platform::System::getProcessPath(); } -void System::maxFD() -{ +void System::maxFD() { Platform::System::maxFD(); } -Uint64 System::getMaxFD() -{ +Uint64 System::getMaxFD() { return Platform::System::getMaxFD(); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/System.hpp b/dep/efsw/src/efsw/System.hpp index 1d6f4a70f91..498e1211531 100644 --- a/dep/efsw/src/efsw/System.hpp +++ b/dep/efsw/src/efsw/System.hpp @@ -5,22 +5,21 @@ namespace efsw { -class System -{ - public: - /// Sleep for x milliseconds - static void sleep( const unsigned long& ms ); +class System { + public: + /// Sleep for x milliseconds + static void sleep( const unsigned long& ms ); - /// @return The process binary path - static std::string getProcessPath(); + /// @return The process binary path + static std::string getProcessPath(); - /// Maximize the number of file descriptors allowed per process in the current OS - static void maxFD(); + /// Maximize the number of file descriptors allowed per process in the current OS + static void maxFD(); - /// @return The number of supported file descriptors for the process - static Uint64 getMaxFD(); + /// @return The number of supported file descriptors for the process + static Uint64 getMaxFD(); }; - -} + +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/Thread.cpp b/dep/efsw/src/efsw/Thread.cpp index fff41517dc1..cfa88b482d3 100644 --- a/dep/efsw/src/efsw/Thread.cpp +++ b/dep/efsw/src/efsw/Thread.cpp @@ -3,49 +3,39 @@ namespace efsw { -Thread::Thread() : - mThreadImpl(NULL), - mEntryPoint(NULL) -{ -} +Thread::Thread() : mThreadImpl( NULL ), mEntryPoint( NULL ) {} -Thread::~Thread() -{ +Thread::~Thread() { wait(); efSAFE_DELETE( mEntryPoint ); } -void Thread::launch() -{ +void Thread::launch() { wait(); mThreadImpl = new Platform::ThreadImpl( this ); } -void Thread::wait() -{ - if ( mThreadImpl ) - { +void Thread::wait() { + if ( mThreadImpl ) { mThreadImpl->wait(); efSAFE_DELETE( mThreadImpl ); } } -void Thread::terminate() -{ - if ( mThreadImpl ) - { +void Thread::terminate() { + if ( mThreadImpl ) { mThreadImpl->terminate(); efSAFE_DELETE( mThreadImpl ); } } -void Thread::run() -{ - mEntryPoint->run(); +void Thread::run() { + if ( mEntryPoint ) + mEntryPoint->run(); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/Thread.hpp b/dep/efsw/src/efsw/Thread.hpp index c7da9e8b33c..b60373c2075 100644 --- a/dep/efsw/src/efsw/Thread.hpp +++ b/dep/efsw/src/efsw/Thread.hpp @@ -5,107 +5,96 @@ namespace efsw { -namespace Platform { class ThreadImpl; } -namespace Private { struct ThreadFunc; } +namespace Platform { +class ThreadImpl; +} +namespace Private { +struct ThreadFunc; +} /** @brief Thread manager class */ class Thread { - public: - typedef void (*FuncType)(void*); + public: + typedef void ( *FuncType )( void* ); - template <typename F> - Thread( F function ); + template <typename F> Thread( F function ); - template <typename F, typename A> - Thread( F function, A argument ); + template <typename F, typename A> Thread( F function, A argument ); - template <typename C> - Thread( void(C::*function)(), C* object ); + template <typename C> Thread( void ( C::*function )(), C* object ); - virtual ~Thread(); + virtual ~Thread(); - /** Launch the thread */ - virtual void launch(); + /** Launch the thread */ + virtual void launch(); - /** Wait the thread until end */ - void wait(); + /** Wait the thread until end */ + void wait(); - /** Terminate the thread */ - void terminate(); - protected: - Thread(); - private: - friend class Platform::ThreadImpl; + /** Terminate the thread */ + void terminate(); - /** The virtual function to run in the thread */ - virtual void run(); + protected: + Thread(); - Platform::ThreadImpl * mThreadImpl; ///< OS-specific implementation of the thread - Private::ThreadFunc * mEntryPoint; ///< Abstraction of the function to run + private: + friend class Platform::ThreadImpl; + + /** The virtual function to run in the thread */ + virtual void run(); + + Platform::ThreadImpl* mThreadImpl; ///< OS-specific implementation of the thread + Private::ThreadFunc* mEntryPoint; ///< Abstraction of the function to run }; //! NOTE: Taken from SFML2 threads namespace Private { // Base class for abstract thread functions -struct ThreadFunc -{ +struct ThreadFunc { virtual ~ThreadFunc() {} virtual void run() = 0; }; // Specialization using a functor (including free functions) with no argument -template <typename T> -struct ThreadFunctor : ThreadFunc -{ - ThreadFunctor(T functor) : m_functor(functor) {} - virtual void run() {m_functor();} +template <typename T> struct ThreadFunctor : ThreadFunc { + ThreadFunctor( T functor ) : m_functor( functor ) {} + virtual void run() { m_functor(); } T m_functor; }; // Specialization using a functor (including free functions) with one argument -template <typename F, typename A> -struct ThreadFunctorWithArg : ThreadFunc -{ - ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} - virtual void run() {m_function(m_arg);} +template <typename F, typename A> struct ThreadFunctorWithArg : ThreadFunc { + ThreadFunctorWithArg( F function, A arg ) : m_function( function ), m_arg( arg ) {} + virtual void run() { m_function( m_arg ); } F m_function; A m_arg; }; // Specialization using a member function -template <typename C> -struct ThreadMemberFunc : ThreadFunc -{ - ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} - virtual void run() {(m_object->*m_function)();} - void(C::*m_function)(); +template <typename C> struct ThreadMemberFunc : ThreadFunc { + ThreadMemberFunc( void ( C::*function )(), C* object ) : + m_function( function ), m_object( object ) {} + virtual void run() { ( m_object->*m_function )(); } + void ( C::*m_function )(); C* m_object; }; -} +} // namespace Private template <typename F> -Thread::Thread(F functor) : - mThreadImpl (NULL), - mEntryPoint( new Private::ThreadFunctor<F>(functor) ) -{ -} +Thread::Thread( F functor ) : + mThreadImpl( NULL ), mEntryPoint( new Private::ThreadFunctor<F>( functor ) ) {} template <typename F, typename A> -Thread::Thread(F function, A argument) : - mThreadImpl(NULL), - mEntryPoint( new Private::ThreadFunctorWithArg<F efCOMMA A>(function, argument) ) -{ -} +Thread::Thread( F function, A argument ) : + mThreadImpl( NULL ), + mEntryPoint( new Private::ThreadFunctorWithArg<F efCOMMA A>( function, argument ) ) {} template <typename C> -Thread::Thread(void(C::*function)(), C* object) : - mThreadImpl(NULL), - mEntryPoint( new Private::ThreadMemberFunc<C>(function, object) ) -{ -} +Thread::Thread( void ( C::*function )(), C* object ) : + mThreadImpl( NULL ), mEntryPoint( new Private::ThreadMemberFunc<C>( function, object ) ) {} -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/Utf.hpp b/dep/efsw/src/efsw/Utf.hpp index 925a7cc149b..6e9ea719d01 100644 --- a/dep/efsw/src/efsw/Utf.hpp +++ b/dep/efsw/src/efsw/Utf.hpp @@ -1,7 +1,8 @@ /** NOTE: -* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php ) -* The class was modified to fit efsw own needs. This is not the original implementation from SFML2. -* */ + * This code is based on the Utf implementation from SFML2. License zlib/png ( + *http://www.sfml-dev.org/license.php ) The class was modified to fit efsw own needs. This is not + *the original implementation from SFML2. + * */ #ifndef EFSW_UTF_HPP #define EFSW_UTF_HPP @@ -9,721 +10,693 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include <locale> -#include <string> #include <cstdlib> #include <efsw/base.hpp> +#include <locale> +#include <string> namespace efsw { -template <unsigned int N> -class Utf; +template <unsigned int N> class Utf; //////////////////////////////////////////////////////////// /// \brief Specialization of the Utf template for UTF-8 /// //////////////////////////////////////////////////////////// -template <> -class Utf<8> { -public : - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-8 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-8 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-8 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-8. - /// - /// \param input Codepoint to encode as UTF-8 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename Out> - static Out Encode(Uint32 input, Out output, Uint8 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-8 character - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-8 sequence - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element, thus the - /// total size can be different from (begin - end). - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static std::size_t Count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-8 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); +template <> class Utf<8> { + public: + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-8 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-8 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-8 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-8. + /// + /// \param input Codepoint to encode as UTF-8 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> static Out Encode( Uint32 input, Out output, Uint8 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-8 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static In Next( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-8 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static std::size_t Count( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-8 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi( In begin, In end, Out output, char replacement = 0, + const std::locale& locale = std::locale() ); #ifndef EFSW_NO_WIDECHAR - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); #endif - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-8 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-8 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other /// specializations of the efsw::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-8 characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf32(In begin, In end, Out output); + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); }; //////////////////////////////////////////////////////////// /// \brief Specialization of the Utf template for UTF-16 /// //////////////////////////////////////////////////////////// -template <> -class Utf<16> -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-16 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-16 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-16 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-16. - /// - /// \param input Codepoint to encode as UTF-16 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename Out> - static Out Encode(Uint32 input, Out output, Uint16 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-16 character - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-16 sequence - /// - /// This function is necessary for multi-elements encodings, as - /// a single character may use more than 1 storage element, thus the - /// total size can be different from (begin - end). - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static std::size_t Count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-16 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); +template <> class Utf<16> { + public: + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-16 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-16 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-16 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-16. + /// + /// \param input Codepoint to encode as UTF-16 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> static Out Encode( Uint32 input, Out output, Uint16 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-16 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static In Next( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-16 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static std::size_t Count( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-16 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi( In begin, In end, Out output, char replacement = 0, + const std::locale& locale = std::locale() ); #ifndef EFSW_NO_WIDECHAR - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); #endif - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-16 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-16 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other /// specializations of the efsw::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-16 characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf32(In begin, In end, Out output); + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); }; //////////////////////////////////////////////////////////// /// \brief Specialization of the Utf template for UTF-32 /// //////////////////////////////////////////////////////////// -template <> -class Utf<32> -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Decode a single UTF-32 character - /// - /// Decoding a character means finding its unique 32-bits - /// code (called the codepoint) in the Unicode standard. - /// For UTF-32, the character value is the same as the codepoint. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Codepoint of the decoded UTF-32 character - /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character - /// - /// Encoding a character means converting a unique 32-bits - /// code (called the codepoint) in the target encoding, UTF-32. - /// For UTF-32, the codepoint is the same as the character value. - /// - /// \param input Codepoint to encode as UTF-32 - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename Out> - static Out Encode(Uint32 input, Out output, Uint32 replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Advance to the next UTF-32 character - /// - /// This function is trivial for UTF-32, which can store - /// every character in a single storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static In Next(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Count the number of characters of a UTF-32 sequence - /// - /// This function is trivial for UTF-32, which can store - /// every character in a single storage element. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// - /// \return Iterator pointing to one past the last read element of the input sequence - /// - //////////////////////////////////////////////////////////// - template <typename In> - static std::size_t Count(In begin, In end); - - //////////////////////////////////////////////////////////// - /// \brief Convert an ANSI characters range to UTF-32 - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Convert a wide characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromWide(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out FromLatin1(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-32 characters range to ANSI characters - /// - /// The current global locale will be used by default, unless you - /// pass a custom one in the \a locale parameter. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); +template <> class Utf<32> { + public: + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-32 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// For UTF-32, the character value is the same as the codepoint. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-32 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> + static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-32. + /// For UTF-32, the codepoint is the same as the character value. + /// + /// \param input Codepoint to encode as UTF-32 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> static Out Encode( Uint32 input, Out output, Uint32 replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-32 character + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static In Next( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-32 sequence + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template <typename In> static std::size_t Count( In begin, In end ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-32 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToAnsi( In begin, In end, Out output, char replacement = 0, + const std::locale& locale = std::locale() ); #ifndef EFSW_NO_WIDECHAR - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-32 characters range to wide characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0); + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); #endif - //////////////////////////////////////////////////////////// - /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToLatin1(In begin, In end, Out output, char replacement = 0); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-8 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out toUtf8(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-16 - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf16(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Convert a UTF-32 characters range to UTF-32 - /// - /// This functions does nothing more than a direct copy; - /// it is defined only to provide the same interface as other + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> + static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-32 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other /// specializations of the efsw::Utf<> template, and allow - /// generic code to be written on top of it. - /// - /// \param begin Iterator pointing to the beginning of the input sequence - /// \param end Iterator pointing to the end of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename In, typename Out> - static Out ToUtf32(In begin, In end, Out output); - - //////////////////////////////////////////////////////////// - /// \brief Decode a single ANSI character to UTF-32 - /// - /// This function does not exist in other specializations + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single ANSI character to UTF-32 + /// + /// This function does not exist in other specializations /// of efsw::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param input Input ANSI character - /// \param locale Locale to use for conversion - /// - /// \return Converted character - /// - //////////////////////////////////////////////////////////// - template <typename In> - static Uint32 DecodeAnsi(In input, const std::locale& locale = std::locale()); - - //////////////////////////////////////////////////////////// - /// \brief Decode a single wide character to UTF-32 - /// - /// This function does not exist in other specializations + /// several other conversion functions). + /// + /// \param input Input ANSI character + /// \param locale Locale to use for conversion + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template <typename In> + static Uint32 DecodeAnsi( In input, const std::locale& locale = std::locale() ); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single wide character to UTF-32 + /// + /// This function does not exist in other specializations /// of efsw::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param input Input wide character - /// - /// \return Converted character - /// - //////////////////////////////////////////////////////////// - template <typename In> - static Uint32 DecodeWide(In input); - - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character to ANSI - /// - /// This function does not exist in other specializations + /// several other conversion functions). + /// + /// \param input Input wide character + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template <typename In> static Uint32 DecodeWide( In input ); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to ANSI + /// + /// This function does not exist in other specializations /// of efsw::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param codepoint Iterator pointing to the beginning of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it) - /// \param locale Locale to use for conversion - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename Out> - static Out EncodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale()); + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to + /// skip it) \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out EncodeAnsi( Uint32 codepoint, Out output, char replacement = 0, + const std::locale& locale = std::locale() ); #ifndef EFSW_NO_WIDECHAR - //////////////////////////////////////////////////////////// - /// \brief Encode a single UTF-32 character to wide - /// - /// This function does not exist in other specializations + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to wide + /// + /// This function does not exist in other specializations /// of efsw::Utf<>, it is defined for convenience (it is used by - /// several other conversion functions). - /// - /// \param codepoint Iterator pointing to the beginning of the input sequence - /// \param output Iterator pointing to the beginning of the output sequence - /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it) - /// - /// \return Iterator to the end of the output sequence which has been written - /// - //////////////////////////////////////////////////////////// - template <typename Out> - static Out EncodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to wide (use 0 to + /// skip it) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template <typename Out> + static Out EncodeWide( Uint32 codepoint, Out output, wchar_t replacement = 0 ); #endif }; #include "Utf.inl" // Make typedefs to get rid of the template syntax -typedef Utf<8> Utf8; +typedef Utf<8> Utf8; typedef Utf<16> Utf16; typedef Utf<32> Utf32; -} +} // namespace efsw #endif //////////////////////////////////////////////////////////// diff --git a/dep/efsw/src/efsw/Utf.inl b/dep/efsw/src/efsw/Utf.inl index db8fd5d61ee..7e3e9d6035a 100644 --- a/dep/efsw/src/efsw/Utf.inl +++ b/dep/efsw/src/efsw/Utf.inl @@ -5,667 +5,572 @@ // http://people.w3.org/rishida/scripts/uniview/conversion //////////////////////////////////////////////////////////// -template <typename In> -In Utf<8>::Decode(In begin, In end, Uint32& output, Uint32 replacement) -{ - // Some useful precomputed data - static const int trailing[256] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 - }; - static const Uint32 offsets[6] = - { - 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 - }; - - // Decode the character - int trailingBytes = trailing[static_cast<Uint8>(*begin)]; - if (begin + trailingBytes < end) - { - output = 0; - switch (trailingBytes) - { - case 5 : output += static_cast<Uint8>(*begin++); output <<= 6; - case 4 : output += static_cast<Uint8>(*begin++); output <<= 6; - case 3 : output += static_cast<Uint8>(*begin++); output <<= 6; - case 2 : output += static_cast<Uint8>(*begin++); output <<= 6; - case 1 : output += static_cast<Uint8>(*begin++); output <<= 6; - case 0 : output += static_cast<Uint8>(*begin++); - } - output -= offsets[trailingBytes]; - } - else - { - // Incomplete character - begin = end; - output = replacement; - } - - return begin; -} - -template <typename Out> -Out Utf<8>::Encode(Uint32 input, Out output, Uint8 replacement) -{ - // Some useful precomputed data - static const Uint8 firstBytes[7] = - { - 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC - }; - - // Encode the character - if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) - { - // Invalid character - if (replacement) - *output++ = replacement; - } - else - { - // Valid character - - // Get the number of bytes to write - int bytesToWrite = 1; - if (input < 0x80) bytesToWrite = 1; - else if (input < 0x800) bytesToWrite = 2; - else if (input < 0x10000) bytesToWrite = 3; - else if (input <= 0x0010FFFF) bytesToWrite = 4; - - // Extract the bytes to write - Uint8 bytes[4]; - switch (bytesToWrite) - { - case 4 : bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; - case 3 : bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; - case 2 : bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6; - case 1 : bytes[0] = static_cast<Uint8> (input | firstBytes[bytesToWrite]); - } - - // Add them to the output - const Uint8* currentByte = bytes; - switch (bytesToWrite) - { - case 4 : *output++ = *currentByte++; - case 3 : *output++ = *currentByte++; - case 2 : *output++ = *currentByte++; - case 1 : *output++ = *currentByte++; - } - } - - return output; -} - -template <typename In> -In Utf<8>::Next(In begin, In end) -{ - Uint32 codepoint; - return Decode(begin, end, codepoint); -} - -template <typename In> -std::size_t Utf<8>::Count(In begin, In end) -{ - std::size_t length = 0; - while (begin < end) - { - begin = Next(begin, end); - ++length; - } - - return length; +template <typename In> In Utf<8>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { + // Some useful precomputed data + static const int trailing[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; + static const Uint32 offsets[6] = { 0x00000000, 0x00003080, 0x000E2080, + 0x03C82080, 0xFA082080, 0x82082080 }; + + // Decode the character + int trailingBytes = trailing[static_cast<Uint8>( *begin )]; + if ( begin + trailingBytes < end ) { + output = 0; + switch ( trailingBytes ) { + case 5: + output += static_cast<Uint8>( *begin++ ); + output <<= 6; + case 4: + output += static_cast<Uint8>( *begin++ ); + output <<= 6; + case 3: + output += static_cast<Uint8>( *begin++ ); + output <<= 6; + case 2: + output += static_cast<Uint8>( *begin++ ); + output <<= 6; + case 1: + output += static_cast<Uint8>( *begin++ ); + output <<= 6; + case 0: + output += static_cast<Uint8>( *begin++ ); + } + output -= offsets[trailingBytes]; + } else { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + +template <typename Out> Out Utf<8>::Encode( Uint32 input, Out output, Uint8 replacement ) { + // Some useful precomputed data + static const Uint8 firstBytes[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + // Encode the character + if ( ( input > 0x0010FFFF ) || ( ( input >= 0xD800 ) && ( input <= 0xDBFF ) ) ) { + // Invalid character + if ( replacement ) + *output++ = replacement; + } else { + // Valid character + + // Get the number of bytes to write + int bytesToWrite = 1; + if ( input < 0x80 ) + bytesToWrite = 1; + else if ( input < 0x800 ) + bytesToWrite = 2; + else if ( input < 0x10000 ) + bytesToWrite = 3; + else if ( input <= 0x0010FFFF ) + bytesToWrite = 4; + + // Extract the bytes to write + Uint8 bytes[4]; + switch ( bytesToWrite ) { + case 4: + bytes[3] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); + input >>= 6; + case 3: + bytes[2] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); + input >>= 6; + case 2: + bytes[1] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); + input >>= 6; + case 1: + bytes[0] = static_cast<Uint8>( input | firstBytes[bytesToWrite] ); + } + + // Add them to the output + const Uint8* currentByte = bytes; + switch ( bytesToWrite ) { + case 4: + *output++ = *currentByte++; + case 3: + *output++ = *currentByte++; + case 2: + *output++ = *currentByte++; + case 1: + *output++ = *currentByte++; + } + } + + return output; +} + +template <typename In> In Utf<8>::Next( In begin, In end ) { + Uint32 codepoint; + return Decode( begin, end, codepoint ); +} + +template <typename In> std::size_t Utf<8>::Count( In begin, In end ) { + std::size_t length = 0; + while ( begin < end ) { + begin = Next( begin, end ); + ++length; + } + + return length; } template <typename In, typename Out> -Out Utf<8>::FromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale); - output = Encode(codepoint, output); - } +Out Utf<8>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { + while ( begin < end ) { + Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); + output = Encode( codepoint, output ); + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<8>::FromWide(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::DecodeWide(*begin++); - output = Encode(codepoint, output); - } +template <typename In, typename Out> Out Utf<8>::FromWide( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); + output = Encode( codepoint, output ); + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<8>::FromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - output = Encode(*begin++, output); +template <typename In, typename Out> Out Utf<8>::FromLatin1( In begin, In end, Out output ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) + output = Encode( *begin++, output ); - return output; + return output; } template <typename In, typename Out> -Out Utf<8>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale); - } +Out Utf<8>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); + } - return output; + return output; } #ifndef EFSW_NO_WIDECHAR template <typename In, typename Out> -Out Utf<8>::ToWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<32>::EncodeWide(codepoint, output, replacement); - } +Out Utf<8>::ToWide( In begin, In end, Out output, wchar_t replacement ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<32>::EncodeWide( codepoint, output, replacement ); + } - return output; + return output; } #endif template <typename In, typename Out> -Out Utf<8>::ToLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - *output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement; - } - - return output; +Out Utf<8>::ToLatin1( In begin, In end, Out output, char replacement ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + *output++ = codepoint < 256 ? static_cast<char>( codepoint ) : replacement; + } + + return output; +} + +template <typename In, typename Out> Out Utf<8>::toUtf8( In begin, In end, Out output ) { + while ( begin < end ) + *output++ = *begin++; + + return output; +} + +template <typename In, typename Out> Out Utf<8>::ToUtf16( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<16>::Encode( codepoint, output ); + } + + return output; +} + +template <typename In, typename Out> Out Utf<8>::ToUtf32( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + *output++ = codepoint; + } + + return output; +} + +template <typename In> In Utf<16>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { + Uint16 first = *begin++; + + // If it's a surrogate pair, first convert to a single UTF-32 character + if ( ( first >= 0xD800 ) && ( first <= 0xDBFF ) ) { + if ( begin < end ) { + Uint32 second = *begin++; + if ( ( second >= 0xDC00 ) && ( second <= 0xDFFF ) ) { + // The second element is valid: convert the two elements to a UTF-32 character + output = static_cast<Uint32>( ( ( first - 0xD800 ) << 10 ) + ( second - 0xDC00 ) + + 0x0010000 ); + } else { + // Invalid character + output = replacement; + } + } else { + // Invalid character + begin = end; + output = replacement; + } + } else { + // We can make a direct copy + output = first; + } + + return begin; +} + +template <typename Out> Out Utf<16>::Encode( Uint32 input, Out output, Uint16 replacement ) { + if ( input < 0xFFFF ) { + // The character can be copied directly, we just need to check if it's in the valid range + if ( ( input >= 0xD800 ) && ( input <= 0xDFFF ) ) { + // Invalid character (this range is reserved) + if ( replacement ) + *output++ = replacement; + } else { + // Valid character directly convertible to a single UTF-16 character + *output++ = static_cast<Uint16>( input ); + } + } else if ( input > 0x0010FFFF ) { + // Invalid character (greater than the maximum unicode value) + if ( replacement ) + *output++ = replacement; + } else { + // The input character will be converted to two UTF-16 elements + input -= 0x0010000; + *output++ = static_cast<Uint16>( ( input >> 10 ) + 0xD800 ); + *output++ = static_cast<Uint16>( ( input & 0x3FFUL ) + 0xDC00 ); + } + + return output; +} + +template <typename In> In Utf<16>::Next( In begin, In end ) { + Uint32 codepoint; + return Decode( begin, end, codepoint ); +} + +template <typename In> std::size_t Utf<16>::Count( In begin, In end ) { + std::size_t length = 0; + while ( begin < end ) { + begin = Next( begin, end ); + ++length; + } + + return length; } template <typename In, typename Out> -Out Utf<8>::toUtf8(In begin, In end, Out output) -{ - while (begin < end) - *output++ = *begin++; +Out Utf<16>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { + while ( begin < end ) { + Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); + output = Encode( codepoint, output ); + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<8>::ToUtf16(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<16>::Encode(codepoint, output); - } - - return output; -} - -template <typename In, typename Out> -Out Utf<8>::ToUtf32(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - *output++ = codepoint; - } - - return output; -} - -template <typename In> -In Utf<16>::Decode(In begin, In end, Uint32& output, Uint32 replacement) -{ - Uint16 first = *begin++; - - // If it's a surrogate pair, first convert to a single UTF-32 character - if ((first >= 0xD800) && (first <= 0xDBFF)) - { - if (begin < end) - { - Uint32 second = *begin++; - if ((second >= 0xDC00) && (second <= 0xDFFF)) - { - // The second element is valid: convert the two elements to a UTF-32 character - output = static_cast<Uint32>(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); - } - else - { - // Invalid character - output = replacement; - } - } - else - { - // Invalid character - begin = end; - output = replacement; - } - } - else - { - // We can make a direct copy - output = first; - } - - return begin; -} - -template <typename Out> -Out Utf<16>::Encode(Uint32 input, Out output, Uint16 replacement) -{ - if (input < 0xFFFF) - { - // The character can be copied directly, we just need to check if it's in the valid range - if ((input >= 0xD800) && (input <= 0xDFFF)) - { - // Invalid character (this range is reserved) - if (replacement) - *output++ = replacement; - } - else - { - // Valid character directly convertible to a single UTF-16 character - *output++ = static_cast<Uint16>(input); - } - } - else if (input > 0x0010FFFF) - { - // Invalid character (greater than the maximum unicode value) - if (replacement) - *output++ = replacement; - } - else - { - // The input character will be converted to two UTF-16 elements - input -= 0x0010000; - *output++ = static_cast<Uint16>((input >> 10) + 0xD800); - *output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00); - } - - return output; -} - -template <typename In> -In Utf<16>::Next(In begin, In end) -{ - Uint32 codepoint; - return Decode(begin, end, codepoint); -} - -template <typename In> -std::size_t Utf<16>::Count(In begin, In end) -{ - std::size_t length = 0; - while (begin < end) - { - begin = Next(begin, end); - ++length; - } - - return length; -} - -template <typename In, typename Out> -Out Utf<16>::FromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale); - output = Encode(codepoint, output); - } - - return output; -} - -template <typename In, typename Out> -Out Utf<16>::FromWide(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint = Utf<32>::DecodeWide(*begin++); - output = Encode(codepoint, output); - } +template <typename In, typename Out> Out Utf<16>::FromWide( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); + output = Encode( codepoint, output ); + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<16>::FromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - *output++ = *begin++; +template <typename In, typename Out> Out Utf<16>::FromLatin1( In begin, In end, Out output ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) + *output++ = *begin++; - return output; + return output; } template <typename In, typename Out> -Out Utf<16>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale); - } +Out Utf<16>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); + } - return output; + return output; } #ifndef EFSW_NO_WIDECHAR template <typename In, typename Out> -Out Utf<16>::ToWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<32>::EncodeWide(codepoint, output, replacement); - } +Out Utf<16>::ToWide( In begin, In end, Out output, wchar_t replacement ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<32>::EncodeWide( codepoint, output, replacement ); + } - return output; + return output; } #endif template <typename In, typename Out> -Out Utf<16>::ToLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement; - begin++; - } +Out Utf<16>::ToLatin1( In begin, In end, Out output, char replacement ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) { + *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; + begin++; + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<16>::toUtf8(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - output = Utf<8>::Encode(codepoint, output); - } +template <typename In, typename Out> Out Utf<16>::toUtf8( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + output = Utf<8>::Encode( codepoint, output ); + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<16>::ToUtf16(In begin, In end, Out output) -{ - while (begin < end) - *output++ = *begin++; +template <typename In, typename Out> Out Utf<16>::ToUtf16( In begin, In end, Out output ) { + while ( begin < end ) + *output++ = *begin++; - return output; + return output; } -template <typename In, typename Out> -Out Utf<16>::ToUtf32(In begin, In end, Out output) -{ - while (begin < end) - { - Uint32 codepoint; - begin = Decode(begin, end, codepoint); - *output++ = codepoint; - } +template <typename In, typename Out> Out Utf<16>::ToUtf32( In begin, In end, Out output ) { + while ( begin < end ) { + Uint32 codepoint; + begin = Decode( begin, end, codepoint ); + *output++ = codepoint; + } - return output; + return output; } -template <typename In> -In Utf<32>::Decode(In begin, In end, Uint32& output, Uint32) -{ - output = *begin++; - return begin; +template <typename In> In Utf<32>::Decode( In begin, In end, Uint32& output, Uint32 ) { + output = *begin++; + return begin; } -template <typename Out> -Out Utf<32>::Encode(Uint32 input, Out output, Uint32 replacement) -{ - *output++ = input; - return output; +template <typename Out> Out Utf<32>::Encode( Uint32 input, Out output, Uint32 replacement ) { + *output++ = input; + return output; } -template <typename In> -In Utf<32>::Next(In begin, In end) -{ - return ++begin; +template <typename In> In Utf<32>::Next( In begin, In end ) { + return ++begin; } -template <typename In> -std::size_t Utf<32>::Count(In begin, In end) -{ - return begin - end; +template <typename In> std::size_t Utf<32>::Count( In begin, In end ) { + return begin - end; } template <typename In, typename Out> -Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale) -{ - while (begin < end) - *output++ = DecodeAnsi(*begin++, locale); +Out Utf<32>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { + while ( begin < end ) + *output++ = DecodeAnsi( *begin++, locale ); - return output; + return output; } -template <typename In, typename Out> -Out Utf<32>::FromWide(In begin, In end, Out output) -{ - while (begin < end) - *output++ = DecodeWide(*begin++); +template <typename In, typename Out> Out Utf<32>::FromWide( In begin, In end, Out output ) { + while ( begin < end ) + *output++ = DecodeWide( *begin++ ); - return output; + return output; } -template <typename In, typename Out> -Out Utf<32>::FromLatin1(In begin, In end, Out output) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - *output++ = *begin++; +template <typename In, typename Out> Out Utf<32>::FromLatin1( In begin, In end, Out output ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) + *output++ = *begin++; - return output; + return output; } template <typename In, typename Out> -Out Utf<32>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) -{ - while (begin < end) - output = EncodeAnsi(*begin++, output, replacement, locale); +Out Utf<32>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { + while ( begin < end ) + output = EncodeAnsi( *begin++, output, replacement, locale ); - return output; + return output; } #ifndef EFSW_NO_WIDECHAR template <typename In, typename Out> -Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement) -{ - while (begin < end) - output = EncodeWide(*begin++, output, replacement); +Out Utf<32>::ToWide( In begin, In end, Out output, wchar_t replacement ) { + while ( begin < end ) + output = EncodeWide( *begin++, output, replacement ); - return output; + return output; } #endif template <typename In, typename Out> -Out Utf<32>::ToLatin1(In begin, In end, Out output, char replacement) -{ - // Latin-1 is directly compatible with Unicode encodings, - // and can thus be treated as (a sub-range of) UTF-32 - while (begin < end) - { - *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement; - begin++; - } +Out Utf<32>::ToLatin1( In begin, In end, Out output, char replacement ) { + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while ( begin < end ) { + *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; + begin++; + } - return output; + return output; } -template <typename In, typename Out> -Out Utf<32>::toUtf8(In begin, In end, Out output) -{ - while (begin < end) - output = Utf<8>::Encode(*begin++, output); +template <typename In, typename Out> Out Utf<32>::toUtf8( In begin, In end, Out output ) { + while ( begin < end ) + output = Utf<8>::Encode( *begin++, output ); - return output; + return output; } -template <typename In, typename Out> -Out Utf<32>::ToUtf16(In begin, In end, Out output) -{ - while (begin < end) - output = Utf<16>::Encode(*begin++, output); +template <typename In, typename Out> Out Utf<32>::ToUtf16( In begin, In end, Out output ) { + while ( begin < end ) + output = Utf<16>::Encode( *begin++, output ); - return output; + return output; } -template <typename In, typename Out> -Out Utf<32>::ToUtf32(In begin, In end, Out output) -{ - while (begin < end) - *output++ = *begin++; +template <typename In, typename Out> Out Utf<32>::ToUtf32( In begin, In end, Out output ) { + while ( begin < end ) + *output++ = *begin++; - return output; + return output; } -template <typename In> -Uint32 Utf<32>::DecodeAnsi(In input, const std::locale& locale) -{ - // On Windows, gcc's standard library (glibc++) has almost - // no support for Unicode stuff. As a consequence, in this - // context we can only use the default locale and ignore - // the one passed as parameter. +template <typename In> Uint32 Utf<32>::DecodeAnsi( In input, const std::locale& locale ) { + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. - #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ - (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ - !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ + ( defined( __GLIBCPP__ ) || \ + defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ + !( defined( __SGI_STL_PORT ) || \ + defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ - wchar_t character = 0; - mbtowc(&character, &input, 1); - return static_cast<Uint32>(character); + wchar_t character = 0; + mbtowc( &character, &input, 1 ); + return static_cast<Uint32>( character ); - #else - // Get the facet of the locale which deals with character conversion - #ifndef EFSW_NO_WIDECHAR - const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale); - #else - const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale); - #endif - - // Use the facet to convert each character of the input string - return static_cast<Uint32>(facet.widen(input)); +#else +// Get the facet of the locale which deals with character conversion +#ifndef EFSW_NO_WIDECHAR + const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); +#else + const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); +#endif + + // Use the facet to convert each character of the input string + return static_cast<Uint32>( facet.widen( input ) ); - #endif +#endif } -template <typename In> -Uint32 Utf<32>::DecodeWide(In input) -{ - // The encoding of wide characters is not well defined and is left to the system; - // however we can safely assume that it is UCS-2 on Windows and - // UCS-4 on Unix systems. - // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, - // and UCS-4 *is* UTF-32). +template <typename In> Uint32 Utf<32>::DecodeWide( In input ) { + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, + // and UCS-4 *is* UTF-32). - return input; + return input; } template <typename Out> -Out Utf<32>::EncodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale) -{ - // On Windows, gcc's standard library (glibc++) has almost - // no support for Unicode stuff. As a consequence, in this - // context we can only use the default locale and ignore - // the one passed as parameter. - - #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ - (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ - !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ - - char character = 0; - if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0) - *output++ = character; - else if (replacement) - *output++ = replacement; - - return output; - - #else - // Get the facet of the locale which deals with character conversion - #ifndef EFSW_NO_WIDECHAR - const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale); - #else - const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale); - #endif +Out Utf<32>::EncodeAnsi( Uint32 codepoint, Out output, char replacement, + const std::locale& locale ) { + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + +#if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ + ( defined( __GLIBCPP__ ) || \ + defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ + !( defined( __SGI_STL_PORT ) || \ + defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ + + char character = 0; + if ( wctomb( &character, static_cast<wchar_t>( codepoint ) ) >= 0 ) + *output++ = character; + else if ( replacement ) + *output++ = replacement; + + return output; + +#else +// Get the facet of the locale which deals with character conversion +#ifndef EFSW_NO_WIDECHAR + const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); +#else + const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); +#endif - // Use the facet to convert each character of the input string - *output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement); + // Use the facet to convert each character of the input string + *output++ = facet.narrow( static_cast<wchar_t>( codepoint ), replacement ); - return output; + return output; - #endif +#endif } #ifndef EFSW_NO_WIDECHAR template <typename Out> -Out Utf<32>::EncodeWide(Uint32 codepoint, Out output, wchar_t replacement) -{ - // The encoding of wide characters is not well defined and is left to the system; - // however we can safely assume that it is UCS-2 on Windows and - // UCS-4 on Unix systems. - // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). - // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). - - switch (sizeof(wchar_t)) - { - case 4: - { - *output++ = static_cast<wchar_t>(codepoint); - break; - } - - default: - { - if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) - { - *output++ = static_cast<wchar_t>(codepoint); - } - else if (replacement) - { - *output++ = replacement; - } - break; - } - } - - return output; +Out Utf<32>::EncodeWide( Uint32 codepoint, Out output, wchar_t replacement ) { + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). + // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). + + switch ( sizeof( wchar_t ) ) { + case 4: { + *output++ = static_cast<wchar_t>( codepoint ); + break; + } + + default: { + if ( ( codepoint <= 0xFFFF ) && ( ( codepoint < 0xD800 ) || ( codepoint > 0xDFFF ) ) ) { + *output++ = static_cast<wchar_t>( codepoint ); + } else if ( replacement ) { + *output++ = replacement; + } + break; + } + } + + return output; } #endif diff --git a/dep/efsw/src/efsw/Watcher.cpp b/dep/efsw/src/efsw/Watcher.cpp index d81c84228ad..913ae3c431a 100644 --- a/dep/efsw/src/efsw/Watcher.cpp +++ b/dep/efsw/src/efsw/Watcher.cpp @@ -2,20 +2,9 @@ namespace efsw { -Watcher::Watcher() : - ID(0), - Directory(""), - Listener(NULL), - Recursive(false) -{ -} +Watcher::Watcher() : ID( 0 ), Directory( "" ), Listener( NULL ), Recursive( false ) {} -Watcher::Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive ) : - ID( id ), - Directory( directory ), - Listener( listener ), - Recursive( recursive ) -{ -} +Watcher::Watcher( WatchID id, std::string directory, FileWatchListener* listener, bool recursive ) : + ID( id ), Directory( directory ), Listener( listener ), Recursive( recursive ) {} -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/Watcher.hpp b/dep/efsw/src/efsw/Watcher.hpp index 5a35cb9a2ac..84f0980bc47 100644 --- a/dep/efsw/src/efsw/Watcher.hpp +++ b/dep/efsw/src/efsw/Watcher.hpp @@ -7,24 +7,23 @@ namespace efsw { /** @brief Base Watcher class */ -class Watcher -{ - public: - Watcher(); +class Watcher { + public: + Watcher(); - Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive ); + Watcher( WatchID id, std::string directory, FileWatchListener* listener, bool recursive ); - virtual ~Watcher() {} + virtual ~Watcher() {} - virtual void watch() {} + virtual void watch() {} - WatchID ID; - std::string Directory; - FileWatchListener * Listener; - bool Recursive; - std::string OldFileName; + WatchID ID; + std::string Directory; + FileWatchListener* Listener; + bool Recursive; + std::string OldFileName; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherFSEvents.cpp b/dep/efsw/src/efsw/WatcherFSEvents.cpp index a13a743b01e..3621df746b5 100644 --- a/dep/efsw/src/efsw/WatcherFSEvents.cpp +++ b/dep/efsw/src/efsw/WatcherFSEvents.cpp @@ -1,39 +1,25 @@ -#include <efsw/WatcherFSEvents.hpp> -#include <efsw/FileWatcherFSEvents.hpp> -#include <efsw/FileSystem.hpp> #include <efsw/Debug.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/FileWatcherFSEvents.hpp> +#include <efsw/WatcherFSEvents.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS namespace efsw { WatcherFSEvents::WatcherFSEvents() : - Watcher(), - FWatcher( NULL ), - FSStream( NULL ), - WatcherGen( NULL ), - initializedAsync( false ) -{ -} + Watcher(), FWatcher( NULL ), FSStream( NULL ), WatcherGen( NULL ) {} -WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent ) : +WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener, + bool recursive, WatcherFSEvents* parent ) : Watcher( id, directory, listener, recursive ), FWatcher( NULL ), FSStream( NULL ), - WatcherGen( NULL ), - initializedAsync( false ) -{ -} - -WatcherFSEvents::~WatcherFSEvents() -{ - if ( NULL != FSStream ) - { - if ( initializedAsync ) - { - FSEventStreamStop( FSStream ); - } + WatcherGen( NULL ) {} +WatcherFSEvents::~WatcherFSEvents() { + if ( NULL != FSStream ) { + FSEventStreamStop( FSStream ); FSEventStreamInvalidate( FSStream ); FSEventStreamRelease( FSStream ); } @@ -41,22 +27,19 @@ WatcherFSEvents::~WatcherFSEvents() efSAFE_DELETE( WatcherGen ); } -void WatcherFSEvents::init() -{ - CFStringRef CFDirectory = CFStringCreateWithCString( NULL, Directory.c_str(), kCFStringEncodingUTF8 ); - CFArrayRef CFDirectoryArray = CFArrayCreate( NULL, (const void **)&CFDirectory, 1, NULL ); - +void WatcherFSEvents::init() { + CFStringRef CFDirectory = + CFStringCreateWithCString( NULL, Directory.c_str(), kCFStringEncodingUTF8 ); + CFArrayRef CFDirectoryArray = CFArrayCreate( NULL, (const void**)&CFDirectory, 1, NULL ); + Uint32 streamFlags = kFSEventStreamCreateFlagNone; - - if ( FileWatcherFSEvents::isGranular() ) - { - streamFlags = efswFSEventStreamCreateFlagFileEvents; - } - else - { - WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher, Recursive ); + + if ( FileWatcherFSEvents::isGranular() ) { + streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer; + } else { + WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive ); } - + FSEventStreamContext ctx; /* Initialize context */ ctx.version = 0; @@ -65,200 +48,161 @@ void WatcherFSEvents::init() ctx.release = NULL; ctx.copyDescription = NULL; - FSStream = FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0.25, streamFlags ); + dispatch_queue_t queue = dispatch_queue_create(NULL, NULL); - FWatcher->mNeedInit.push_back( this ); + FSStream = + FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, + CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0., streamFlags ); - CFRelease( CFDirectoryArray ); - CFRelease( CFDirectory ); -} + FSEventStreamSetDispatchQueue(FSStream, queue); -void WatcherFSEvents::initAsync() -{ - FSEventStreamScheduleWithRunLoop( FSStream, FWatcher->mRunLoopRef, kCFRunLoopDefaultMode ); FSEventStreamStart( FSStream ); - initializedAsync = true; + + CFRelease( CFDirectoryArray ); + CFRelease( CFDirectory ); } -void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename ) -{ - Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), FileSystem::precomposeFileName( filename ), action, oldFilename ); +void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, + const std::string& filename, Action action, + std::string oldFilename ) { + Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), + FileSystem::precomposeFileName( filename ), action, FileSystem::precomposeFileName( oldFilename ) ); } -void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, std::string& filePath ) -{ - if ( flags & efswFSEventStreamEventFlagItemCreated ) - { - if ( FileInfo::exists( path ) ) - { +void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, + std::string& dirPath, std::string& filePath ) { + if ( flags & efswFSEventStreamEventFlagItemCreated ) { + if ( FileInfo::exists( path ) ) { sendFileAction( ID, dirPath, filePath, Actions::Add ); } } - if ( flags & efswFSEventsModified ) - { + if ( flags & efswFSEventsModified ) { sendFileAction( ID, dirPath, filePath, Actions::Modified ); } - if ( flags & efswFSEventStreamEventFlagItemRemoved ) - { - // Since i don't know the order, at least i try to keep the data consistent with the real state - if ( !FileInfo::exists( path ) ) - { + if ( flags & efswFSEventStreamEventFlagItemRemoved ) { + // Since i don't know the order, at least i try to keep the data consistent with the real + // state + if ( !FileInfo::exists( path ) ) { sendFileAction( ID, dirPath, filePath, Actions::Delete ); } } } -void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) -{ +void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) { size_t esize = events.size(); - for ( size_t i = 0; i < esize; i++ ) - { + for ( size_t i = 0; i < esize; i++ ) { FSEvent& event = events[i]; - if ( event.Flags & ( kFSEventStreamEventFlagUserDropped | - kFSEventStreamEventFlagKernelDropped | - kFSEventStreamEventFlagEventIdsWrapped | - kFSEventStreamEventFlagHistoryDone | - kFSEventStreamEventFlagMount | - kFSEventStreamEventFlagUnmount | - kFSEventStreamEventFlagRootChanged ) ) - { + if ( event.Flags & + ( kFSEventStreamEventFlagUserDropped | kFSEventStreamEventFlagKernelDropped | + kFSEventStreamEventFlagEventIdsWrapped | kFSEventStreamEventFlagHistoryDone | + kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount | + kFSEventStreamEventFlagRootChanged ) ) { continue; } - if ( !Recursive ) - { + if ( !Recursive ) { /** In case that is not recursive the watcher, ignore the events from subfolders */ - if ( event.Path.find_last_of( FileSystem::getOSSlash() ) != Directory.size() - 1 ) - { + if ( event.Path.find_last_of( FileSystem::getOSSlash() ) != Directory.size() - 1 ) { continue; } } - if ( FileWatcherFSEvents::isGranular() ) - { + if ( FileWatcherFSEvents::isGranular() ) { std::string dirPath( FileSystem::pathRemoveFileName( event.Path ) ); std::string filePath( FileSystem::fileNameFromPath( event.Path ) ); - if ( event.Flags & ( efswFSEventStreamEventFlagItemCreated | - efswFSEventStreamEventFlagItemRemoved | - efswFSEventStreamEventFlagItemRenamed ) - ) - { - if ( dirPath != Directory ) - { + if ( event.Flags & + ( efswFSEventStreamEventFlagItemCreated | efswFSEventStreamEventFlagItemRemoved | + efswFSEventStreamEventFlagItemRenamed ) ) { + if ( dirPath != Directory ) { DirsChanged.insert( dirPath ); } } - // This is a mess. But it's FSEvents faults, because shrinks events from the same file in one single event ( so there's no order for them ) - // For example a file could have been added modified and erased, but i can't know if first was erased and then added and modified, or added, then modified and then erased. - // I don't know what they were thinking by doing this... - efDEBUG( "Event in: %s - flags: %ld\n", path.c_str(), event.Flags ); - - if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) - { - if ( ( i + 1 < esize ) && - ( events[ i + 1 ].Flags & efswFSEventStreamEventFlagItemRenamed ) && - ( events[ i + 1 ].Id == event.Id + 1 ) - ) - { - FSEvent& nEvent = events[ i + 1 ]; + // This is a mess. But it's FSEvents faults, because shrinks events from the same file + // in one single event ( so there's no order for them ) For example a file could have + // been added modified and erased, but i can't know if first was erased and then added + // and modified, or added, then modified and then erased. I don't know what they were + // thinking by doing this... + efDEBUG( "Event in: %s - flags: %ld\n", event.Path.c_str(), event.Flags ); + + if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) { + if ( ( i + 1 < esize ) && + ( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) && + ( events[i + 1].Id == event.Id + 1 ) ) { + FSEvent& nEvent = events[i + 1]; std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) ); std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) ); - if ( event.Path != nEvent.Path ) - { - if ( dirPath == newDir ) - { - if ( !FileInfo::exists( event.Path ) ) - { - sendFileAction( ID, dirPath, newFilepath, Actions::Moved, filePath ); + if ( event.Path != nEvent.Path ) { + if ( dirPath == newDir ) { + if ( !FileInfo::exists( event.Path ) ) { + sendFileAction( ID, dirPath, newFilepath, Actions::Moved, + filePath ); + } else { + sendFileAction( ID, dirPath, filePath, Actions::Moved, + newFilepath ); } - else - { - sendFileAction( ID, dirPath, filePath, Actions::Moved, newFilepath ); - } - } - else - { + } else { sendFileAction( ID, dirPath, filePath, Actions::Delete ); sendFileAction( ID, newDir, newFilepath, Actions::Add ); - if ( nEvent.Flags & efswFSEventsModified ) - { + if ( nEvent.Flags & efswFSEventsModified ) { sendFileAction( ID, newDir, newFilepath, Actions::Modified ); } } - } - else - { + } else { handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath ); } - if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated | - efswFSEventStreamEventFlagItemRemoved | - efswFSEventStreamEventFlagItemRenamed ) - ) - { - if ( newDir != Directory ) - { + if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated | + efswFSEventStreamEventFlagItemRemoved | + efswFSEventStreamEventFlagItemRenamed ) ) { + if ( newDir != Directory ) { DirsChanged.insert( newDir ); } } // Skip the renamed file i++; - } - else if ( FileInfo::exists( event.Path ) ) - { + } else if ( FileInfo::exists( event.Path ) ) { sendFileAction( ID, dirPath, filePath, Actions::Add ); - if ( event.Flags & efswFSEventsModified ) - { + if ( event.Flags & efswFSEventsModified ) { sendFileAction( ID, dirPath, filePath, Actions::Modified ); } - } - else - { + } else { sendFileAction( ID, dirPath, filePath, Actions::Delete ); } - } - else - { + } else { handleAddModDel( event.Flags, event.Path, dirPath, filePath ); } - } - else - { + } else { efDEBUG( "Directory: %s changed\n", event.Path.c_str() ); DirsChanged.insert( event.Path ); } } } -void WatcherFSEvents::process() -{ +void WatcherFSEvents::process() { std::set<std::string>::iterator it = DirsChanged.begin(); - for ( ; it != DirsChanged.end(); it++ ) - { - if ( !FileWatcherFSEvents::isGranular() ) - { - WatcherGen->watchDir( (*it) ); - } - else - { - sendFileAction( ID, FileSystem::pathRemoveFileName( (*it) ), FileSystem::fileNameFromPath( (*it) ), Actions::Modified ); + for ( ; it != DirsChanged.end(); it++ ) { + if ( !FileWatcherFSEvents::isGranular() ) { + WatcherGen->watchDir( ( *it ) ); + } else { + sendFileAction( ID, FileSystem::pathRemoveFileName( ( *it ) ), + FileSystem::fileNameFromPath( ( *it ) ), Actions::Modified ); } } DirsChanged.clear(); } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherFSEvents.hpp b/dep/efsw/src/efsw/WatcherFSEvents.hpp index d4fc5c9a8d3..a18c06d40b9 100644 --- a/dep/efsw/src/efsw/WatcherFSEvents.hpp +++ b/dep/efsw/src/efsw/WatcherFSEvents.hpp @@ -5,10 +5,10 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS -#include <efsw/WatcherGeneric.hpp> -#include <efsw/FileInfo.hpp> #include <CoreFoundation/CoreFoundation.h> #include <CoreServices/CoreServices.h> +#include <efsw/FileInfo.hpp> +#include <efsw/WatcherGeneric.hpp> #include <set> #include <vector> @@ -16,54 +16,46 @@ namespace efsw { class FileWatcherFSEvents; -class FSEvent -{ - public: - FSEvent( std::string path, long flags, Uint64 id ) : - Path( path ), - Flags( flags ), - Id ( id ) - { - } - - std::string Path; - long Flags; - Uint64 Id; +class FSEvent { + public: + FSEvent( std::string path, long flags, Uint64 id ) : Path( path ), Flags( flags ), Id( id ) {} + + std::string Path; + long Flags; + Uint64 Id; }; -class WatcherFSEvents : public Watcher -{ - public: - WatcherFSEvents(); - - WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent = NULL ); - - ~WatcherFSEvents(); +class WatcherFSEvents : public Watcher { + public: + WatcherFSEvents(); - void init(); + WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener, bool recursive, + WatcherFSEvents* parent = NULL ); - void initAsync(); + ~WatcherFSEvents(); - void handleActions( std::vector<FSEvent> & events ); + void init(); - void process(); + void handleActions( std::vector<FSEvent>& events ); - FileWatcherFSEvents * FWatcher; + void process(); - FSEventStreamRef FSStream; - protected: - void handleAddModDel( const Uint32 &flags, const std::string &path, std::string &dirPath, std::string &filePath ); + Atomic<FileWatcherFSEvents*> FWatcher; + FSEventStreamRef FSStream; - WatcherGeneric * WatcherGen; + protected: + void handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, + std::string& filePath ); - bool initializedAsync; + WatcherGeneric* WatcherGen; - std::set<std::string> DirsChanged; + std::set<std::string> DirsChanged; - void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" ); + void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, + Action action, std::string oldFilename = "" ); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherGeneric.cpp b/dep/efsw/src/efsw/WatcherGeneric.cpp index 94170d3ce87..a6bb10619be 100644 --- a/dep/efsw/src/efsw/WatcherGeneric.cpp +++ b/dep/efsw/src/efsw/WatcherGeneric.cpp @@ -1,15 +1,12 @@ -#include <efsw/WatcherGeneric.hpp> -#include <efsw/FileSystem.hpp> #include <efsw/DirWatcherGeneric.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/WatcherGeneric.hpp> -namespace efsw -{ +namespace efsw { -WatcherGeneric::WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive ) : - Watcher( id, directory, fwl, recursive ), - WatcherImpl( fw ), - DirWatch( NULL ) -{ +WatcherGeneric::WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener* fwl, + FileWatcherImpl* fw, bool recursive ) : + Watcher( id, directory, fwl, recursive ), WatcherImpl( fw ), DirWatch( NULL ) { FileSystem::dirAddSlashAtEnd( Directory ); DirWatch = new DirWatcherGeneric( NULL, this, directory, recursive, false ); @@ -17,24 +14,20 @@ WatcherGeneric::WatcherGeneric( WatchID id, const std::string& directory, FileWa DirWatch->addChilds( false ); } -WatcherGeneric::~WatcherGeneric() -{ +WatcherGeneric::~WatcherGeneric() { efSAFE_DELETE( DirWatch ); } -void WatcherGeneric::watch() -{ +void WatcherGeneric::watch() { DirWatch->watch(); } -void WatcherGeneric::watchDir( std::string dir ) -{ +void WatcherGeneric::watchDir( std::string dir ) { DirWatch->watchDir( dir ); } -bool WatcherGeneric::pathInWatches( std::string path ) -{ +bool WatcherGeneric::pathInWatches( std::string path ) { return DirWatch->pathInWatches( path ); } -} +} // namespace efsw diff --git a/dep/efsw/src/efsw/WatcherGeneric.hpp b/dep/efsw/src/efsw/WatcherGeneric.hpp index 8794e921b40..d11ec20efd5 100644 --- a/dep/efsw/src/efsw/WatcherGeneric.hpp +++ b/dep/efsw/src/efsw/WatcherGeneric.hpp @@ -3,28 +3,27 @@ #include <efsw/FileWatcherImpl.hpp> -namespace efsw -{ +namespace efsw { class DirWatcherGeneric; -class WatcherGeneric : public Watcher -{ - public: - FileWatcherImpl * WatcherImpl; - DirWatcherGeneric * DirWatch; +class WatcherGeneric : public Watcher { + public: + FileWatcherImpl* WatcherImpl; + DirWatcherGeneric* DirWatch; - WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive ); + WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener* fwl, + FileWatcherImpl* fw, bool recursive ); - ~WatcherGeneric(); + ~WatcherGeneric(); - void watch(); + void watch() override; - void watchDir( std::string dir ); + void watchDir( std::string dir ); - bool pathInWatches( std::string path ); + bool pathInWatches( std::string path ); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherInotify.cpp b/dep/efsw/src/efsw/WatcherInotify.cpp index 741641bf43c..812ddaee44c 100644 --- a/dep/efsw/src/efsw/WatcherInotify.cpp +++ b/dep/efsw/src/efsw/WatcherInotify.cpp @@ -2,27 +2,13 @@ namespace efsw { -WatcherInotify::WatcherInotify() : - Watcher(), - Parent( NULL ) -{ -} - -WatcherInotify::WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent ) : - Watcher( id, directory, listener, recursive ), - Parent( parent ), - DirInfo( directory ) -{ -} +WatcherInotify::WatcherInotify() : Watcher(), Parent( NULL ) {} -bool WatcherInotify::inParentTree( WatcherInotify * parent ) -{ - WatcherInotify * tNext = Parent; +bool WatcherInotify::inParentTree( WatcherInotify* parent ) { + WatcherInotify* tNext = Parent; - while ( NULL != tNext ) - { - if ( tNext == parent ) - { + while ( NULL != tNext ) { + if ( tNext == parent ) { return true; } @@ -31,5 +17,5 @@ bool WatcherInotify::inParentTree( WatcherInotify * parent ) return false; } - -} + +} // namespace efsw diff --git a/dep/efsw/src/efsw/WatcherInotify.hpp b/dep/efsw/src/efsw/WatcherInotify.hpp index 1caf399679b..d43935c5009 100644 --- a/dep/efsw/src/efsw/WatcherInotify.hpp +++ b/dep/efsw/src/efsw/WatcherInotify.hpp @@ -1,25 +1,23 @@ -#ifndef EFSW_WATCHERINOTIFY_HPP +#ifndef EFSW_WATCHERINOTIFY_HPP #define EFSW_WATCHERINOTIFY_HPP -#include <efsw/FileWatcherImpl.hpp> #include <efsw/FileInfo.hpp> +#include <efsw/FileWatcherImpl.hpp> namespace efsw { -class WatcherInotify : public Watcher -{ - public: - WatcherInotify(); - - WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent = NULL ); +class WatcherInotify : public Watcher { + public: + WatcherInotify(); - bool inParentTree( WatcherInotify * parent ); + bool inParentTree( WatcherInotify* parent ); - WatcherInotify * Parent; + WatcherInotify* Parent; + WatchID InotifyID; - FileInfo DirInfo; + FileInfo DirInfo; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherKqueue.cpp b/dep/efsw/src/efsw/WatcherKqueue.cpp index 8347fb53439..397264162e5 100644 --- a/dep/efsw/src/efsw/WatcherKqueue.cpp +++ b/dep/efsw/src/efsw/WatcherKqueue.cpp @@ -2,38 +2,36 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS -#include <sys/stat.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> #include <cstdio> #include <cstdlib> #include <cstring> +#include <dirent.h> #include <efsw/Debug.hpp> +#include <efsw/FileSystem.hpp> +#include <efsw/FileWatcherKqueue.hpp> #include <efsw/String.hpp> #include <efsw/System.hpp> -#include <efsw/FileSystem.hpp> #include <efsw/WatcherGeneric.hpp> -#include <efsw/FileWatcherKqueue.hpp> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> -#define KEVENT_RESERVE_VALUE (10) +#define KEVENT_RESERVE_VALUE ( 10 ) #ifndef O_EVTONLY -#define O_EVTONLY (O_RDONLY | O_NONBLOCK) +#define O_EVTONLY ( O_RDONLY | O_NONBLOCK ) #endif namespace efsw { -int comparator(const void* ke1, const void* ke2) -{ - const KEvent * kev1 = reinterpret_cast<const KEvent*>( ke1 ); - const KEvent * kev2 = reinterpret_cast<const KEvent*>( ke2 ); +int comparator( const void* ke1, const void* ke2 ) { + const KEvent* kev1 = reinterpret_cast<const KEvent*>( ke1 ); + const KEvent* kev2 = reinterpret_cast<const KEvent*>( ke2 ); - if ( NULL != kev2->udata ) - { - FileInfo * fi1 = reinterpret_cast<FileInfo*>( kev1->udata ); - FileInfo * fi2 = reinterpret_cast<FileInfo*>( kev2->udata ); + if ( NULL != kev2->udata ) { + FileInfo* fi1 = reinterpret_cast<FileInfo*>( kev1->udata ); + FileInfo* fi2 = reinterpret_cast<FileInfo*>( kev2->udata ); return strcmp( fi1->Filepath.c_str(), fi2->Filepath.c_str() ); } @@ -41,75 +39,68 @@ int comparator(const void* ke1, const void* ke2) return 1; } -WatcherKqueue::WatcherKqueue(WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent ) : +WatcherKqueue::WatcherKqueue( WatchID watchid, const std::string& dirname, + FileWatchListener* listener, bool recursive, + FileWatcherKqueue* watcher, WatcherKqueue* parent ) : Watcher( watchid, dirname, listener, recursive ), - mLastWatchID(0), + mLastWatchID( 0 ), mChangeListCount( 0 ), mKqueue( kqueue() ), mWatcher( watcher ), mParent( parent ), mInitOK( true ), - mErrno(0) -{ - if ( -1 == mKqueue ) - { - efDEBUG( "kqueue() returned invalid descriptor for directory %s. File descriptors count: %ld\n", Directory.c_str(), mWatcher->mFileDescriptorCount ); - + mErrno( 0 ) { + if ( -1 == mKqueue ) { + efDEBUG( + "kqueue() returned invalid descriptor for directory %s. File descriptors count: %ld\n", + Directory.c_str(), mWatcher->mFileDescriptorCount ); + mInitOK = false; mErrno = errno; - } - else - { + } else { mWatcher->addFD(); } } -WatcherKqueue::~WatcherKqueue() -{ +WatcherKqueue::~WatcherKqueue() { // Remove the childs watchers ( sub-folders watches ) removeAll(); - for ( size_t i = 0; i < mChangeListCount; i++ ) - { - if ( NULL != mChangeList[i].udata ) - { - FileInfo * fi = reinterpret_cast<FileInfo*>( mChangeList[i].udata ); + for ( size_t i = 0; i < mChangeListCount; i++ ) { + if ( NULL != mChangeList[i].udata ) { + FileInfo* fi = reinterpret_cast<FileInfo*>( mChangeList[i].udata ); efSAFE_DELETE( fi ); } } close( mKqueue ); - + mWatcher->removeFD(); } -void WatcherKqueue::addAll() -{ - if ( -1 == mKqueue ) - { +void WatcherKqueue::addAll() { + if ( -1 == mKqueue ) { return; } // scan directory and call addFile(name, false) on each file FileSystem::dirAddSlashAtEnd( Directory ); - efDEBUG( "addAll(): Added folder: %s\n", Directory.c_str()); + efDEBUG( "addAll(): Added folder: %s\n", Directory.c_str() ); // add base dir int fd = open( Directory.c_str(), O_EVTONLY ); - - if ( -1 == fd ) - { + + if ( -1 == fd ) { efDEBUG( "addAll(): Couldn't open folder: %s\n", Directory.c_str() ); - - if ( EACCES != errno ) - { + + if ( EACCES != errno ) { mInitOK = false; } mErrno = errno; - + return; } @@ -119,83 +110,66 @@ void WatcherKqueue::addAll() mChangeList.resize( KEVENT_RESERVE_VALUE ); // Creates the kevent for the folder - EV_SET( - &mChangeList[0], - fd, - EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, - 0, - 0 - ); + EV_SET( &mChangeList[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, 0, 0 ); mWatcher->addFD(); // Get the files and directories from the directory FileInfoMap files = FileSystem::filesInfoFromPath( Directory ); - for ( FileInfoMap::iterator it = files.begin(); it != files.end(); it++ ) - { + for ( FileInfoMap::iterator it = files.begin(); it != files.end(); it++ ) { FileInfo& fi = it->second; - if ( fi.isRegularFile() ) - { + if ( fi.isRegularFile() ) { // Add the regular files kevent - addFile( fi.Filepath , false ); - } - else if ( Recursive && fi.isDirectory() && fi.isReadable() ) - { + addFile( fi.Filepath, false ); + } else if ( Recursive && fi.isDirectory() && fi.isReadable() ) { // Create another watcher for the subfolders ( if recursive ) WatchID id = addWatch( fi.Filepath, Listener, Recursive, this ); // If the watcher is not adding the watcher means that the directory was created - if ( id > 0 && !mWatcher->isAddingWatcher() ) - { + if ( id > 0 && !mWatcher->isAddingWatcher() ) { handleFolderAction( fi.Filepath, Actions::Add ); } } } } -void WatcherKqueue::removeAll() -{ +void WatcherKqueue::removeAll() { efDEBUG( "removeAll(): Removing all child watchers\n" ); - std::list<WatchID> erase; + std::vector<WatchID> erase; - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) - { + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) { efDEBUG( "removeAll(): Removed child watcher %s\n", it->second->Directory.c_str() ); erase.push_back( it->second->ID ); } - for ( std::list<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ ) - { + for ( std::vector<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ ) { removeWatch( *eit ); } } -void WatcherKqueue::addFile(const std::string& name, bool emitEvents) -{ +void WatcherKqueue::addFile( const std::string& name, bool emitEvents ) { efDEBUG( "addFile(): Added: %s\n", name.c_str() ); // Open the file to get the file descriptor int fd = open( name.c_str(), O_EVTONLY ); - if( fd == -1 ) - { - efDEBUG( "addFile(): Could open file descriptor for %s. File descriptor count: %ld\n", name.c_str(), mWatcher->mFileDescriptorCount ); - + if ( fd == -1 ) { + efDEBUG( "addFile(): Could open file descriptor for %s. File descriptor count: %ld\n", + name.c_str(), mWatcher->mFileDescriptorCount ); + Errors::Log::createLastError( Errors::FileNotReadable, name ); - - if ( EACCES != errno ) - { + + if ( EACCES != errno ) { mInitOK = false; } mErrno = errno; - + return; } @@ -205,39 +179,31 @@ void WatcherKqueue::addFile(const std::string& name, bool emitEvents) mChangeListCount++; if ( mChangeListCount + KEVENT_RESERVE_VALUE > mChangeList.size() && - mChangeListCount % KEVENT_RESERVE_VALUE == 0 ) - { + mChangeListCount % KEVENT_RESERVE_VALUE == 0 ) { size_t reserve_size = mChangeList.size() + KEVENT_RESERVE_VALUE; mChangeList.resize( reserve_size ); - efDEBUG( "addFile(): Reserverd more KEvents space for %s, space reserved %ld, list actual size %ld.\n", Directory.c_str(), reserve_size, mChangeListCount ); + efDEBUG( "addFile(): Reserverd more KEvents space for %s, space reserved %ld, list actual " + "size %ld.\n", + Directory.c_str(), reserve_size, mChangeListCount ); } // create entry - FileInfo * entry = new FileInfo( name ); + FileInfo* entry = new FileInfo( name ); // set the event data at the end of the list - EV_SET( - &mChangeList[mChangeListCount], - fd, - EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, - 0, - (void*)entry - ); + EV_SET( &mChangeList[mChangeListCount], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME, 0, (void*)entry ); // qsort sort the list by name - qsort(&mChangeList[1], mChangeListCount, sizeof(KEvent), comparator); + qsort( &mChangeList[1], mChangeListCount, sizeof( KEvent ), comparator ); // handle action - if( emitEvents ) - { - handleAction(name, Actions::Add); + if ( emitEvents ) { + handleAction( name, Actions::Add ); } } -void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) -{ +void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) { efDEBUG( "removeFile(): Trying to remove file: %s\n", name.c_str() ); // bsearch @@ -249,11 +215,11 @@ void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) target.udata = &tempEntry; // Search the kevent - KEvent * ke = (KEvent*)bsearch(&target, &mChangeList[0], mChangeListCount + 1, sizeof(KEvent), comparator); + KEvent* ke = (KEvent*)bsearch( &target, &mChangeList[0], mChangeListCount + 1, sizeof( KEvent ), + comparator ); // Trying to remove a non-existing file? - if( !ke ) - { + if ( !ke ) { Errors::Log::createLastError( Errors::FileNotFound, name ); efDEBUG( "File not removed\n" ); return; @@ -262,13 +228,12 @@ void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) efDEBUG( "File removed\n" ); // handle action - if ( emitEvents ) - { + if ( emitEvents ) { handleAction( name, Actions::Delete ); } // Delete the user data ( FileInfo ) from the kevent closed - FileInfo * del = reinterpret_cast<FileInfo*>( ke->udata ); + FileInfo* del = reinterpret_cast<FileInfo*>( ke->udata ); efSAFE_DELETE( del ); @@ -277,121 +242,104 @@ void WatcherKqueue::removeFile( const std::string& name, bool emitEvents ) mWatcher->removeFD(); - memset(ke, 0, sizeof(KEvent)); + memset( ke, 0, sizeof( KEvent ) ); // move end to current - memcpy(ke, &mChangeList[mChangeListCount], sizeof(KEvent)); - memset(&mChangeList[mChangeListCount], 0, sizeof(KEvent)); + memcpy( ke, &mChangeList[mChangeListCount], sizeof( KEvent ) ); + memset( &mChangeList[mChangeListCount], 0, sizeof( KEvent ) ); --mChangeListCount; } -void WatcherKqueue::rescan() -{ +void WatcherKqueue::rescan() { efDEBUG( "rescan(): Rescanning: %s\n", Directory.c_str() ); DirectorySnapshotDiff Diff = mDirSnap.scan(); - if ( Diff.DirChanged ) - { + if ( Diff.DirChanged ) { sendDirChanged(); } - if ( Diff.changed() ) - { + if ( Diff.changed() ) { FileInfoList::iterator it; MovedList::iterator mit; /// Files - DiffIterator( FilesCreated ) - { - addFile( (*it).Filepath ); + DiffIterator( FilesCreated ) { + addFile( ( *it ).Filepath ); } - DiffIterator( FilesModified ) - { - handleAction( (*it).Filepath, Actions::Modified ); + DiffIterator( FilesModified ) { + handleAction( ( *it ).Filepath, Actions::Modified ); } - DiffIterator( FilesDeleted ) - { - removeFile( (*it).Filepath ); + DiffIterator( FilesDeleted ) { + removeFile( ( *it ).Filepath ); } - DiffMovedIterator( FilesMoved ) - { - handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first ); - removeFile( Directory + (*mit).first, false ); - addFile( (*mit).second.Filepath, false ); + DiffMovedIterator( FilesMoved ) { + handleAction( ( *mit ).second.Filepath, Actions::Moved, ( *mit ).first ); + removeFile( Directory + ( *mit ).first, false ); + addFile( ( *mit ).second.Filepath, false ); } /// Directories - DiffIterator( DirsCreated ) - { - handleFolderAction( (*it).Filepath, Actions::Add ); - addWatch( (*it).Filepath, Listener, Recursive, this ); + DiffIterator( DirsCreated ) { + handleFolderAction( ( *it ).Filepath, Actions::Add ); + addWatch( ( *it ).Filepath, Listener, Recursive, this ); } - DiffIterator( DirsModified ) - { - handleFolderAction( (*it).Filepath, Actions::Modified ); + DiffIterator( DirsModified ) { + handleFolderAction( ( *it ).Filepath, Actions::Modified ); } - DiffIterator( DirsDeleted ) - { - handleFolderAction( (*it).Filepath, Actions::Delete ); + DiffIterator( DirsDeleted ) { + handleFolderAction( ( *it ).Filepath, Actions::Delete ); - Watcher * watch = findWatcher( (*it).Filepath ); + Watcher* watch = findWatcher( ( *it ).Filepath ); - if ( NULL != watch ) - { + if ( NULL != watch ) { removeWatch( watch->ID ); - } } - DiffMovedIterator( DirsMoved ) - { - moveDirectory( Directory + (*mit).first, (*mit).second.Filepath ); + DiffMovedIterator( DirsMoved ) { + moveDirectory( Directory + ( *mit ).first, ( *mit ).second.Filepath ); } } } -WatchID WatcherKqueue::watchingDirectory( std::string dir ) -{ - Watcher * watch = findWatcher( dir ); +WatchID WatcherKqueue::watchingDirectory( std::string dir ) { + Watcher* watch = findWatcher( dir ); - if ( NULL != watch ) - { + if ( NULL != watch ) { return watch->ID; } return Errors::FileNotFound; } -void WatcherKqueue::handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename ) -{ - Listener->handleFileAction( ID, Directory, FileSystem::fileNameFromPath( filename ), action, FileSystem::fileNameFromPath( oldFilename ) ); +void WatcherKqueue::handleAction( const std::string& filename, efsw::Action action, + const std::string& oldFilename ) { + Listener->handleFileAction( ID, Directory, FileSystem::fileNameFromPath( filename ), action, + FileSystem::fileNameFromPath( oldFilename ) ); } -void WatcherKqueue::handleFolderAction( std::string filename, efsw::Action action , const std::string &oldFilename ) -{ +void WatcherKqueue::handleFolderAction( std::string filename, efsw::Action action, + const std::string& oldFilename ) { FileSystem::dirRemoveSlashAtEnd( filename ); handleAction( filename, action, oldFilename ); } -void WatcherKqueue::sendDirChanged() -{ - if ( NULL != mParent ) - { - Listener->handleFileAction( mParent->ID, mParent->Directory, FileSystem::fileNameFromPath( Directory ), Actions::Modified ); +void WatcherKqueue::sendDirChanged() { + if ( NULL != mParent ) { + Listener->handleFileAction( mParent->ID, mParent->Directory, + FileSystem::fileNameFromPath( Directory ), Actions::Modified ); } } -void WatcherKqueue::watch() -{ - if ( -1 == mKqueue ) - { +void WatcherKqueue::watch() { + if ( -1 == mKqueue ) { return; } @@ -399,89 +347,70 @@ void WatcherKqueue::watch() KEvent event; // First iterate the childs, to get the events from the deepest folder, to the watcher childs - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) - { + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { it->second->watch(); } bool needScan = false; // Then we get the the events of the current folder - while( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1, &mWatcher->mTimeOut ) ) != 0 ) - { + while ( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1, + &mWatcher->mTimeOut ) ) != 0 ) { // An error ocurred? - if( nev == -1 ) - { + if ( nev == -1 ) { efDEBUG( "watch(): Error on directory %s\n", Directory.c_str() ); - perror("kevent"); + perror( "kevent" ); break; - } - else - { - FileInfo * entry = NULL; + } else { + FileInfo* entry = NULL; // If udate == NULL means that it is the fisrt element of the change list, the folder. // otherwise it is an event of some file inside the folder - if( ( entry = reinterpret_cast<FileInfo*> ( event.udata ) ) != NULL ) - { + if ( ( entry = reinterpret_cast<FileInfo*>( event.udata ) ) != NULL ) { efDEBUG( "watch(): File: %s ", entry->Filepath.c_str() ); // If the event flag is delete... the file was deleted - if ( event.fflags & NOTE_DELETE ) - { + if ( event.fflags & NOTE_DELETE ) { efDEBUG( "deleted\n" ); mDirSnap.removeFile( entry->Filepath ); removeFile( entry->Filepath ); - } - else if ( event.fflags & NOTE_EXTEND || - event.fflags & NOTE_WRITE || - event.fflags & NOTE_ATTRIB - ) - { + } else if ( event.fflags & NOTE_EXTEND || event.fflags & NOTE_WRITE || + event.fflags & NOTE_ATTRIB ) { // The file was modified efDEBUG( "modified\n" ); FileInfo fi( entry->Filepath ); - if ( fi != *entry ) - { + if ( fi != *entry ) { *entry = fi; mDirSnap.updateFile( entry->Filepath ); handleAction( entry->Filepath, efsw::Actions::Modified ); } - } - else if ( event.fflags & NOTE_RENAME ) - { + } else if ( event.fflags & NOTE_RENAME ) { efDEBUG( "moved\n" ); needScan = true; } - } - else - { + } else { needScan = true; } } } - if ( needScan ) - { + if ( needScan ) { rescan(); } } -Watcher * WatcherKqueue::findWatcher( const std::string path ) -{ +Watcher* WatcherKqueue::findWatcher( const std::string path ) { WatchMap::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) - { - if ( it->second->Directory == path ) - { + for ( ; it != mWatches.end(); it++ ) { + if ( it->second->Directory == path ) { return it->second; } } @@ -489,28 +418,24 @@ Watcher * WatcherKqueue::findWatcher( const std::string path ) return NULL; } -void WatcherKqueue::moveDirectory( std::string oldPath, std::string newPath, bool emitEvents ) -{ +void WatcherKqueue::moveDirectory( std::string oldPath, std::string newPath, bool emitEvents ) { // Update the directory path if it's a watcher std::string opath2( oldPath ); FileSystem::dirAddSlashAtEnd( opath2 ); - Watcher * watch = findWatcher( opath2 ); + Watcher* watch = findWatcher( opath2 ); - if ( NULL != watch ) - { + if ( NULL != watch ) { watch->Directory = opath2; } - if ( emitEvents ) - { + if ( emitEvents ) { handleFolderAction( newPath, efsw::Actions::Moved, oldPath ); } } -WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive , WatcherKqueue *parent) -{ - static long s_fc = 0; +WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, + bool recursive, WatcherKqueue* parent ) { static bool s_ug = false; std::string dir( directory ); @@ -518,57 +443,42 @@ WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener FileSystem::dirAddSlashAtEnd( dir ); // This should never happen here - if( !FileSystem::isDirectory( dir ) ) - { + if ( !FileSystem::isDirectory( dir ) ) { return Errors::Log::createLastError( Errors::FileNotFound, dir ); - } - else if ( pathInWatches( dir ) || pathInParent( dir ) ) - { + } else if ( pathInWatches( dir ) || pathInParent( dir ) ) { return Errors::Log::createLastError( Errors::FileRepeated, directory ); - } - else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) - { + } else if ( NULL != parent && FileSystem::isRemoteFS( dir ) ) { return Errors::Log::createLastError( Errors::FileRemote, dir ); } std::string curPath; std::string link( FileSystem::getLinkRealPath( dir, curPath ) ); - if ( "" != link ) - { + if ( "" != link ) { /// Avoid adding symlinks directories if it's now enabled - if ( NULL != parent && !mWatcher->mFileWatcher->followSymlinks() ) - { + if ( NULL != parent && !mWatcher->mFileWatcher->followSymlinks() ) { return Errors::Log::createLastError( Errors::FileOutOfScope, dir ); } - if ( pathInWatches( link ) || pathInParent( link ) ) - { + if ( pathInWatches( link ) || pathInParent( link ) ) { return Errors::Log::createLastError( Errors::FileRepeated, link ); - } - else if ( !mWatcher->linkAllowed( curPath, link ) ) - { + } else if ( !mWatcher->linkAllowed( curPath, link ) ) { return Errors::Log::createLastError( Errors::FileOutOfScope, link ); - } - else - { + } else { dir = link; } } - if ( mWatcher->availablesFD() ) - { - WatcherKqueue* watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, mWatcher, parent ); + if ( mWatcher->availablesFD() ) { + WatcherKqueue* watch = + new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, mWatcher, parent ); - mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatches.insert( std::make_pair( mLastWatchID, watch ) ); watch->addAll(); - s_fc++; - // if failed to open the directory... erase the watcher - if ( !watch->initOK() ) - { + if ( !watch->initOK() ) { int le = watch->lastErrno(); mWatches.erase( watch->ID ); @@ -578,90 +488,78 @@ WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener mLastWatchID--; // Probably the folder has too many files, create a generic watcher - if ( EACCES != le ) - { - WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); + if ( EACCES != le ) { + WatcherGeneric* watch = + new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); - mWatches.insert(std::make_pair(mLastWatchID, watch)); - } - else - { + mWatches.insert( std::make_pair( mLastWatchID, watch ) ); + } else { return Errors::Log::createLastError( Errors::Unspecified, link ); } } - } - else - { - if ( !s_ug ) - { - efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld. Folders added: %ld\n", mWatcher->mFileDescriptorCount, s_fc ); + } else { + if ( !s_ug ) { + efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld.\n", + mWatcher->mFileDescriptorCount ); s_ug = true; } - WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); + WatcherGeneric* watch = + new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive ); - mWatches.insert(std::make_pair(mLastWatchID, watch)); + mWatches.insert( std::make_pair( mLastWatchID, watch ) ); } return mLastWatchID; } -bool WatcherKqueue::initOK() -{ +bool WatcherKqueue::initOK() { return mInitOK; } -void WatcherKqueue::removeWatch( WatchID watchid ) -{ - WatchMap::iterator iter = mWatches.find(watchid); +void WatcherKqueue::removeWatch( WatchID watchid ) { + WatchMap::iterator iter = mWatches.find( watchid ); - if(iter == mWatches.end()) + if ( iter == mWatches.end() ) return; - Watcher * watch = iter->second; + Watcher* watch = iter->second; - mWatches.erase(iter); + mWatches.erase( iter ); efSAFE_DELETE( watch ); } -bool WatcherKqueue::pathInWatches( const std::string& path ) -{ +bool WatcherKqueue::pathInWatches( const std::string& path ) { return NULL != findWatcher( path ); } -bool WatcherKqueue::pathInParent( const std::string &path ) -{ - WatcherKqueue * pNext = mParent; +bool WatcherKqueue::pathInParent( const std::string& path ) { + WatcherKqueue* pNext = mParent; - while ( NULL != pNext ) - { - if ( pNext->pathInWatches( path ) ) - { + while ( NULL != pNext ) { + if ( pNext->pathInWatches( path ) ) { return true; } pNext = pNext->mParent; } - if ( mWatcher->pathInWatches( path ) ) - { + if ( mWatcher->pathInWatches( path ) ) { return true; } - if ( path == Directory ) - { + if ( path == Directory ) { return true; } return false; } -int WatcherKqueue::lastErrno() -{ +int WatcherKqueue::lastErrno() { return mErrno; } -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherKqueue.hpp b/dep/efsw/src/efsw/WatcherKqueue.hpp index 4babbe73354..75c0f623dd7 100644 --- a/dep/efsw/src/efsw/WatcherKqueue.hpp +++ b/dep/efsw/src/efsw/WatcherKqueue.hpp @@ -5,14 +5,13 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS +#include <efsw/DirectorySnapshot.hpp> #include <map> -#include <vector> -#include <sys/types.h> #include <sys/event.h> -#include <efsw/DirectorySnapshot.hpp> +#include <sys/types.h> +#include <vector> -namespace efsw -{ +namespace efsw { class FileWatcherKqueue; class WatcherKqueue; @@ -22,72 +21,76 @@ typedef struct kevent KEvent; /// type for a map from WatchID to WatcherKqueue pointer typedef std::map<WatchID, Watcher*> WatchMap; -class WatcherKqueue : public Watcher -{ - public: - WatcherKqueue( WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent = NULL ); +class WatcherKqueue : public Watcher { + public: + WatcherKqueue( WatchID watchid, const std::string& dirname, FileWatchListener* listener, + bool recursive, FileWatcherKqueue* watcher, WatcherKqueue* parent = NULL ); + + virtual ~WatcherKqueue(); + + void addFile( const std::string& name, bool emitEvents = true ); + + void removeFile( const std::string& name, bool emitEvents = true ); + + // called when the directory is actually changed + // means a file has been added or removed + // rescans the watched directory adding/removing files and sending notices + void rescan(); - virtual ~WatcherKqueue(); + void handleAction( const std::string& filename, efsw::Action action, + const std::string& oldFilename = "" ); - void addFile( const std::string& name, bool emitEvents = true ); + void handleFolderAction( std::string filename, efsw::Action action, + const std::string& oldFilename = "" ); - void removeFile( const std::string& name, bool emitEvents = true ); + void addAll(); - // called when the directory is actually changed - // means a file has been added or removed - // rescans the watched directory adding/removing files and sending notices - void rescan(); + void removeAll(); - void handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename = "" ); + WatchID watchingDirectory( std::string dir ); - void handleFolderAction( std::string filename, efsw::Action action, const std::string& oldFilename = "" ); + void watch() override; - void addAll(); + WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, + WatcherKqueue* parent ); - void removeAll(); + void removeWatch( WatchID watchid ); - WatchID watchingDirectory( std::string dir ); + bool initOK(); - void watch(); + int lastErrno(); - WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherKqueue * parent); + protected: + WatchMap mWatches; + int mLastWatchID; - void removeWatch (WatchID watchid ); - - bool initOK(); + // index 0 is always the directory + std::vector<KEvent> mChangeList; + size_t mChangeListCount; + DirectorySnapshot mDirSnap; - int lastErrno(); - protected: - WatchMap mWatches; - int mLastWatchID; + /// The descriptor for the kqueue + int mKqueue; - // index 0 is always the directory - std::vector<KEvent> mChangeList; - size_t mChangeListCount; - DirectorySnapshot mDirSnap; + FileWatcherKqueue* mWatcher; - /// The descriptor for the kqueue - int mKqueue; + WatcherKqueue* mParent; - FileWatcherKqueue * mWatcher; + bool mInitOK; + int mErrno; - WatcherKqueue * mParent; - - bool mInitOK; - int mErrno; + bool pathInWatches( const std::string& path ); - bool pathInWatches( const std::string& path ); - - bool pathInParent( const std::string& path ); + bool pathInParent( const std::string& path ); - Watcher * findWatcher( const std::string path ); + Watcher* findWatcher( const std::string path ); - void moveDirectory( std::string oldPath, std::string newPath, bool emitEvents = true ); + void moveDirectory( std::string oldPath, std::string newPath, bool emitEvents = true ); - void sendDirChanged(); + void sendDirChanged(); }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/WatcherWin32.cpp b/dep/efsw/src/efsw/WatcherWin32.cpp index 4d2dc7e064f..ad206e35f71 100644 --- a/dep/efsw/src/efsw/WatcherWin32.cpp +++ b/dep/efsw/src/efsw/WatcherWin32.cpp @@ -1,144 +1,130 @@ -#include <efsw/WatcherWin32.hpp> +#include <efsw/Debug.hpp> #include <efsw/String.hpp> +#include <efsw/WatcherWin32.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 -namespace efsw -{ +#include <algorithm> + +namespace efsw { /// Unpacks events and passes them to a user defined callback. -void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) -{ - char szFile[MAX_PATH]; - PFILE_NOTIFY_INFORMATION pNotify; - WatcherStructWin32 * tWatch = (WatcherStructWin32*) lpOverlapped; - WatcherWin32 * pWatch = tWatch->Watch; - size_t offset = 0; +void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) { - if (dwNumberOfBytesTransfered == 0) - { - RefreshWatch(tWatch); // If dwNumberOfBytesTransfered == 0, it means the buffer overflowed (too many changes between GetOverlappedResults calls). Those events are lost, but at least we can refresh so subsequent changes are seen again. + if ( NULL == lpOverlapped ) { return; } - if (dwErrorCode == ERROR_SUCCESS) - { - do - { - bool skip = false; + PFILE_NOTIFY_INFORMATION pNotify; + WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped; + WatcherWin32* pWatch = tWatch->Watch; + size_t offset = 0; + + if ( dwNumberOfBytesTransfered == 0 ) { + if ( nullptr != pWatch && !pWatch->StopNow ) { + RefreshWatch( tWatch ); + } else { + return; + } + } - pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset]; - offset += pNotify->NextEntryOffset; + do { + bool skip = false; - int count = WideCharToMultiByte(CP_UTF8, 0, pNotify->FileName, - pNotify->FileNameLength / sizeof(WCHAR), - szFile, MAX_PATH - 1, NULL, NULL); - szFile[count] = TEXT('\0'); + pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset]; + offset += pNotify->NextEntryOffset; + int count = + WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, + pNotify->FileNameLength / sizeof( WCHAR ), NULL, 0, NULL, NULL ); + if ( count == 0 ) + continue; - std::string nfile( szFile ); + std::string nfile( count, '\0' ); - if ( FILE_ACTION_MODIFIED == pNotify->Action ) - { - FileInfo fifile( std::string( pWatch->DirName ) + nfile ); + count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, + pNotify->FileNameLength / sizeof( WCHAR ), &nfile[0], count, + NULL, NULL ); - if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && pWatch->LastModifiedEvent.file.Size == fifile.Size && pWatch->LastModifiedEvent.fileName == nfile ) - { - skip = true; - } + if ( FILE_ACTION_MODIFIED == pNotify->Action ) { + FileInfo fifile( std::string( pWatch->DirName ) + nfile ); - pWatch->LastModifiedEvent.fileName = nfile; - pWatch->LastModifiedEvent.file = fifile; + if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && + pWatch->LastModifiedEvent.file.Size == fifile.Size && + pWatch->LastModifiedEvent.fileName == nfile ) { + skip = true; } - if ( !skip ) - { - pWatch->Watch->handleAction(pWatch, nfile, pNotify->Action); - } - } while (pNotify->NextEntryOffset != 0); - } + pWatch->LastModifiedEvent.fileName = nfile; + pWatch->LastModifiedEvent.file = fifile; + } + + if ( !skip ) { + pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action ); + } + } while ( pNotify->NextEntryOffset != 0 ); - if (!pWatch->StopNow) - { - RefreshWatch(tWatch); + if ( !pWatch->StopNow ) { + RefreshWatch( tWatch ); } } /// Refreshes the directory monitoring. -bool RefreshWatch(WatcherStructWin32* pWatch) -{ - return ReadDirectoryChangesW( - pWatch->Watch->DirHandle, - pWatch->Watch->mBuffer, - sizeof(pWatch->Watch->mBuffer), - pWatch->Watch->Recursive, - pWatch->Watch->NotifyFilter, - NULL, - &pWatch->Overlapped, - NULL - ) != 0; +bool RefreshWatch( WatcherStructWin32* pWatch ) { + bool bRet = ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(), + pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive, + pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, NULL ) != 0; + + if ( !bRet ) { + std::string error = std::to_string( GetLastError() ); + Errors::Log::createLastError( Errors::WatcherFailed, error ); + } + + return bRet; } /// Stops monitoring a directory. -void DestroyWatch(WatcherStructWin32* pWatch) -{ - if (pWatch) - { - WatcherWin32 * tWatch = pWatch->Watch; - +void DestroyWatch( WatcherStructWin32* pWatch ) { + if ( pWatch ) { + WatcherWin32* tWatch = pWatch->Watch; tWatch->StopNow = true; - - CancelIoEx(tWatch->DirHandle, &pWatch->Overlapped); - - RefreshWatch(pWatch); - CloseHandle(pWatch->Overlapped.hEvent); - CloseHandle(pWatch->Watch->DirHandle); + CancelIoEx( pWatch->Watch->DirHandle, &pWatch->Overlapped ); + CloseHandle( pWatch->Watch->DirHandle ); efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); efSAFE_DELETE( pWatch->Watch ); - HeapFree(GetProcessHeap(), 0, pWatch); } } /// Starts monitoring a directory. -WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter) -{ - WatcherStructWin32 * tWatch; - size_t ptrsize = sizeof(*tWatch); - tWatch = static_cast<WatcherStructWin32*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize)); - - WatcherWin32 * pWatch = new WatcherWin32(); +WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, + DWORD bufferSize, DWORD notifyFilter, HANDLE iocp ) { + WatcherStructWin32* tWatch; + size_t ptrsize = sizeof( *tWatch ); + tWatch = static_cast<WatcherStructWin32*>( + HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize ) ); + + WatcherWin32* pWatch = new WatcherWin32(bufferSize); tWatch->Watch = pWatch; pWatch->DirHandle = CreateFileW( - szDirectory, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, - NULL - ); - - if (pWatch->DirHandle != INVALID_HANDLE_VALUE) - { - tWatch->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - pWatch->NotifyFilter = NotifyFilter; + szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); + + if ( pWatch->DirHandle != INVALID_HANDLE_VALUE && + CreateIoCompletionPort( pWatch->DirHandle, iocp, 0, 1 ) ) { + pWatch->NotifyFilter = notifyFilter; pWatch->Recursive = recursive; - if (RefreshWatch(tWatch)) - { + if ( RefreshWatch( tWatch ) ) { return tWatch; } - else - { - CloseHandle(tWatch->Overlapped.hEvent); - CloseHandle(pWatch->DirHandle); - } } - HeapFree(GetProcessHeap(), 0, tWatch); + CloseHandle( pWatch->DirHandle ); + efSAFE_DELETE( pWatch->Watch ); + HeapFree( GetProcessHeap(), 0, tWatch ); return NULL; } -} +} // namespace efsw - #endif +#endif diff --git a/dep/efsw/src/efsw/WatcherWin32.hpp b/dep/efsw/src/efsw/WatcherWin32.hpp index 3c6d988fbf4..ae050b730df 100644 --- a/dep/efsw/src/efsw/WatcherWin32.hpp +++ b/dep/efsw/src/efsw/WatcherWin32.hpp @@ -1,76 +1,73 @@ #ifndef EFSW_WATCHERWIN32_HPP #define EFSW_WATCHERWIN32_HPP -#include <efsw/FileWatcherImpl.hpp> #include <efsw/FileInfo.hpp> +#include <efsw/FileWatcherImpl.hpp> +#include <vector> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #include <windows.h> #ifdef EFSW_COMPILER_MSVC - #pragma comment(lib, "comctl32.lib") - #pragma comment(lib, "user32.lib") - #pragma comment(lib, "ole32.lib") +#pragma comment( lib, "comctl32.lib" ) +#pragma comment( lib, "user32.lib" ) +#pragma comment( lib, "ole32.lib" ) - // disable secure warnings - #pragma warning (disable: 4996) +// disable secure warnings +#pragma warning( disable : 4996 ) #endif -namespace efsw -{ +namespace efsw { class WatcherWin32; /// Internal watch data -struct WatcherStructWin32 -{ +struct WatcherStructWin32 { OVERLAPPED Overlapped; - WatcherWin32 * Watch; + WatcherWin32* Watch; }; -class cLastModifiedEvent -{ - public: - cLastModifiedEvent() {} - FileInfo file; - std::string fileName; +struct sLastModifiedEvent { + FileInfo file; + std::string fileName; }; -bool RefreshWatch(WatcherStructWin32* pWatch); +bool RefreshWatch( WatcherStructWin32* pWatch ); -void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped); +void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ); -void DestroyWatch(WatcherStructWin32* pWatch); +void DestroyWatch( WatcherStructWin32* pWatch ); -WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter); +WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, + DWORD bufferSize, DWORD notifyFilter, HANDLE iocp ); -class WatcherWin32 : public Watcher -{ - public: - WatcherWin32() : - Struct( NULL ), - DirHandle( NULL ), - lParam( 0 ), - NotifyFilter( 0 ), - StopNow( false ), - Watch( NULL ), - DirName( NULL ) - { +class WatcherWin32 : public Watcher { + public: + WatcherWin32(DWORD dwBufferSize) : + Struct( NULL ), + DirHandle( NULL ), + Buffer(), + lParam( 0 ), + NotifyFilter( 0 ), + StopNow( false ), + Watch( NULL ), + DirName( NULL ) { + Buffer.resize(dwBufferSize); } - WatcherStructWin32 * Struct; - HANDLE DirHandle; - BYTE mBuffer[63 * 1024]; // do NOT make this bigger than 64K because it will fail if the folder being watched is on the network! (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) - LPARAM lParam; - DWORD NotifyFilter; - bool StopNow; - FileWatcherImpl* Watch; - char* DirName; - cLastModifiedEvent LastModifiedEvent; + WatcherStructWin32* Struct; + HANDLE DirHandle; + std::vector<BYTE> Buffer; + LPARAM lParam; + DWORD NotifyFilter; + bool StopNow; + FileWatcherImpl* Watch; + char* DirName; + sLastModifiedEvent LastModifiedEvent; }; -} +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/base.hpp b/dep/efsw/src/efsw/base.hpp index b5a9687dc74..43abc4fd5e8 100644 --- a/dep/efsw/src/efsw/base.hpp +++ b/dep/efsw/src/efsw/base.hpp @@ -1,115 +1,129 @@ #ifndef EFSW_BASE #define EFSW_BASE -#include <efsw/sophist.h> #include <efsw/efsw.hpp> +#include <efsw/sophist.h> namespace efsw { -typedef SOPHIST_int8 Int8; -typedef SOPHIST_uint8 Uint8; -typedef SOPHIST_int16 Int16; -typedef SOPHIST_uint16 Uint16; -typedef SOPHIST_int32 Int32; -typedef SOPHIST_uint32 Uint32; -typedef SOPHIST_int64 Int64; -typedef SOPHIST_uint64 Uint64; - -#define EFSW_OS_WIN 1 -#define EFSW_OS_LINUX 2 -#define EFSW_OS_MACOSX 3 -#define EFSW_OS_BSD 4 -#define EFSW_OS_SOLARIS 5 -#define EFSW_OS_HAIKU 6 -#define EFSW_OS_ANDROID 7 -#define EFSW_OS_IOS 8 - -#define EFSW_PLATFORM_WIN32 1 -#define EFSW_PLATFORM_INOTIFY 2 -#define EFSW_PLATFORM_KQUEUE 3 -#define EFSW_PLATFORM_FSEVENTS 4 -#define EFSW_PLATFORM_GENERIC 5 - -#if defined(_WIN32) - /// Any Windows platform - #define EFSW_OS EFSW_OS_WIN - #define EFSW_PLATFORM EFSW_PLATFORM_WIN32 - - #if ( defined( _MSCVER ) || defined( _MSC_VER ) ) - #define EFSW_COMPILER_MSVC - #endif - - /// Force windows target version above or equal to Windows Server 2008 or Windows Vista - #if _WIN32_WINNT < 0x600 - #undef _WIN32_WINNT - #define _WIN32_WINNT 0x600 - #endif -#elif defined( __FreeBSD__ ) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined( __DragonFly__ ) - #define EFSW_OS EFSW_OS_BSD - #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE - -#elif defined( __APPLE_CC__ ) || defined ( __APPLE__ ) - #include <TargetConditionals.h> - - #if defined( __IPHONE__ ) || ( defined( TARGET_OS_IPHONE ) && TARGET_OS_IPHONE ) || ( defined( TARGET_IPHONE_SIMULATOR ) && TARGET_IPHONE_SIMULATOR ) - #define EFSW_OS EFSW_OS_IOS - #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE - #else - #define EFSW_OS EFSW_OS_MACOSX - - #if defined(EFSW_FSEVENTS_NOT_SUPPORTED) - #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE - #else - #define EFSW_PLATFORM EFSW_PLATFORM_FSEVENTS - #endif - #endif - -#elif defined(__linux__) - /// This includes Linux and Android - #ifndef EFSW_KQUEUE - #define EFSW_PLATFORM EFSW_PLATFORM_INOTIFY - #else - /// This is for testing libkqueue, sadly it doesnt work - #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE - #endif - - #if defined( __ANDROID__ ) || defined( ANDROID ) - #define EFSW_OS EFSW_OS_ANDROID - #else - #define EFSW_OS EFSW_OS_LINUX - #endif +typedef SOPHIST_int8 Int8; +typedef SOPHIST_uint8 Uint8; +typedef SOPHIST_int16 Int16; +typedef SOPHIST_uint16 Uint16; +typedef SOPHIST_int32 Int32; +typedef SOPHIST_uint32 Uint32; +typedef SOPHIST_int64 Int64; +typedef SOPHIST_uint64 Uint64; + +#define EFSW_OS_WIN 1 +#define EFSW_OS_LINUX 2 +#define EFSW_OS_MACOSX 3 +#define EFSW_OS_BSD 4 +#define EFSW_OS_SOLARIS 5 +#define EFSW_OS_HAIKU 6 +#define EFSW_OS_ANDROID 7 +#define EFSW_OS_IOS 8 + +#define EFSW_PLATFORM_WIN32 1 +#define EFSW_PLATFORM_INOTIFY 2 +#define EFSW_PLATFORM_KQUEUE 3 +#define EFSW_PLATFORM_FSEVENTS 4 +#define EFSW_PLATFORM_GENERIC 5 + +#if defined( _WIN32 ) +/// Any Windows platform +#define EFSW_OS EFSW_OS_WIN +#define EFSW_PLATFORM EFSW_PLATFORM_WIN32 + +#if ( defined( _MSCVER ) || defined( _MSC_VER ) ) +#define EFSW_COMPILER_MSVC +#endif + +/// Force windows target version above or equal to Windows Server 2008 or Windows Vista +#if _WIN32_WINNT < 0x600 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x600 +#endif +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) || \ + defined( __DragonFly__ ) +#define EFSW_OS EFSW_OS_BSD +#define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE + +#elif defined( __APPLE_CC__ ) || defined( __APPLE__ ) +#include <TargetConditionals.h> + +#if defined( __IPHONE__ ) || ( defined( TARGET_OS_IPHONE ) && TARGET_OS_IPHONE ) || \ + ( defined( TARGET_IPHONE_SIMULATOR ) && TARGET_IPHONE_SIMULATOR ) +#define EFSW_OS EFSW_OS_IOS +#define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE +#else +#define EFSW_OS EFSW_OS_MACOSX + +#if defined( EFSW_FSEVENTS_NOT_SUPPORTED ) +#define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE +#else +#define EFSW_PLATFORM EFSW_PLATFORM_FSEVENTS +#endif +#endif +#elif defined( __linux__ ) +/// This includes Linux and Android +#ifndef EFSW_KQUEUE +#define EFSW_PLATFORM EFSW_PLATFORM_INOTIFY #else - #if defined( __SVR4 ) - #define EFSW_OS EFSW_OS_SOLARIS - #elif defined( __HAIKU__ ) || defined( __BEOS__ ) - #define EFSW_OS EFSW_OS_HAIKU - #endif - - /// Everything else - #define EFSW_PLATFORM EFSW_PLATFORM_GENERIC +/// This is for testing libkqueue, sadly it doesnt work +#define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE +#endif + +#if defined( __ANDROID__ ) || defined( ANDROID ) +#define EFSW_OS EFSW_OS_ANDROID +#else +#define EFSW_OS EFSW_OS_LINUX +#endif + +#else +#if defined( __SVR4 ) +#define EFSW_OS EFSW_OS_SOLARIS +#elif defined( __HAIKU__ ) || defined( __BEOS__ ) +#define EFSW_OS EFSW_OS_HAIKU +#endif + +/// Everything else +#define EFSW_PLATFORM EFSW_PLATFORM_GENERIC #endif #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 - #define EFSW_PLATFORM_POSIX +#define EFSW_PLATFORM_POSIX #endif #if 1 == SOPHIST_pointer64 - #define EFSW_64BIT +#define EFSW_64BIT #else - #define EFSW_32BIT +#define EFSW_32BIT #endif -#if defined(arm) || defined(__arm__) - #define EFSW_ARM +#if defined( arm ) || defined( __arm__ ) +#define EFSW_ARM #endif #define efCOMMA , -#define efSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } -#define efSAFE_DELETE_ARRAY(p) { if(p) { delete [] (p); (p)=NULL; } } -#define efARRAY_SIZE(__array) ( sizeof(__array) / sizeof(__array[0]) ) - -} +#define efSAFE_DELETE( p ) \ + { \ + if ( p ) { \ + delete ( p ); \ + ( p ) = NULL; \ + } \ + } +#define efSAFE_DELETE_ARRAY( p ) \ + { \ + if ( p ) { \ + delete[] ( p ); \ + ( p ) = NULL; \ + } \ + } +#define efARRAY_SIZE( __array ) ( sizeof( __array ) / sizeof( __array[0] ) ) + +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/platform/platformimpl.hpp b/dep/efsw/src/efsw/platform/platformimpl.hpp index 86a74eee0c8..54425806985 100644 --- a/dep/efsw/src/efsw/platform/platformimpl.hpp +++ b/dep/efsw/src/efsw/platform/platformimpl.hpp @@ -4,17 +4,17 @@ #include <efsw/base.hpp> #if defined( EFSW_PLATFORM_POSIX ) - #include <efsw/platform/posix/ThreadImpl.hpp> - #include <efsw/platform/posix/MutexImpl.hpp> - #include <efsw/platform/posix/SystemImpl.hpp> - #include <efsw/platform/posix/FileSystemImpl.hpp> +#include <efsw/platform/posix/ThreadImpl.hpp> +#include <efsw/platform/posix/MutexImpl.hpp> +#include <efsw/platform/posix/SystemImpl.hpp> +#include <efsw/platform/posix/FileSystemImpl.hpp> #elif EFSW_PLATFORM == EFSW_PLATFORM_WIN32 - #include <efsw/platform/win/ThreadImpl.hpp> - #include <efsw/platform/win/MutexImpl.hpp> - #include <efsw/platform/win/SystemImpl.hpp> - #include <efsw/platform/win/FileSystemImpl.hpp> +#include <efsw/platform/win/ThreadImpl.hpp> +#include <efsw/platform/win/MutexImpl.hpp> +#include <efsw/platform/win/SystemImpl.hpp> +#include <efsw/platform/win/FileSystemImpl.hpp> #else - #error Thread, Mutex, and System not implemented for this platform. +#error Thread, Mutex, and System not implemented for this platform. #endif #endif diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp index 5795d567740..92eeb4768ea 100644 --- a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp @@ -2,11 +2,11 @@ #if defined( EFSW_PLATFORM_POSIX ) +#include <cstring> +#include <dirent.h> #include <efsw/FileInfo.hpp> #include <efsw/FileSystem.hpp> -#include <dirent.h> #include <unistd.h> -#include <cstring> #ifndef _DARWIN_FEATURE_64_BIT_INODE #define _DARWIN_FEATURE_64_BIT_INODE @@ -16,15 +16,15 @@ #define _FILE_OFFSET_BITS 64 #endif -#include <sys/stat.h> -#include <cstdlib> #include <climits> +#include <cstdlib> +#include <sys/stat.h> #if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID #include <sys/vfs.h> #elif EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_IOS -#include <sys/param.h> #include <sys/mount.h> +#include <sys/param.h> #endif /** Remote file systems codes */ @@ -52,43 +52,15 @@ #define S_MAGIC_VXFS 0xA501FCF5 #if EFSW_OS == EFSW_OS_LINUX -#include <mntent.h> #include <cstdio> +#include <mntent.h> #endif namespace efsw { namespace Platform { #if EFSW_OS == EFSW_OS_LINUX -#pragma pack(push, 1) -struct ntfs_super_block -{ - char jump[3]; - char oem_id[8]; -}; -#pragma pack(pop) - -bool isNTFS( std::string device ) -{ - FILE * fd = fopen( device.c_str(), "r" ); - - ntfs_super_block ns; - - if ( fd != NULL ) - { - fread( &ns, 1, sizeof(ntfs_super_block), fd ); - fclose( fd ); - - std::string oemId( ns.oem_id ); - - return oemId.compare(0, 4, "NTFS") == 0; - } - - return false; -} - -std::string findMountPoint( std::string file ) -{ +std::string findMountPoint( std::string file ) { std::string cwd = FileSystem::getCurrentWorkingDirectory(); struct stat last_stat; struct stat file_stat; @@ -108,22 +80,20 @@ std::string findMountPoint( std::string file ) if ( !FileSystem::changeWorkingDirectory( dir ) ) return ""; - if (stat (".", &last_stat) < 0) + if ( stat( ".", &last_stat ) < 0 ) return ""; } - while (true) - { + while ( true ) { struct stat st; - if ( stat("..", &st) < 0 ) + if ( stat( "..", &st ) < 0 ) goto done; if ( st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino ) break; - if ( !FileSystem::changeWorkingDirectory("..") ) - { + if ( !FileSystem::changeWorkingDirectory( ".." ) ) { goto done; } @@ -139,46 +109,41 @@ done: return mp; } -std::string findDevicePath( const std::string& directory ) -{ - struct mntent *ent; - FILE *aFile; +std::string findDevicePath( const std::string& directory ) { + struct mntent* ent; + FILE* aFile; - aFile = setmntent("/proc/mounts", "r"); + aFile = setmntent( "/proc/mounts", "r" ); if ( aFile == NULL ) return ""; - while ( NULL != ( ent = getmntent( aFile ) ) ) - { + while ( NULL != ( ent = getmntent( aFile ) ) ) { std::string dirName( ent->mnt_dir ); - if ( dirName == directory ) - { + if ( dirName == directory ) { std::string fsName( ent->mnt_fsname ); - endmntent(aFile); + endmntent( aFile ); return fsName; } } - endmntent(aFile); + endmntent( aFile ); return ""; } -bool isLocalFUSEDirectory( std::string directory ) -{ +bool isLocalFUSEDirectory( std::string directory ) { efsw::FileSystem::dirRemoveSlashAtEnd( directory ); directory = findMountPoint( directory ); - if ( !directory.empty() ) - { + if ( !directory.empty() ) { std::string devicePath = findDevicePath( directory ); - return ( !devicePath.empty() && isNTFS( devicePath ) ); + return !devicePath.empty(); } return false; @@ -186,102 +151,93 @@ bool isLocalFUSEDirectory( std::string directory ) #endif -bool FileSystem::changeWorkingDirectory( const std::string & path ) -{ +bool FileSystem::changeWorkingDirectory( const std::string& path ) { return -1 != chdir( path.c_str() ); } std::string FileSystem::getCurrentWorkingDirectory() { char dir[PATH_MAX + 1]; - getcwd( dir, PATH_MAX + 1 ); - return std::string( dir ); + char* result = getcwd( dir, PATH_MAX + 1 ); + return result != NULL ? std::string( result ) : std::string(); } -FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) -{ +FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) { FileInfoMap files; - DIR *dp; - struct dirent *dirp; + DIR* dp; + struct dirent* dirp; - if( ( dp = opendir( path.c_str() ) ) == NULL) + if ( ( dp = opendir( path.c_str() ) ) == NULL ) return files; - while ( ( dirp = readdir(dp) ) != NULL) - { - if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) - { + while ( ( dirp = readdir( dp ) ) != NULL ) { + if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) { std::string name( dirp->d_name ); std::string fpath( path + name ); - files[ name ] = FileInfo( fpath ); + files[name] = FileInfo( fpath ); } } - closedir(dp); + closedir( dp ); return files; } -char FileSystem::getOSSlash() -{ +char FileSystem::getOSSlash() { return '/'; } -bool FileSystem::isDirectory( const std::string& path ) -{ +bool FileSystem::isDirectory( const std::string& path ) { struct stat st; int res = stat( path.c_str(), &st ); - if ( 0 == res ) - { - return static_cast<bool>( S_ISDIR(st.st_mode) ); + if ( 0 == res ) { + return static_cast<bool>( S_ISDIR( st.st_mode ) ); } return false; } -bool FileSystem::isRemoteFS( const std::string& directory ) -{ -#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS +bool FileSystem::isRemoteFS( const std::string& directory ) { +#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || \ + EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS struct statfs statfsbuf; statfs( directory.c_str(), &statfsbuf ); - switch ( statfsbuf.f_type | 0UL ) - { + switch ( statfsbuf.f_type | 0UL ) { case S_MAGIC_FUSEBLK: /* 0x65735546 remote */ { - #if EFSW_OS == EFSW_OS_LINUX +#if EFSW_OS == EFSW_OS_LINUX return !isLocalFUSEDirectory( directory ); - #endif +#endif } - case S_MAGIC_AFS: /* 0x5346414F remote */ - case S_MAGIC_AUFS: /* 0x61756673 remote */ - case S_MAGIC_CEPH: /* 0x00C36400 remote */ - case S_MAGIC_CIFS: /* 0xFF534D42 remote */ - case S_MAGIC_CODA: /* 0x73757245 remote */ - case S_MAGIC_FHGFS: /* 0x19830326 remote */ + case S_MAGIC_AFS: /* 0x5346414F remote */ + case S_MAGIC_AUFS: /* 0x61756673 remote */ + case S_MAGIC_CEPH: /* 0x00C36400 remote */ + case S_MAGIC_CIFS: /* 0xFF534D42 remote */ + case S_MAGIC_CODA: /* 0x73757245 remote */ + case S_MAGIC_FHGFS: /* 0x19830326 remote */ case S_MAGIC_FUSECTL: /* 0x65735543 remote */ - case S_MAGIC_GFS: /* 0x01161970 remote */ - case S_MAGIC_GPFS: /* 0x47504653 remote */ - case S_MAGIC_KAFS: /* 0x6B414653 remote */ - case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */ - case S_MAGIC_NCP: /* 0x564C remote */ - case S_MAGIC_NFS: /* 0x6969 remote */ - case S_MAGIC_NFSD: /* 0x6E667364 remote */ - case S_MAGIC_OCFS2: /* 0x7461636F remote */ - case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */ - case S_MAGIC_PIPEFS: /* 0x50495045 remote */ - case S_MAGIC_SMB: /* 0x517B remote */ - case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */ - case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */ - case S_MAGIC_VXFS: /* 0xA501FCF5 remote */ + case S_MAGIC_GFS: /* 0x01161970 remote */ + case S_MAGIC_GPFS: /* 0x47504653 remote */ + case S_MAGIC_KAFS: /* 0x6B414653 remote */ + case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */ + case S_MAGIC_NCP: /* 0x564C remote */ + case S_MAGIC_NFS: /* 0x6969 remote */ + case S_MAGIC_NFSD: /* 0x6E667364 remote */ + case S_MAGIC_OCFS2: /* 0x7461636F remote */ + case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */ + case S_MAGIC_PIPEFS: /* 0x50495045 remote */ + case S_MAGIC_SMB: /* 0x517B remote */ + case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */ + case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */ + case S_MAGIC_VXFS: /* 0xA501FCF5 remote */ { return true; } - default: - { + default: { return false; } } @@ -290,6 +246,6 @@ bool FileSystem::isRemoteFS( const std::string& directory ) return false; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp index 7353d81cf3f..0bfba7656f5 100644 --- a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp @@ -1,30 +1,29 @@ #ifndef EFSW_FILESYSTEMIMPLPOSIX_HPP #define EFSW_FILESYSTEMIMPLPOSIX_HPP -#include <efsw/base.hpp> #include <efsw/FileInfo.hpp> +#include <efsw/base.hpp> #if defined( EFSW_PLATFORM_POSIX ) namespace efsw { namespace Platform { -class FileSystem -{ - public: - static FileInfoMap filesInfoFromPath( const std::string& path ); +class FileSystem { + public: + static FileInfoMap filesInfoFromPath( const std::string& path ); - static char getOSSlash(); + static char getOSSlash(); - static bool isDirectory( const std::string& path ); + static bool isDirectory( const std::string& path ); - static bool isRemoteFS( const std::string& directory ); + static bool isRemoteFS( const std::string& directory ); - static bool changeWorkingDirectory( const std::string & path ); + static bool changeWorkingDirectory( const std::string& path ); - static std::string getCurrentWorkingDirectory(); + static std::string getCurrentWorkingDirectory(); }; -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp index 6f2af5abc61..2233798284c 100644 --- a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp +++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp @@ -4,29 +4,25 @@ namespace efsw { namespace Platform { -MutexImpl::MutexImpl() -{ +MutexImpl::MutexImpl() { pthread_mutexattr_t attributes; - pthread_mutexattr_init(&attributes); - pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&mMutex, &attributes); + pthread_mutexattr_init( &attributes ); + pthread_mutexattr_settype( &attributes, PTHREAD_MUTEX_RECURSIVE ); + pthread_mutex_init( &mMutex, &attributes ); } -MutexImpl::~MutexImpl() -{ - pthread_mutex_destroy(&mMutex); +MutexImpl::~MutexImpl() { + pthread_mutex_destroy( &mMutex ); } -void MutexImpl::lock() -{ - pthread_mutex_lock(&mMutex); +void MutexImpl::lock() { + pthread_mutex_lock( &mMutex ); } -void MutexImpl::unlock() -{ - pthread_mutex_unlock(&mMutex); +void MutexImpl::unlock() { + pthread_mutex_unlock( &mMutex ); } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp index d51eecb16aa..a33d827966f 100644 --- a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp +++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp @@ -9,23 +9,22 @@ namespace efsw { namespace Platform { -class MutexImpl -{ - public: - MutexImpl(); +class MutexImpl { + public: + MutexImpl(); - ~MutexImpl(); + ~MutexImpl(); - void lock(); + void lock(); - void unlock(); - private: - pthread_mutex_t mMutex; + void unlock(); + + private: + pthread_mutex_t mMutex; }; -}} +}} // namespace efsw::Platform #endif #endif - diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp index 22e37095afd..37d4120ef1e 100644 --- a/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp @@ -3,32 +3,31 @@ #if defined( EFSW_PLATFORM_POSIX ) #include <cstdio> -#include <pthread.h> -#include <sys/time.h> #include <limits.h> +#include <pthread.h> #include <sys/resource.h> +#include <sys/time.h> -#include <efsw/FileSystem.hpp> #include <efsw/Debug.hpp> +#include <efsw/FileSystem.hpp> #if EFSW_OS == EFSW_OS_MACOSX - #include <CoreFoundation/CoreFoundation.h> +#include <CoreFoundation/CoreFoundation.h> #elif EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_ANDROID - #include <libgen.h> - #include <unistd.h> +#include <libgen.h> +#include <unistd.h> #elif EFSW_OS == EFSW_OS_HAIKU - #include <kernel/OS.h> - #include <kernel/image.h> +#include <kernel/OS.h> +#include <kernel/image.h> #elif EFSW_OS == EFSW_OS_SOLARIS - #include <stdlib.h> +#include <stdlib.h> #elif EFSW_OS == EFSW_OS_BSD - #include <sys/sysctl.h> +#include <sys/sysctl.h> #endif namespace efsw { namespace Platform { -void System::sleep( const unsigned long& ms ) -{ +void System::sleep( const unsigned long& ms ) { // usleep( static_cast<unsigned long>( ms * 1000 ) ); // usleep is not reliable enough (it might block the @@ -42,47 +41,44 @@ void System::sleep( const unsigned long& ms ) // get the current time timeval tv; - gettimeofday(&tv, NULL); + gettimeofday( &tv, NULL ); // construct the time limit (current time + time to wait) timespec ti; - ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000; - ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000); + ti.tv_nsec = ( tv.tv_usec + ( usecs % 1000000 ) ) * 1000; + ti.tv_sec = tv.tv_sec + ( usecs / 1000000 ) + ( ti.tv_nsec / 1000000000 ); ti.tv_nsec %= 1000000000; // create a mutex and thread condition pthread_mutex_t mutex; - pthread_mutex_init(&mutex, 0); + pthread_mutex_init( &mutex, 0 ); pthread_cond_t condition; - pthread_cond_init(&condition, 0); + pthread_cond_init( &condition, 0 ); // wait... - pthread_mutex_lock(&mutex); - pthread_cond_timedwait(&condition, &mutex, &ti); - pthread_mutex_unlock(&mutex); + pthread_mutex_lock( &mutex ); + pthread_cond_timedwait( &condition, &mutex, &ti ); + pthread_mutex_unlock( &mutex ); // destroy the mutex and condition - pthread_cond_destroy(&condition); + pthread_cond_destroy( &condition ); } -std::string System::getProcessPath() -{ +std::string System::getProcessPath() { #if EFSW_OS == EFSW_OS_MACOSX char exe_file[FILENAME_MAX + 1]; CFBundleRef mainBundle = CFBundleGetMainBundle(); - if (mainBundle) - { - CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle); + if ( mainBundle ) { + CFURLRef mainURL = CFBundleCopyBundleURL( mainBundle ); - if (mainURL) - { - int ok = CFURLGetFileSystemRepresentation ( mainURL, (Boolean) true, (UInt8*)exe_file, FILENAME_MAX ); + if ( mainURL ) { + int ok = CFURLGetFileSystemRepresentation( mainURL, ( Boolean ) true, (UInt8*)exe_file, + FILENAME_MAX ); - if (ok) - { - return std::string(exe_file) + "/"; + if ( ok ) { + return std::string( exe_file ) + "/"; } } } @@ -93,14 +89,11 @@ std::string System::getProcessPath() int size; - size = readlink("/proc/self/exe", exe_file, FILENAME_MAX); + size = readlink( "/proc/self/exe", exe_file, FILENAME_MAX ); - if (size < 0) - { - return std::string( "./" ); - } - else - { + if ( size < 0 ) { + return std::string( "./" ); + } else { exe_file[size] = '\0'; return std::string( dirname( exe_file ) ) + "/"; } @@ -112,8 +105,8 @@ std::string System::getProcessPath() mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; char buf[1024]; - size_t cb = sizeof(buf); - sysctl(mib, 4, buf, &cb, NULL, 0); + size_t cb = sizeof( buf ); + sysctl( mib, 4, buf, &cb, NULL, 0 ); return FileSystem::pathRemoveFileName( std::string( buf ) ); @@ -124,8 +117,7 @@ std::string System::getProcessPath() image_info info; int32 cookie = 0; - while ( B_OK == get_next_image_info( 0, &cookie, &info ) ) - { + while ( B_OK == get_next_image_info( 0, &cookie, &info ) ) { if ( info.type == B_APP_IMAGE ) break; } @@ -136,18 +128,16 @@ std::string System::getProcessPath() return "/sdcard/"; #else - #warning getProcessPath() not implemented on this platform. ( will return "./" ) +#warning getProcessPath() not implemented on this platform. ( will return "./" ) return "./"; #endif } -void System::maxFD() -{ +void System::maxFD() { static bool maxed = false; - if ( !maxed ) - { + if ( !maxed ) { struct rlimit limit; getrlimit( RLIMIT_NOFILE, &limit ); limit.rlim_cur = limit.rlim_max; @@ -161,12 +151,10 @@ void System::maxFD() } } -Uint64 System::getMaxFD() -{ +Uint64 System::getMaxFD() { static rlim_t max_fd = 0; - if ( max_fd == 0 ) - { + if ( max_fd == 0 ) { struct rlimit limit; getrlimit( RLIMIT_NOFILE, &limit ); max_fd = limit.rlim_cur; @@ -175,6 +163,6 @@ Uint64 System::getMaxFD() return max_fd; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp index 34734104467..9322b06c800 100644 --- a/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp @@ -7,19 +7,18 @@ namespace efsw { namespace Platform { -class System -{ - public: - static void sleep( const unsigned long& ms ); +class System { + public: + static void sleep( const unsigned long& ms ); - static std::string getProcessPath(); + static std::string getProcessPath(); - static void maxFD(); + static void maxFD(); - static Uint64 getMaxFD(); + static Uint64 getMaxFD(); }; -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp index 2d3671db9b8..0f96bca7e55 100644 --- a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp +++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp @@ -1,61 +1,55 @@ -#include <efsw/platform/posix/ThreadImpl.hpp> #include <efsw/Thread.hpp> +#include <efsw/platform/posix/ThreadImpl.hpp> #if defined( EFSW_PLATFORM_POSIX ) #include <cassert> -#include <iostream> #include <efsw/Debug.hpp> +#include <iostream> namespace efsw { namespace Platform { -ThreadImpl::ThreadImpl( Thread * owner ) : - mIsActive(false) -{ +ThreadImpl::ThreadImpl( efsw::Thread* owner ) : mIsActive( false ) { mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0; - if ( !mIsActive ) - { + if ( !mIsActive ) { efDEBUG( "Failed to create thread\n" ); } } -void ThreadImpl::wait() -{ +ThreadImpl::~ThreadImpl() { + terminate(); +} + +void ThreadImpl::wait() { // Wait for the thread to finish, no timeout - if ( mIsActive ) - { + if ( mIsActive ) { assert( pthread_equal( pthread_self(), mThread ) == 0 ); - pthread_join( mThread, NULL ); - - mIsActive = false; // Reset the thread state + mIsActive = pthread_join( mThread, NULL ) != 0; } } -void ThreadImpl::terminate() -{ - if ( mIsActive ) - { - #if !defined( __ANDROID__ ) && !defined( ANDROID ) - pthread_cancel( mThread ); - #else - pthread_kill( mThread , SIGUSR1 ); - #endif +void ThreadImpl::terminate() { + if ( mIsActive ) { +#if !defined( __ANDROID__ ) && !defined( ANDROID ) + pthread_cancel( mThread ); +#else + pthread_kill( mThread, SIGUSR1 ); +#endif mIsActive = false; } } -void * ThreadImpl::entryPoint( void * userData ) -{ - // The Thread instance is stored in the user data - Thread * owner = static_cast<Thread*>( userData ); +void* ThreadImpl::entryPoint( void* userData ) { +// Tell the thread to handle cancel requests immediatly +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); +#endif - // Tell the thread to handle cancel requests immediatly - #ifdef PTHREAD_CANCEL_ASYNCHRONOUS - pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); - #endif + // The Thread instance is stored in the user data + Thread* owner = static_cast<Thread*>( userData ); // Forward to the owner owner->run(); @@ -63,6 +57,6 @@ void * ThreadImpl::entryPoint( void * userData ) return NULL; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp index be6dc1b3e58..2e02f9ac89d 100644 --- a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp +++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp @@ -5,6 +5,7 @@ #if defined( EFSW_PLATFORM_POSIX ) +#include <efsw/Atomic.hpp> #include <pthread.h> namespace efsw { @@ -13,22 +14,25 @@ class Thread; namespace Platform { -class ThreadImpl -{ - public: - ThreadImpl( Thread * owner ); - - void wait(); - - void terminate(); - protected: - static void * entryPoint( void* userData ); - - pthread_t mThread; - bool mIsActive; +class ThreadImpl { + public: + explicit ThreadImpl( efsw::Thread* owner ); + + ~ThreadImpl(); + + void wait(); + + void terminate(); + + protected: + static void* entryPoint( void* userData ); + + pthread_t mThread; + Atomic<bool> mIsActive; }; -}} +} // namespace Platform +} // namespace efsw #endif diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp index cf27eb7a0f6..2b875139e8b 100644 --- a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp @@ -4,7 +4,7 @@ #include <climits> #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif #include <windows.h> @@ -16,31 +16,30 @@ namespace efsw { namespace Platform { -bool FileSystem::changeWorkingDirectory( const std::string & path ) -{ +bool FileSystem::changeWorkingDirectory( const std::string& path ) { int res; #ifdef EFSW_COMPILER_MSVC - #ifdef UNICODE +#ifdef UNICODE res = _wchdir( String::fromUtf8( path.c_str() ).toWideString().c_str() ); - #else +#else res = _chdir( String::fromUtf8( path.c_str() ).toAnsiString().c_str() ); - #endif +#endif #else res = chdir( path.c_str() ); #endif return -1 != res; } -std::string FileSystem::getCurrentWorkingDirectory() -{ +std::string FileSystem::getCurrentWorkingDirectory() { #ifdef EFSW_COMPILER_MSVC - #if defined( UNICODE ) AND !defined( EFSW_NO_WIDECHAR ) +#if defined( UNICODE ) && !defined( EFSW_NO_WIDECHAR ) wchar_t dir[_MAX_PATH]; return ( 0 != GetCurrentDirectoryW( _MAX_PATH, dir ) ) ? String( dir ).toUtf8() : std::string(); - #else +#else char dir[_MAX_PATH]; - return ( 0 != GetCurrentDirectory( _MAX_PATH, dir ) ) ? String( dir, std::locale() ).toUtf8() : std::string(); - #endif + return ( 0 != GetCurrentDirectory( _MAX_PATH, dir ) ) ? String( dir, std::locale() ).toUtf8() + : std::string(); +#endif #else char dir[PATH_MAX + 1]; getcwd( dir, PATH_MAX + 1 ); @@ -48,42 +47,34 @@ std::string FileSystem::getCurrentWorkingDirectory() #endif } -FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) -{ +FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) { FileInfoMap files; String tpath( path ); - if ( tpath[ tpath.size() - 1 ] == '/' || tpath[ tpath.size() - 1 ] == '\\' ) - { + if ( tpath[tpath.size() - 1] == '/' || tpath[tpath.size() - 1] == '\\' ) { tpath += "*"; - } - else - { + } else { tpath += "\\*"; } WIN32_FIND_DATAW findFileData; HANDLE hFind = FindFirstFileW( (LPCWSTR)tpath.toWideString().c_str(), &findFileData ); - if( hFind != INVALID_HANDLE_VALUE ) - { + if ( hFind != INVALID_HANDLE_VALUE ) { std::string name( String( findFileData.cFileName ).toUtf8() ); std::string fpath( path + name ); - if ( name != "." && name != ".." ) - { - files[ name ] = FileInfo( fpath ); + if ( name != "." && name != ".." ) { + files[name] = FileInfo( fpath ); } - while( FindNextFileW( hFind, &findFileData ) ) - { + while ( FindNextFileW( hFind, &findFileData ) ) { name = String( findFileData.cFileName ).toUtf8(); fpath = path + name; - if ( name != "." && name != ".." ) - { - files[ name ] = FileInfo( fpath ); + if ( name != "." && name != ".." ) { + files[name] = FileInfo( fpath ); } } @@ -93,32 +84,28 @@ FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) return files; } -char FileSystem::getOSSlash() -{ +char FileSystem::getOSSlash() { return '\\'; } -bool FileSystem::isDirectory( const std::string& path ) -{ - return 0 != ( GetFileAttributesW( String( path ).toWideString().c_str() ) & FILE_ATTRIBUTE_DIRECTORY ); +bool FileSystem::isDirectory( const std::string& path ) { + DWORD attrs = GetFileAttributesW( String( path ).toWideString().c_str() ); + return attrs != INVALID_FILE_ATTRIBUTES && ( attrs & FILE_ATTRIBUTE_DIRECTORY ) != 0; } -bool FileSystem::isRemoteFS( const std::string& directory ) -{ - if ((directory[0] == '\\' || directory[0] == '/') && - (directory[1] == '\\' || directory[1] == '/')) - { +bool FileSystem::isRemoteFS( const std::string& directory ) { + if ( ( directory[0] == '\\' || directory[0] == '/' ) && + ( directory[1] == '\\' || directory[1] == '/' ) ) { return true; } - if ( directory.size() >= 3 ) - { + if ( directory.size() >= 3 ) { return 4 == GetDriveTypeA( directory.substr( 0, 3 ).c_str() ); } return false; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp index 8f6c5ad1837..e952efcee62 100644 --- a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp @@ -1,31 +1,30 @@ #ifndef EFSW_FILESYSTEMIMPLWIN_HPP #define EFSW_FILESYSTEMIMPLWIN_HPP -#include <efsw/base.hpp> -#include <efsw/String.hpp> #include <efsw/FileInfo.hpp> +#include <efsw/String.hpp> +#include <efsw/base.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 namespace efsw { namespace Platform { -class FileSystem -{ - public: - static FileInfoMap filesInfoFromPath( const std::string& path ); +class FileSystem { + public: + static FileInfoMap filesInfoFromPath( const std::string& path ); - static char getOSSlash(); + static char getOSSlash(); - static bool isDirectory( const std::string& path ); + static bool isDirectory( const std::string& path ); - static bool isRemoteFS( const std::string& directory ); + static bool isRemoteFS( const std::string& directory ); - static bool changeWorkingDirectory( const std::string & path ); + static bool changeWorkingDirectory( const std::string& path ); - static std::string getCurrentWorkingDirectory(); + static std::string getCurrentWorkingDirectory(); }; -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp index 0c8c36d8b39..62b7f836e51 100644 --- a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp @@ -4,26 +4,22 @@ namespace efsw { namespace Platform { -MutexImpl::MutexImpl() -{ - InitializeCriticalSection(&mMutex); +MutexImpl::MutexImpl() { + InitializeCriticalSection( &mMutex ); } -MutexImpl::~MutexImpl() -{ - DeleteCriticalSection(&mMutex); +MutexImpl::~MutexImpl() { + DeleteCriticalSection( &mMutex ); } -void MutexImpl::lock() -{ - EnterCriticalSection(&mMutex); +void MutexImpl::lock() { + EnterCriticalSection( &mMutex ); } -void MutexImpl::unlock() -{ - LeaveCriticalSection(&mMutex); +void MutexImpl::unlock() { + LeaveCriticalSection( &mMutex ); } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp index da1e20c5fa9..7b064920f81 100644 --- a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp @@ -6,29 +6,28 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif #include <windows.h> namespace efsw { namespace Platform { -class MutexImpl -{ - public: - MutexImpl(); +class MutexImpl { + public: + MutexImpl(); - ~MutexImpl(); + ~MutexImpl(); - void lock(); + void lock(); - void unlock(); - private: - CRITICAL_SECTION mMutex; + void unlock(); + + private: + CRITICAL_SECTION mMutex; }; -}} +}} // namespace efsw::Platform #endif #endif - diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.cpp b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp index ddbe1e5c45c..d1f2b21a87c 100644 --- a/dep/efsw/src/efsw/platform/win/SystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp @@ -1,23 +1,21 @@ -#include <efsw/platform/win/SystemImpl.hpp> #include <efsw/String.hpp> +#include <efsw/platform/win/SystemImpl.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif -#include <windows.h> #include <cstdlib> +#include <windows.h> namespace efsw { namespace Platform { -void System::sleep( const unsigned long& ms ) -{ +void System::sleep( const unsigned long& ms ) { ::Sleep( ms ); } -std::string System::getProcessPath() -{ +std::string System::getProcessPath() { // Get path to executable: WCHAR szDrive[_MAX_DRIVE]; WCHAR szDir[_MAX_DIR]; @@ -25,26 +23,24 @@ std::string System::getProcessPath() WCHAR szExt[_MAX_DIR]; std::wstring dllName( _MAX_DIR, 0 ); - GetModuleFileNameW(0, &dllName[0], _MAX_PATH); + GetModuleFileNameW( 0, &dllName[0], _MAX_PATH ); - #ifdef EFSW_COMPILER_MSVC - _wsplitpath_s( dllName.c_str(), szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, szExt, _MAX_DIR ); - #else - _wsplitpath( dllName.c_str(), szDrive, szDir, szFilename, szExt); - #endif +#ifdef EFSW_COMPILER_MSVC + _wsplitpath_s( dllName.c_str(), szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, + szExt, _MAX_DIR ); +#else + _wsplitpath( dllName.c_str(), szDrive, szDir, szFilename, szExt ); +#endif return String( szDrive ).toUtf8() + String( szDir ).toUtf8(); } -void System::maxFD() -{ -} +void System::maxFD() {} -Uint64 System::getMaxFD() -{ // Number of ReadDirectory per thread +Uint64 System::getMaxFD() { // Number of ReadDirectory per thread return 60; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.hpp b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp index 2f785e3565c..99b486756bd 100644 --- a/dep/efsw/src/efsw/platform/win/SystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp @@ -7,19 +7,18 @@ namespace efsw { namespace Platform { -class System -{ - public: - static void sleep( const unsigned long& ms ); +class System { + public: + static void sleep( const unsigned long& ms ); - static std::string getProcessPath(); + static std::string getProcessPath(); - static void maxFD(); + static void maxFD(); - static Uint64 getMaxFD(); + static Uint64 getMaxFD(); }; -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp index 48c9456adab..463934c9009 100644 --- a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp @@ -1,6 +1,6 @@ -#include <efsw/platform/win/ThreadImpl.hpp> -#include <efsw/Thread.hpp> #include <assert.h> +#include <efsw/Thread.hpp> +#include <efsw/platform/win/ThreadImpl.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 @@ -8,57 +8,49 @@ namespace efsw { namespace Platform { -ThreadImpl::ThreadImpl( Thread *owner ) -{ - mThread = reinterpret_cast<HANDLE>( _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) ); +ThreadImpl::ThreadImpl( efsw::Thread* owner ) { + mThread = reinterpret_cast<HANDLE>( + _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) ); - if ( !mThread ) - { + if ( !mThread ) { efDEBUG( "Failed to create thread\n" ); } } -ThreadImpl::~ThreadImpl() -{ - if ( mThread ) - { +ThreadImpl::~ThreadImpl() { + if ( mThread ) { CloseHandle( mThread ); } } -void ThreadImpl::wait() -{ +void ThreadImpl::wait() { // Wait for the thread to finish, no timeout - if ( mThread ) - { + if ( mThread ) { assert( mThreadId != GetCurrentThreadId() ); // A thread cannot wait for itself! WaitForSingleObject( mThread, INFINITE ); } } -void ThreadImpl::terminate() -{ - if ( mThread ) - { +void ThreadImpl::terminate() { + if ( mThread ) { TerminateThread( mThread, 0 ); } } -unsigned int __stdcall ThreadImpl::entryPoint( void * userData ) -{ +unsigned int __stdcall ThreadImpl::entryPoint( void* userData ) { // The Thread instance is stored in the user data - Thread * owner = static_cast<Thread*>( userData ); + Thread* owner = static_cast<Thread*>( userData ); // Forward to the owner owner->run(); // Optional, but it is cleaner - _endthreadex(0); + _endthreadex( 0 ); return 0; } -}} +}} // namespace efsw::Platform #endif diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp index 45e4505897a..455f24c2783 100644 --- a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp @@ -6,10 +6,10 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN #endif -#include <windows.h> #include <process.h> +#include <windows.h> namespace efsw { @@ -17,24 +17,25 @@ class Thread; namespace Platform { -class ThreadImpl -{ - public: - ThreadImpl( Thread * owner ); - - ~ThreadImpl(); - - void wait(); - - void terminate(); - protected: - static unsigned int __stdcall entryPoint(void* userData); - - HANDLE mThread; - unsigned int mThreadId; +class ThreadImpl { + public: + explicit ThreadImpl( efsw::Thread* owner ); + + ~ThreadImpl(); + + void wait(); + + void terminate(); + + protected: + static unsigned int __stdcall entryPoint( void* userData ); + + HANDLE mThread; + unsigned int mThreadId; }; -}} +} // namespace Platform +} // namespace efsw #endif diff --git a/dep/efsw/src/test/efsw-test.c b/dep/efsw/src/test/efsw-test.c new file mode 100644 index 00000000000..54a3e21bba5 --- /dev/null +++ b/dep/efsw/src/test/efsw-test.c @@ -0,0 +1,164 @@ +#include <efsw/efsw.h> + +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> + +#ifdef _WIN32 + #include <Windows.h> +#else + #include <unistd.h> +#endif + +const char PATH_SEPARATOR = +#ifdef _WIN32 + '\\'; +#else + '/'; +#endif + +bool STOP = false; + +void sigend( int sig ) { + printf( "Bye bye" ); + STOP = true; +} + +void sleepMsecs( int msecs ) { +#ifdef _WIN32 + Sleep( msecs ); +#else + sleep( msecs ); +#endif +} + +const char * getActionName( enum efsw_action action ) { + switch ( action ) { + case EFSW_ADD: + return "Add"; + case EFSW_MODIFIED: + return "Modified"; + case EFSW_DELETE: + return "Delete"; + case EFSW_MOVED: + return "Moved"; + default: + return "Bad Action"; + } +} + +void handleFileAction( efsw_watcher watcher, efsw_watchid watchid, + const char* dir, const char* filename, + enum efsw_action action, const char* oldFilename, + void* param ) { + if ( strlen( oldFilename ) == 0 ) { + printf( "Watch ID %ld DIR (%s) FILE (%s) has event %s\n", + watchid, dir, filename, getActionName( action )); + } else { + printf( "Watch ID %ld DIR (%s) FILE (from file %s to %s) has event %s\n", + watchid, dir, oldFilename, filename, getActionName( action )); + } +} + +efsw_watchid handleWatchID( efsw_watchid watchid ) { + switch ( watchid ) { + case EFSW_NOTFOUND: + case EFSW_REPEATED: + case EFSW_OUTOFSCOPE: + case EFSW_REMOTE: + case EFSW_WATCHER_FAILED: + case EFSW_UNSPECIFIED: { + printf( "%s\n", efsw_getlasterror() ); + break; + } + default: { + printf( "Added WatchID: %ld\n", watchid ); + } + } + + return watchid; +} + +int main( int argc, char** argv ) { + signal( SIGABRT, sigend ); + signal( SIGINT, sigend ); + signal( SIGTERM, sigend ); + + printf("Press ^C to exit demo\n"); + + bool commonTest = true; + bool useGeneric = false; + char *path = 0; + + if ( argc >= 2 ) { + path = argv[1]; + + struct stat s; + if( stat(path,&s) == 0 && (s.st_mode & S_IFDIR) == S_IFDIR ) { + commonTest = false; + } + + if ( argc >= 3 ) { + if ( strcmp( argv[2], "true" ) == 0 ) { + useGeneric = true; + } + } + } + + /// create the file watcher object + efsw_watcher fileWatcher = efsw_create( useGeneric ); + efsw_follow_symlinks( fileWatcher, false ); + efsw_allow_outofscopelinks( fileWatcher, false ); + + if ( commonTest ) { + char cwd[256]; + getcwd( cwd, sizeof(cwd) ); + printf( "CurPath: %s\n", cwd ); + + /// starts watching + efsw_watch( fileWatcher ); + + /// add a watch to the system + char path1[256]; + sprintf(path1, "%s%ctest", cwd, PATH_SEPARATOR ); + handleWatchID( efsw_addwatch_withoptions( fileWatcher, path1, handleFileAction, true, 0, 0, 0 ) ); + + /// adds another watch after started watching... + sleepMsecs( 100 ); + + char path2[256]; + sprintf(path2, "%s%ctest2", cwd, PATH_SEPARATOR ); + efsw_watchid watchID = handleWatchID( + efsw_addwatch_withoptions( fileWatcher, path2, handleFileAction, true, 0, 0, 0 ) ); + + /// delete the watch + if ( watchID > 0 ) { + sleepMsecs( 1000 ); + efsw_removewatch_byid( fileWatcher, watchID ); + } + } else { + if ( efsw_addwatch( fileWatcher, path, handleFileAction, true, 0 ) > 0 ) { + efsw_watch( fileWatcher ); + + printf( "Watching directory: %s\n", path ); + + if ( useGeneric ) { + printf( "Using generic backend watcher\n" ); + } + } else { + printf( "Error trying to watch directory: %s\n", path ); + printf( "%s\n", efsw_getlasterror() ); + } + } + + while ( !STOP ) { + sleepMsecs( 100 ); + } + + efsw_release( fileWatcher ); + + return 0; +} diff --git a/dep/efsw/src/test/efsw-test.cpp b/dep/efsw/src/test/efsw-test.cpp index a49e3414fcc..d51d68d7599 100644 --- a/dep/efsw/src/test/efsw-test.cpp +++ b/dep/efsw/src/test/efsw-test.cpp @@ -1,56 +1,59 @@ -#include <efsw/efsw.hpp> -#include <efsw/System.hpp> #include <efsw/FileSystem.hpp> -#include <signal.h> +#include <efsw/System.hpp> +#include <efsw/efsw.hpp> #include <iostream> +#include <signal.h> bool STOP = false; -void sigend(int signal) -{ +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"; - } +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 = "" ) - { - std::cout << "DIR (" << dir + ") FILE (" + ( oldFilename.empty() ? "" : "from file " + oldFilename + " to " ) + filename + ") has event " << getActionName( action ) << std::endl; - } + 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 ) - { +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::Unspecified: - { + case efsw::Errors::WatcherFailed: + case efsw::Errors::Unspecified: { std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl; break; } - default: - { + default: { std::cout << "Added WatchID: " << watchid << std::endl; } } @@ -58,11 +61,10 @@ efsw::WatchID handleWatchID( efsw::WatchID watchid ) return watchid; } -int main(int argc, char **argv) -{ - signal( SIGABRT , sigend ); - signal( SIGINT , sigend ); - signal( SIGTERM , sigend ); +int main( int argc, char** argv ) { + signal( SIGABRT, sigend ); + signal( SIGINT, sigend ); + signal( SIGTERM, sigend ); std::cout << "Press ^C to exit demo" << std::endl; @@ -70,25 +72,21 @@ int main(int argc, char **argv) bool useGeneric = false; std::string path; - if ( argc >= 2 ) - { + if ( argc >= 2 ) { path = std::string( argv[1] ); - if ( efsw::FileSystem::isDirectory( path ) ) - { - commonTest = false; + if ( efsw::FileSystem::isDirectory( path ) ) { + commonTest = false; } - if ( argc >= 3 ) - { - if ( std::string( argv[2] ) == "true" ) - { + if ( argc >= 3 ) { + if ( std::string( argv[2] ) == "true" ) { useGeneric = true; } } } - UpdateListener * ul = new UpdateListener(); + UpdateListener* ul = new UpdateListener(); /// create the file watcher object efsw::FileWatcher fileWatcher( useGeneric ); @@ -96,54 +94,44 @@ int main(int argc, char **argv) fileWatcher.followSymlinks( false ); fileWatcher.allowOutOfScopeLinks( false ); - if ( commonTest ) - { + 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 ) ); - /// starts watching - fileWatcher.watch(); - /// adds another watch after started watching... efsw::System::sleep( 100 ); - efsw::WatchID watchID = handleWatchID( fileWatcher.addWatch( CurPath + "test2", ul, true ) ); + efsw::WatchID watchID = + handleWatchID( fileWatcher.addWatch( CurPath + "test2", ul, true ) ); /// delete the watch - if ( watchID > 0 ) - { + if ( watchID > 0 ) { efsw::System::sleep( 1000 ); fileWatcher.removeWatch( watchID ); } - } - else - { - efsw::WatchID err; - - if ( ( err = fileWatcher.addWatch( path, ul, true ) ) > 0 ) - { + } else { + if ( fileWatcher.addWatch( path, ul, true ) > 0 ) { fileWatcher.watch(); std::cout << "Watching directory: " << path.c_str() << std::endl; - if ( useGeneric ) - { + if ( useGeneric ) { std::cout << "Using generic backend watcher" << std::endl; } - } - else - { + } 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 ) - { + while ( !STOP ) { efsw::System::sleep( 100 ); } |