diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-04-09 17:40:13 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-04-09 17:40:13 +0800 |
| commit | 9750786a5c03b5ce3ea22b240d1b3cd34990856b (patch) | |
| tree | e495e43245e1bacc86d33142af202613a82a40c1 /src | |
| parent | 571fb952b99e580a0381f539885f8f175e2ec3b0 (diff) | |
| download | yuescript-9750786a5c03b5ce3ea22b240d1b3cd34990856b.tar.gz yuescript-9750786a5c03b5ce3ea22b240d1b3cd34990856b.tar.bz2 yuescript-9750786a5c03b5ce3ea22b240d1b3cd34990856b.zip | |
Updated efsw. Fixed issue #204.
Diffstat (limited to 'src')
74 files changed, 2952 insertions, 2613 deletions
diff --git a/src/3rdParty/efsw/Atomic.hpp b/src/3rdParty/efsw/Atomic.hpp index 4008dfc..9015c60 100755..100644 --- a/src/3rdParty/efsw/Atomic.hpp +++ b/src/3rdParty/efsw/Atomic.hpp | |||
| @@ -3,9 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <efsw/base.hpp> | 4 | #include <efsw/base.hpp> |
| 5 | 5 | ||
| 6 | #ifdef EFSW_USE_CXX11 | ||
| 7 | #include <atomic> | 6 | #include <atomic> |
| 8 | #endif | ||
| 9 | 7 | ||
| 10 | namespace efsw { | 8 | namespace efsw { |
| 11 | 9 | ||
| @@ -14,36 +12,20 @@ template <typename T> class Atomic { | |||
| 14 | explicit Atomic( T set = false ) : set_( set ) {} | 12 | explicit Atomic( T set = false ) : set_( set ) {} |
| 15 | 13 | ||
| 16 | Atomic& operator=( T set ) { | 14 | Atomic& operator=( T set ) { |
| 17 | #ifdef EFSW_USE_CXX11 | ||
| 18 | set_.store( set, std::memory_order_release ); | 15 | set_.store( set, std::memory_order_release ); |
| 19 | #else | ||
| 20 | set_ = set; | ||
| 21 | #endif | ||
| 22 | return *this; | 16 | return *this; |
| 23 | } | 17 | } |
| 24 | 18 | ||
| 25 | explicit operator T() const { | 19 | explicit operator T() const { |
| 26 | #ifdef EFSW_USE_CXX11 | ||
| 27 | return set_.load( std::memory_order_acquire ); | 20 | return set_.load( std::memory_order_acquire ); |
| 28 | #else | ||
| 29 | return set_; | ||
| 30 | #endif | ||
| 31 | } | 21 | } |
| 32 | 22 | ||
| 33 | T load() const { | 23 | T load() const { |
| 34 | #ifdef EFSW_USE_CXX11 | ||
| 35 | return set_.load( std::memory_order_acquire ); | 24 | return set_.load( std::memory_order_acquire ); |
| 36 | #else | ||
| 37 | return set_; | ||
| 38 | #endif | ||
| 39 | } | 25 | } |
| 40 | 26 | ||
| 41 | private: | 27 | private: |
| 42 | #ifdef EFSW_USE_CXX11 | ||
| 43 | std::atomic<T> set_; | 28 | std::atomic<T> set_; |
| 44 | #else | ||
| 45 | volatile T set_; | ||
| 46 | #endif | ||
| 47 | }; | 29 | }; |
| 48 | 30 | ||
| 49 | } // namespace efsw | 31 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/Debug.cpp b/src/3rdParty/efsw/Debug.cpp index 18cfd31..18cfd31 100755..100644 --- a/src/3rdParty/efsw/Debug.cpp +++ b/src/3rdParty/efsw/Debug.cpp | |||
diff --git a/src/3rdParty/efsw/Debug.hpp b/src/3rdParty/efsw/Debug.hpp index 78d3557..fefaec4 100755..100644 --- a/src/3rdParty/efsw/Debug.hpp +++ b/src/3rdParty/efsw/Debug.hpp | |||
| @@ -49,8 +49,10 @@ void efPRINTC( unsigned int cond, const char* format, ... ); | |||
| 49 | #define efDEBUGC( cond, format, args... ) \ | 49 | #define efDEBUGC( cond, format, args... ) \ |
| 50 | {} | 50 | {} |
| 51 | #else | 51 | #else |
| 52 | #define efDEBUG | 52 | #define efDEBUG( ... ) \ |
| 53 | #define efDEBUGC | 53 | {} |
| 54 | #define efDEBUGC( ... ) \ | ||
| 55 | {} | ||
| 54 | #endif | 56 | #endif |
| 55 | 57 | ||
| 56 | #endif | 58 | #endif |
diff --git a/src/3rdParty/efsw/DirWatcherGeneric.cpp b/src/3rdParty/efsw/DirWatcherGeneric.cpp index 8b6bc8a..8b6bc8a 100755..100644 --- a/src/3rdParty/efsw/DirWatcherGeneric.cpp +++ b/src/3rdParty/efsw/DirWatcherGeneric.cpp | |||
diff --git a/src/3rdParty/efsw/DirWatcherGeneric.hpp b/src/3rdParty/efsw/DirWatcherGeneric.hpp index ca52de7..ca52de7 100755..100644 --- a/src/3rdParty/efsw/DirWatcherGeneric.hpp +++ b/src/3rdParty/efsw/DirWatcherGeneric.hpp | |||
diff --git a/src/3rdParty/efsw/DirectorySnapshot.cpp b/src/3rdParty/efsw/DirectorySnapshot.cpp index 6049e4a..f78475f 100755..100644 --- a/src/3rdParty/efsw/DirectorySnapshot.cpp +++ b/src/3rdParty/efsw/DirectorySnapshot.cpp | |||
| @@ -44,7 +44,7 @@ void DirectorySnapshot::initFiles() { | |||
| 44 | Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); | 44 | Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); |
| 45 | 45 | ||
| 46 | FileInfoMap::iterator it = Files.begin(); | 46 | FileInfoMap::iterator it = Files.begin(); |
| 47 | std::list<std::string> eraseFiles; | 47 | std::vector<std::string> eraseFiles; |
| 48 | 48 | ||
| 49 | /// Remove all non regular files and non directories | 49 | /// Remove all non regular files and non directories |
| 50 | for ( ; it != Files.end(); it++ ) { | 50 | for ( ; it != Files.end(); it++ ) { |
| @@ -53,7 +53,7 @@ void DirectorySnapshot::initFiles() { | |||
| 53 | } | 53 | } |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | for ( std::list<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); | 56 | for ( std::vector<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); |
| 57 | eit++ ) { | 57 | eit++ ) { |
| 58 | Files.erase( *eit ); | 58 | Files.erase( *eit ); |
| 59 | } | 59 | } |
diff --git a/src/3rdParty/efsw/DirectorySnapshot.hpp b/src/3rdParty/efsw/DirectorySnapshot.hpp index 0e60542..0e60542 100755..100644 --- a/src/3rdParty/efsw/DirectorySnapshot.hpp +++ b/src/3rdParty/efsw/DirectorySnapshot.hpp | |||
diff --git a/src/3rdParty/efsw/DirectorySnapshotDiff.cpp b/src/3rdParty/efsw/DirectorySnapshotDiff.cpp index 37ee507..37ee507 100755..100644 --- a/src/3rdParty/efsw/DirectorySnapshotDiff.cpp +++ b/src/3rdParty/efsw/DirectorySnapshotDiff.cpp | |||
diff --git a/src/3rdParty/efsw/DirectorySnapshotDiff.hpp b/src/3rdParty/efsw/DirectorySnapshotDiff.hpp index 26a29ec..26a29ec 100755..100644 --- a/src/3rdParty/efsw/DirectorySnapshotDiff.hpp +++ b/src/3rdParty/efsw/DirectorySnapshotDiff.hpp | |||
diff --git a/src/3rdParty/efsw/FileInfo.cpp b/src/3rdParty/efsw/FileInfo.cpp index 072cd6d..707f617 100755..100644 --- a/src/3rdParty/efsw/FileInfo.cpp +++ b/src/3rdParty/efsw/FileInfo.cpp | |||
| @@ -35,10 +35,6 @@ | |||
| 35 | #endif | 35 | #endif |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 | ||
| 39 | #include <filesystem> | ||
| 40 | #endif | ||
| 41 | |||
| 42 | namespace efsw { | 38 | namespace efsw { |
| 43 | 39 | ||
| 44 | bool FileInfo::exists( const std::string& filePath ) { | 40 | bool FileInfo::exists( const std::string& filePath ) { |
| @@ -186,12 +182,14 @@ bool FileInfo::isLink() const { | |||
| 186 | std::string FileInfo::linksTo() { | 182 | std::string FileInfo::linksTo() { |
| 187 | #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 | 183 | #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 |
| 188 | if ( isLink() ) { | 184 | if ( isLink() ) { |
| 189 | std::error_code ec; | 185 | char* ch = realpath( Filepath.c_str(), NULL ); |
| 190 | auto ch = std::filesystem::canonical( Filepath, ec ); | 186 | |
| 187 | if ( NULL != ch ) { | ||
| 188 | std::string tstr( ch ); | ||
| 191 | 189 | ||
| 192 | if ( !ec ) { | 190 | free( ch ); |
| 193 | 191 | ||
| 194 | return ch.string(); | 192 | return tstr; |
| 195 | } | 193 | } |
| 196 | } | 194 | } |
| 197 | #endif | 195 | #endif |
diff --git a/src/3rdParty/efsw/FileInfo.hpp b/src/3rdParty/efsw/FileInfo.hpp index f1bcf4b..1b55c35 100755..100644 --- a/src/3rdParty/efsw/FileInfo.hpp +++ b/src/3rdParty/efsw/FileInfo.hpp | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #define EFSW_FILEINFO_HPP | 2 | #define EFSW_FILEINFO_HPP |
| 3 | 3 | ||
| 4 | #include <efsw/base.hpp> | 4 | #include <efsw/base.hpp> |
| 5 | #include <list> | 5 | #include <vector> |
| 6 | #include <map> | 6 | #include <map> |
| 7 | #include <string> | 7 | #include <string> |
| 8 | 8 | ||
| @@ -18,11 +18,11 @@ class FileInfo { | |||
| 18 | 18 | ||
| 19 | FileInfo(); | 19 | FileInfo(); |
| 20 | 20 | ||
| 21 | explicit FileInfo( const std::string& filepath ); | 21 | FileInfo( const std::string& filepath ); |
| 22 | 22 | ||
| 23 | FileInfo( const std::string& filepath, bool linkInfo ); | 23 | FileInfo( const std::string& filepath, bool linkInfo ); |
| 24 | 24 | ||
| 25 | FileInfo( const FileInfo& ) = default; | 25 | FileInfo(const FileInfo&) = default; |
| 26 | 26 | ||
| 27 | bool operator==( const FileInfo& Other ) const; | 27 | bool operator==( const FileInfo& Other ) const; |
| 28 | 28 | ||
| @@ -58,8 +58,8 @@ class FileInfo { | |||
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | typedef std::map<std::string, FileInfo> FileInfoMap; | 60 | typedef std::map<std::string, FileInfo> FileInfoMap; |
| 61 | typedef std::list<FileInfo> FileInfoList; | 61 | typedef std::vector<FileInfo> FileInfoList; |
| 62 | typedef std::list<std::pair<std::string, FileInfo>> MovedList; | 62 | typedef std::vector<std::pair<std::string, FileInfo>> MovedList; |
| 63 | 63 | ||
| 64 | } // namespace efsw | 64 | } // namespace efsw |
| 65 | 65 | ||
diff --git a/src/3rdParty/efsw/FileSystem.cpp b/src/3rdParty/efsw/FileSystem.cpp index 867f120..1ed346c 100755..100644 --- a/src/3rdParty/efsw/FileSystem.cpp +++ b/src/3rdParty/efsw/FileSystem.cpp | |||
| @@ -1,10 +1,19 @@ | |||
| 1 | #include <cstring> | ||
| 1 | #include <efsw/FileSystem.hpp> | 2 | #include <efsw/FileSystem.hpp> |
| 2 | #include <efsw/platform/platformimpl.hpp> | 3 | #include <efsw/platform/platformimpl.hpp> |
| 4 | #include <climits> | ||
| 3 | 5 | ||
| 4 | #if EFSW_OS == EFSW_OS_MACOSX | 6 | #if EFSW_OS == EFSW_OS_MACOSX |
| 5 | #include <CoreFoundation/CoreFoundation.h> | 7 | #include <CoreFoundation/CoreFoundation.h> |
| 6 | #endif | 8 | #endif |
| 7 | 9 | ||
| 10 | #if EFSW_OS == EFSW_OS_WIN | ||
| 11 | #ifndef WIN32_LEAN_AND_MEAN | ||
| 12 | #define WIN32_LEAN_AND_MEAN | ||
| 13 | #endif | ||
| 14 | #include <windows.h> | ||
| 15 | #endif | ||
| 16 | |||
| 8 | namespace efsw { | 17 | namespace efsw { |
| 9 | 18 | ||
| 10 | bool FileSystem::isDirectory( const std::string& path ) { | 19 | bool FileSystem::isDirectory( const std::string& path ) { |
| @@ -26,13 +35,13 @@ bool FileSystem::slashAtEnd( std::string& dir ) { | |||
| 26 | } | 35 | } |
| 27 | 36 | ||
| 28 | void FileSystem::dirAddSlashAtEnd( std::string& dir ) { | 37 | void FileSystem::dirAddSlashAtEnd( std::string& dir ) { |
| 29 | if ( dir.size() > 1 && dir[dir.size() - 1] != getOSSlash() ) { | 38 | if ( dir.size() >= 1 && dir[dir.size() - 1] != getOSSlash() ) { |
| 30 | dir.push_back( getOSSlash() ); | 39 | dir.push_back( getOSSlash() ); |
| 31 | } | 40 | } |
| 32 | } | 41 | } |
| 33 | 42 | ||
| 34 | void FileSystem::dirRemoveSlashAtEnd( std::string& dir ) { | 43 | void FileSystem::dirRemoveSlashAtEnd( std::string& dir ) { |
| 35 | if ( dir.size() > 1 && dir[dir.size() - 1] == getOSSlash() ) { | 44 | if ( dir.size() >= 1 && dir[dir.size() - 1] == getOSSlash() ) { |
| 36 | dir.erase( dir.size() - 1 ); | 45 | dir.erase( dir.size() - 1 ); |
| 37 | } | 46 | } |
| 38 | } | 47 | } |
| @@ -91,13 +100,30 @@ std::string FileSystem::precomposeFileName( const std::string& name ) { | |||
| 91 | 100 | ||
| 92 | CFStringNormalize( cfMutable, kCFStringNormalizationFormC ); | 101 | CFStringNormalize( cfMutable, kCFStringNormalizationFormC ); |
| 93 | 102 | ||
| 94 | char c_str[255 + 1]; | 103 | const char* c_str = CFStringGetCStringPtr( cfMutable, kCFStringEncodingUTF8 ); |
| 95 | CFStringGetCString( cfMutable, c_str, sizeof( c_str ) - 1, kCFStringEncodingUTF8 ); | 104 | if ( c_str != NULL ) { |
| 96 | 105 | std::string result( c_str ); | |
| 97 | CFRelease( cfStringRef ); | 106 | CFRelease( cfStringRef ); |
| 98 | CFRelease( cfMutable ); | 107 | CFRelease( cfMutable ); |
| 108 | return result; | ||
| 109 | } | ||
| 110 | CFIndex length = CFStringGetLength( cfMutable ); | ||
| 111 | CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ); | ||
| 112 | if ( maxSize == kCFNotFound ) { | ||
| 113 | CFRelease( cfStringRef ); | ||
| 114 | CFRelease( cfMutable ); | ||
| 115 | return std::string(); | ||
| 116 | } | ||
| 99 | 117 | ||
| 100 | return std::string( c_str ); | 118 | std::string result( maxSize + 1, '\0' ); |
| 119 | if ( CFStringGetCString( cfMutable, &result[0], result.size(), kCFStringEncodingUTF8 ) ) { | ||
| 120 | result.resize( std::strlen( result.c_str() ) ); | ||
| 121 | CFRelease( cfStringRef ); | ||
| 122 | CFRelease( cfMutable ); | ||
| 123 | } else { | ||
| 124 | result.clear(); | ||
| 125 | } | ||
| 126 | return result; | ||
| 101 | #else | 127 | #else |
| 102 | return name; | 128 | return name; |
| 103 | #endif | 129 | #endif |
| @@ -115,4 +141,21 @@ std::string FileSystem::getCurrentWorkingDirectory() { | |||
| 115 | return Platform::FileSystem::getCurrentWorkingDirectory(); | 141 | return Platform::FileSystem::getCurrentWorkingDirectory(); |
| 116 | } | 142 | } |
| 117 | 143 | ||
| 144 | std::string FileSystem::getRealPath( const std::string& path ) { | ||
| 145 | std::string realPath; | ||
| 146 | #if defined( EFSW_PLATFORM_POSIX ) | ||
| 147 | char dir[PATH_MAX]; | ||
| 148 | realpath( path.c_str(), &dir[0] ); | ||
| 149 | realPath = std::string( dir ); | ||
| 150 | #elif EFSW_OS == EFSW_OS_WIN | ||
| 151 | wchar_t dir[_MAX_PATH + 1]; | ||
| 152 | GetFullPathNameW( String::fromUtf8( path ).toWideString().c_str(), _MAX_PATH, &dir[0], | ||
| 153 | nullptr ); | ||
| 154 | realPath = String( dir ).toUtf8(); | ||
| 155 | #else | ||
| 156 | #warning FileSystem::getRealPath() not implemented on this platform. | ||
| 157 | #endif | ||
| 158 | return realPath; | ||
| 159 | } | ||
| 160 | |||
| 118 | } // namespace efsw | 161 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/FileSystem.hpp b/src/3rdParty/efsw/FileSystem.hpp index 6c24386..1d66ece 100755..100644 --- a/src/3rdParty/efsw/FileSystem.hpp +++ b/src/3rdParty/efsw/FileSystem.hpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include <efsw/FileInfo.hpp> | 4 | #include <efsw/FileInfo.hpp> |
| 5 | #include <efsw/base.hpp> | 5 | #include <efsw/base.hpp> |
| 6 | #include <map> | ||
| 7 | 6 | ||
| 8 | namespace efsw { | 7 | namespace efsw { |
| 9 | 8 | ||
| @@ -34,6 +33,9 @@ class FileSystem { | |||
| 34 | static bool changeWorkingDirectory( const std::string& path ); | 33 | static bool changeWorkingDirectory( const std::string& path ); |
| 35 | 34 | ||
| 36 | static std::string getCurrentWorkingDirectory(); | 35 | static std::string getCurrentWorkingDirectory(); |
| 36 | |||
| 37 | static std::string getRealPath( const std::string& path ); | ||
| 38 | |||
| 37 | }; | 39 | }; |
| 38 | 40 | ||
| 39 | } // namespace efsw | 41 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/FileWatcher.cpp b/src/3rdParty/efsw/FileWatcher.cpp index 696a46f..f45b243 100755..100644 --- a/src/3rdParty/efsw/FileWatcher.cpp +++ b/src/3rdParty/efsw/FileWatcher.cpp | |||
| @@ -1,119 +1,120 @@ | |||
| 1 | #include <efsw/FileSystem.hpp> | 1 | #include <efsw/FileSystem.hpp> |
| 2 | #include <efsw/FileWatcherGeneric.hpp> | 2 | #include <efsw/FileWatcherGeneric.hpp> |
| 3 | #include <efsw/FileWatcherImpl.hpp> | 3 | #include <efsw/FileWatcherImpl.hpp> |
| 4 | #include <efsw/efsw.hpp> | 4 | #include <efsw/efsw.hpp> |
| 5 | 5 | ||
| 6 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 | 6 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 |
| 7 | #include <efsw/FileWatcherWin32.hpp> | 7 | #include <efsw/FileWatcherWin32.hpp> |
| 8 | #define FILEWATCHER_IMPL FileWatcherWin32 | 8 | #define FILEWATCHER_IMPL FileWatcherWin32 |
| 9 | #define BACKEND_NAME "Win32" | 9 | #define BACKEND_NAME "Win32" |
| 10 | #elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY | 10 | #elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY |
| 11 | #include <efsw/FileWatcherInotify.hpp> | 11 | #include <efsw/FileWatcherInotify.hpp> |
| 12 | #define FILEWATCHER_IMPL FileWatcherInotify | 12 | #define FILEWATCHER_IMPL FileWatcherInotify |
| 13 | #define BACKEND_NAME "Inotify" | 13 | #define BACKEND_NAME "Inotify" |
| 14 | #elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE | 14 | #elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE |
| 15 | #include <efsw/FileWatcherKqueue.hpp> | 15 | #include <efsw/FileWatcherKqueue.hpp> |
| 16 | #define FILEWATCHER_IMPL FileWatcherKqueue | 16 | #define FILEWATCHER_IMPL FileWatcherKqueue |
| 17 | #define BACKEND_NAME "Kqueue" | 17 | #define BACKEND_NAME "Kqueue" |
| 18 | #elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS | 18 | #elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS |
| 19 | #include <efsw/FileWatcherFSEvents.hpp> | 19 | #include <efsw/FileWatcherFSEvents.hpp> |
| 20 | #define FILEWATCHER_IMPL FileWatcherFSEvents | 20 | #define FILEWATCHER_IMPL FileWatcherFSEvents |
| 21 | #define BACKEND_NAME "FSEvents" | 21 | #define BACKEND_NAME "FSEvents" |
| 22 | #else | 22 | #else |
| 23 | #define FILEWATCHER_IMPL FileWatcherGeneric | 23 | #define FILEWATCHER_IMPL FileWatcherGeneric |
| 24 | #define BACKEND_NAME "Generic" | 24 | #define BACKEND_NAME "Generic" |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | #include <efsw/Debug.hpp> | 27 | #include <efsw/Debug.hpp> |
| 28 | 28 | ||
| 29 | namespace efsw { | 29 | namespace efsw { |
| 30 | 30 | ||
| 31 | FileWatcher::FileWatcher() : mFollowSymlinks( false ), mOutOfScopeLinks( false ) { | 31 | FileWatcher::FileWatcher() : mFollowSymlinks( false ), mOutOfScopeLinks( false ) { |
| 32 | efDEBUG( "Using backend: %s\n", BACKEND_NAME ); | 32 | efDEBUG( "Using backend: %s\n", BACKEND_NAME ); |
| 33 | 33 | ||
| 34 | mImpl = new FILEWATCHER_IMPL( this ); | 34 | mImpl = new FILEWATCHER_IMPL( this ); |
| 35 | 35 | ||
| 36 | if ( !mImpl->initOK() ) { | 36 | if ( !mImpl->initOK() ) { |
| 37 | efSAFE_DELETE( mImpl ); | 37 | efSAFE_DELETE( mImpl ); |
| 38 | 38 | ||
| 39 | efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); | 39 | efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); |
| 40 | 40 | ||
| 41 | mImpl = new FileWatcherGeneric( this ); | 41 | mImpl = new FileWatcherGeneric( this ); |
| 42 | } | 42 | } |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | FileWatcher::FileWatcher( bool useGenericFileWatcher ) : | 45 | FileWatcher::FileWatcher( bool useGenericFileWatcher ) : |
| 46 | mFollowSymlinks( false ), mOutOfScopeLinks( false ) { | 46 | mFollowSymlinks( false ), mOutOfScopeLinks( false ) { |
| 47 | if ( useGenericFileWatcher ) { | 47 | if ( useGenericFileWatcher ) { |
| 48 | efDEBUG( "Using backend: Generic\n" ); | 48 | efDEBUG( "Using backend: Generic\n" ); |
| 49 | 49 | ||
| 50 | mImpl = new FileWatcherGeneric( this ); | 50 | mImpl = new FileWatcherGeneric( this ); |
| 51 | } else { | 51 | } else { |
| 52 | efDEBUG( "Using backend: %s\n", BACKEND_NAME ); | 52 | efDEBUG( "Using backend: %s\n", BACKEND_NAME ); |
| 53 | 53 | ||
| 54 | mImpl = new FILEWATCHER_IMPL( this ); | 54 | mImpl = new FILEWATCHER_IMPL( this ); |
| 55 | 55 | ||
| 56 | if ( !mImpl->initOK() ) { | 56 | if ( !mImpl->initOK() ) { |
| 57 | efSAFE_DELETE( mImpl ); | 57 | efSAFE_DELETE( mImpl ); |
| 58 | 58 | ||
| 59 | efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); | 59 | efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME ); |
| 60 | 60 | ||
| 61 | mImpl = new FileWatcherGeneric( this ); | 61 | mImpl = new FileWatcherGeneric( this ); |
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | FileWatcher::~FileWatcher() { | 66 | FileWatcher::~FileWatcher() { |
| 67 | efSAFE_DELETE( mImpl ); | 67 | efSAFE_DELETE( mImpl ); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher ) { | 70 | WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher ) { |
| 71 | if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) { | 71 | return addWatch( directory, watcher, false, {} ); |
| 72 | return mImpl->addWatch( directory, watcher, false ); | 72 | } |
| 73 | } else { | 73 | |
| 74 | return Errors::Log::createLastError( Errors::FileRemote, directory ); | 74 | WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 75 | } | 75 | bool recursive ) { |
| 76 | } | 76 | return addWatch( directory, watcher, recursive, {} ); |
| 77 | 77 | } | |
| 78 | WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, | 78 | |
| 79 | bool recursive ) { | 79 | WatchID FileWatcher::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 80 | if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) { | 80 | bool recursive, const std::vector<WatcherOption>& options ) { |
| 81 | return mImpl->addWatch( directory, watcher, recursive ); | 81 | if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) ) { |
| 82 | } else { | 82 | return mImpl->addWatch( directory, watcher, recursive, options ); |
| 83 | return Errors::Log::createLastError( Errors::FileRemote, directory ); | 83 | } else { |
| 84 | } | 84 | return Errors::Log::createLastError( Errors::FileRemote, directory ); |
| 85 | } | 85 | } |
| 86 | 86 | } | |
| 87 | void FileWatcher::removeWatch( const std::string& directory ) { | 87 | |
| 88 | mImpl->removeWatch( directory ); | 88 | void FileWatcher::removeWatch( const std::string& directory ) { |
| 89 | } | 89 | mImpl->removeWatch( directory ); |
| 90 | 90 | } | |
| 91 | void FileWatcher::removeWatch( WatchID watchid ) { | 91 | |
| 92 | mImpl->removeWatch( watchid ); | 92 | void FileWatcher::removeWatch( WatchID watchid ) { |
| 93 | } | 93 | mImpl->removeWatch( watchid ); |
| 94 | 94 | } | |
| 95 | void FileWatcher::watch() { | 95 | |
| 96 | mImpl->watch(); | 96 | void FileWatcher::watch() { |
| 97 | } | 97 | mImpl->watch(); |
| 98 | 98 | } | |
| 99 | std::list<std::string> FileWatcher::directories() { | 99 | |
| 100 | return mImpl->directories(); | 100 | std::vector<std::string> FileWatcher::directories() { |
| 101 | } | 101 | return mImpl->directories(); |
| 102 | 102 | } | |
| 103 | void FileWatcher::followSymlinks( bool follow ) { | 103 | |
| 104 | mFollowSymlinks = follow; | 104 | void FileWatcher::followSymlinks( bool follow ) { |
| 105 | } | 105 | mFollowSymlinks = follow; |
| 106 | 106 | } | |
| 107 | const bool& FileWatcher::followSymlinks() const { | 107 | |
| 108 | return mFollowSymlinks; | 108 | const bool& FileWatcher::followSymlinks() const { |
| 109 | } | 109 | return mFollowSymlinks; |
| 110 | 110 | } | |
| 111 | void FileWatcher::allowOutOfScopeLinks( bool allow ) { | 111 | |
| 112 | mOutOfScopeLinks = allow; | 112 | void FileWatcher::allowOutOfScopeLinks( bool allow ) { |
| 113 | } | 113 | mOutOfScopeLinks = allow; |
| 114 | 114 | } | |
| 115 | const bool& FileWatcher::allowOutOfScopeLinks() const { | 115 | |
| 116 | return mOutOfScopeLinks; | 116 | const bool& FileWatcher::allowOutOfScopeLinks() const { |
| 117 | } | 117 | return mOutOfScopeLinks; |
| 118 | 118 | } | |
| 119 | } // namespace efsw | 119 | |
| 120 | } // namespace efsw | ||
diff --git a/src/3rdParty/efsw/FileWatcherCWrapper.cpp b/src/3rdParty/efsw/FileWatcherCWrapper.cpp index 5c49a66..8712d6e 100755..100644 --- a/src/3rdParty/efsw/FileWatcherCWrapper.cpp +++ b/src/3rdParty/efsw/FileWatcherCWrapper.cpp | |||
| @@ -28,12 +28,12 @@ class Watcher_CAPI : public efsw::FileWatchListener { | |||
| 28 | */ | 28 | */ |
| 29 | static std::vector<Watcher_CAPI*> g_callbacks; | 29 | static std::vector<Watcher_CAPI*> g_callbacks; |
| 30 | 30 | ||
| 31 | Watcher_CAPI* find_callback( efsw_watcher watcher, efsw_pfn_fileaction_callback fn ) { | 31 | Watcher_CAPI* find_callback( efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param ) { |
| 32 | for ( std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); | 32 | for ( std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); |
| 33 | ++i ) { | 33 | ++i ) { |
| 34 | Watcher_CAPI* callback = *i; | 34 | Watcher_CAPI* callback = *i; |
| 35 | 35 | ||
| 36 | if ( callback->mFn == fn && callback->mWatcher == watcher ) | 36 | if ( callback->mFn == fn && callback->mWatcher == watcher && callback->mParam == param ) |
| 37 | return *i; | 37 | return *i; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| @@ -71,17 +71,35 @@ const char* efsw_getlasterror() { | |||
| 71 | return log_str.c_str(); | 71 | return log_str.c_str(); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | EFSW_API void efsw_clearlasterror() { | ||
| 75 | efsw::Errors::Log::clearLastError(); | ||
| 76 | } | ||
| 77 | |||
| 74 | efsw_watchid efsw_addwatch( efsw_watcher watcher, const char* directory, | 78 | efsw_watchid efsw_addwatch( efsw_watcher watcher, const char* directory, |
| 75 | efsw_pfn_fileaction_callback callback_fn, int recursive, void* param ) { | 79 | efsw_pfn_fileaction_callback callback_fn, int recursive, void* param ) { |
| 76 | Watcher_CAPI* callback = find_callback( watcher, callback_fn ); | 80 | return efsw_addwatch_withoptions( watcher, directory, callback_fn, recursive, 0, 0, param ); |
| 81 | } | ||
| 82 | |||
| 83 | efsw_watchid efsw_addwatch_withoptions(efsw_watcher watcher, const char* directory, | ||
| 84 | efsw_pfn_fileaction_callback callback_fn, int recursive, | ||
| 85 | efsw_watcher_option *options, int options_number, | ||
| 86 | void* param) { | ||
| 87 | Watcher_CAPI* callback = find_callback( watcher, callback_fn, param ); | ||
| 77 | 88 | ||
| 78 | if ( callback == NULL ) { | 89 | if ( callback == NULL ) { |
| 79 | callback = new Watcher_CAPI( watcher, callback_fn, param ); | 90 | callback = new Watcher_CAPI( watcher, callback_fn, param ); |
| 80 | g_callbacks.push_back( callback ); | 91 | g_callbacks.push_back( callback ); |
| 81 | } | 92 | } |
| 82 | 93 | ||
| 94 | std::vector<efsw::WatcherOption> watcher_options{}; | ||
| 95 | for ( int i = 0; i < options_number; i++ ) { | ||
| 96 | efsw_watcher_option* option = &options[i]; | ||
| 97 | watcher_options.emplace_back( efsw::WatcherOption{ | ||
| 98 | static_cast<efsw::Option>(option->option), option->value } ); | ||
| 99 | } | ||
| 100 | |||
| 83 | return ( (efsw::FileWatcher*)watcher ) | 101 | return ( (efsw::FileWatcher*)watcher ) |
| 84 | ->addWatch( std::string( directory ), callback, TOBOOL( recursive ) ); | 102 | ->addWatch( std::string( directory ), callback, TOBOOL( recursive ), watcher_options ); |
| 85 | } | 103 | } |
| 86 | 104 | ||
| 87 | void efsw_removewatch( efsw_watcher watcher, const char* directory ) { | 105 | void efsw_removewatch( efsw_watcher watcher, const char* directory ) { |
diff --git a/src/3rdParty/efsw/FileWatcherFSEvents.cpp b/src/3rdParty/efsw/FileWatcherFSEvents.cpp index bcfdbe6..70ec2b1 100755..100644 --- a/src/3rdParty/efsw/FileWatcherFSEvents.cpp +++ b/src/3rdParty/efsw/FileWatcherFSEvents.cpp | |||
| @@ -41,6 +41,32 @@ bool FileWatcherFSEvents::isGranular() { | |||
| 41 | return getOSXReleaseNumber() >= 11; | 41 | return getOSXReleaseNumber() >= 11; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static std::string convertCFStringToStdString( CFStringRef cfString ) { | ||
| 45 | // Try to get the C string pointer directly | ||
| 46 | const char* cStr = CFStringGetCStringPtr( cfString, kCFStringEncodingUTF8 ); | ||
| 47 | |||
| 48 | if ( cStr ) { | ||
| 49 | // If the pointer is valid, directly return a std::string from it | ||
| 50 | return std::string( cStr ); | ||
| 51 | } else { | ||
| 52 | // If not, manually convert it | ||
| 53 | CFIndex length = CFStringGetLength( cfString ); | ||
| 54 | CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ) + | ||
| 55 | 1; // +1 for null terminator | ||
| 56 | |||
| 57 | char* buffer = new char[maxSize]; | ||
| 58 | |||
| 59 | if ( CFStringGetCString( cfString, buffer, maxSize, kCFStringEncodingUTF8 ) ) { | ||
| 60 | std::string result( buffer ); | ||
| 61 | delete[] buffer; | ||
| 62 | return result; | ||
| 63 | } else { | ||
| 64 | delete[] buffer; | ||
| 65 | return ""; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 44 | void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, void* userData, | 70 | void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, void* userData, |
| 45 | size_t numEvents, void* eventPaths, | 71 | size_t numEvents, void* eventPaths, |
| 46 | const FSEventStreamEventFlags eventFlags[], | 72 | const FSEventStreamEventFlags eventFlags[], |
| @@ -51,8 +77,24 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, | |||
| 51 | events.reserve( numEvents ); | 77 | events.reserve( numEvents ); |
| 52 | 78 | ||
| 53 | for ( size_t i = 0; i < numEvents; i++ ) { | 79 | for ( size_t i = 0; i < numEvents; i++ ) { |
| 54 | events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), (long)eventFlags[i], | 80 | if ( isGranular() ) { |
| 55 | (Uint64)eventIds[i] ) ); | 81 | CFDictionaryRef pathInfoDict = |
| 82 | static_cast<CFDictionaryRef>( CFArrayGetValueAtIndex( (CFArrayRef)eventPaths, i ) ); | ||
| 83 | CFStringRef path = static_cast<CFStringRef>( | ||
| 84 | CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedDataPathKey ) ); | ||
| 85 | CFNumberRef cfInode = static_cast<CFNumberRef>( | ||
| 86 | CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedFileIDKey ) ); | ||
| 87 | |||
| 88 | if ( cfInode ) { | ||
| 89 | unsigned long inode = 0; | ||
| 90 | CFNumberGetValue( cfInode, kCFNumberLongType, &inode ); | ||
| 91 | events.push_back( FSEvent( convertCFStringToStdString( path ), (long)eventFlags[i], | ||
| 92 | (Uint64)eventIds[i], inode ) ); | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), | ||
| 96 | (long)eventFlags[i], (Uint64)eventIds[i] ) ); | ||
| 97 | } | ||
| 56 | } | 98 | } |
| 57 | 99 | ||
| 58 | watcher->handleActions( events ); | 100 | watcher->handleActions( events ); |
| @@ -63,7 +105,7 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef /*streamRef*/, | |||
| 63 | } | 105 | } |
| 64 | 106 | ||
| 65 | FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) : | 107 | FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) : |
| 66 | FileWatcherImpl( parent ), mRunLoopRef( NULL ), mLastWatchID( 0 ), mThread( NULL ) { | 108 | FileWatcherImpl( parent ), mLastWatchID( 0 ) { |
| 67 | mInitOK = true; | 109 | mInitOK = true; |
| 68 | 110 | ||
| 69 | watch(); | 111 | watch(); |
| @@ -72,10 +114,7 @@ FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher* parent ) : | |||
| 72 | FileWatcherFSEvents::~FileWatcherFSEvents() { | 114 | FileWatcherFSEvents::~FileWatcherFSEvents() { |
| 73 | mInitOK = false; | 115 | mInitOK = false; |
| 74 | 116 | ||
| 75 | if ( mRunLoopRef.load() ) | 117 | mWatchCond.notify_all(); |
| 76 | CFRunLoopStop( mRunLoopRef.load() ); | ||
| 77 | |||
| 78 | efSAFE_DELETE( mThread ); | ||
| 79 | 118 | ||
| 80 | WatchMap::iterator iter = mWatches.begin(); | 119 | WatchMap::iterator iter = mWatches.begin(); |
| 81 | 120 | ||
| @@ -84,18 +123,11 @@ FileWatcherFSEvents::~FileWatcherFSEvents() { | |||
| 84 | 123 | ||
| 85 | efSAFE_DELETE( watch ); | 124 | efSAFE_DELETE( watch ); |
| 86 | } | 125 | } |
| 87 | |||
| 88 | mWatches.clear(); | ||
| 89 | } | 126 | } |
| 90 | 127 | ||
| 91 | WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, | 128 | WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 92 | bool recursive ) { | 129 | bool recursive, const std::vector<WatcherOption>& options ) { |
| 93 | /// Wait to the RunLoopRef to be ready | 130 | std::string dir( FileSystem::getRealPath( directory ) ); |
| 94 | while ( NULL == mRunLoopRef.load() ) { | ||
| 95 | System::sleep( 1 ); | ||
| 96 | } | ||
| 97 | |||
| 98 | std::string dir( directory ); | ||
| 99 | 131 | ||
| 100 | FileInfo fi( dir ); | 132 | FileInfo fi( dir ); |
| 101 | 133 | ||
| @@ -135,12 +167,18 @@ WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchLi | |||
| 135 | pWatch->Directory = dir; | 167 | pWatch->Directory = dir; |
| 136 | pWatch->Recursive = recursive; | 168 | pWatch->Recursive = recursive; |
| 137 | pWatch->FWatcher = this; | 169 | pWatch->FWatcher = this; |
| 170 | pWatch->ModifiedFlags = | ||
| 171 | getOptionValue( options, Option::MacModifiedFilter, efswFSEventsModified ); | ||
| 172 | pWatch->SanitizeEvents = getOptionValue( options, Option::MacSanitizeEvents, 0 ) != 0; | ||
| 138 | 173 | ||
| 139 | pWatch->init(); | 174 | pWatch->init(); |
| 140 | 175 | ||
| 141 | Lock lock( mWatchesLock ); | 176 | { |
| 142 | mWatches.insert( std::make_pair( mLastWatchID, pWatch ) ); | 177 | Lock lock( mWatchesLock ); |
| 178 | mWatches.insert( std::make_pair( mLastWatchID, pWatch ) ); | ||
| 179 | } | ||
| 143 | 180 | ||
| 181 | mWatchCond.notify_all(); | ||
| 144 | return pWatch->ID; | 182 | return pWatch->ID; |
| 145 | } | 183 | } |
| 146 | 184 | ||
| @@ -174,50 +212,20 @@ void FileWatcherFSEvents::removeWatch( WatchID watchid ) { | |||
| 174 | efSAFE_DELETE( watch ); | 212 | efSAFE_DELETE( watch ); |
| 175 | } | 213 | } |
| 176 | 214 | ||
| 177 | void FileWatcherFSEvents::watch() { | 215 | void FileWatcherFSEvents::watch() {} |
| 178 | if ( NULL == mThread ) { | ||
| 179 | mThread = new Thread( &FileWatcherFSEvents::run, this ); | ||
| 180 | mThread->launch(); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | void FileWatcherFSEvents::run() { | ||
| 185 | mRunLoopRef = CFRunLoopGetCurrent(); | ||
| 186 | |||
| 187 | while ( mInitOK ) { | ||
| 188 | mNeedInitMutex.lock(); | ||
| 189 | |||
| 190 | if ( !mNeedInit.empty() ) { | ||
| 191 | for ( std::vector<WatcherFSEvents*>::iterator it = mNeedInit.begin(); | ||
| 192 | it != mNeedInit.end(); ++it ) { | ||
| 193 | ( *it )->initAsync(); | ||
| 194 | } | ||
| 195 | |||
| 196 | mNeedInit.clear(); | ||
| 197 | } | ||
| 198 | |||
| 199 | mNeedInitMutex.unlock(); | ||
| 200 | |||
| 201 | if ( mWatches.empty() ) { | ||
| 202 | System::sleep( 100 ); | ||
| 203 | } else { | ||
| 204 | CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut ); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | mRunLoopRef = NULL; | ||
| 209 | } | ||
| 210 | 216 | ||
| 211 | void FileWatcherFSEvents::handleAction( Watcher* /*watch*/, const std::string& /*filename*/, | 217 | void FileWatcherFSEvents::handleAction( Watcher* /*watch*/, const std::string& /*filename*/, |
| 212 | unsigned long /*action*/, std::string /*oldFilename*/ ) { | 218 | unsigned long /*action*/, std::string /*oldFilename*/ ) { |
| 213 | /// Not used | 219 | /// Not used |
| 214 | } | 220 | } |
| 215 | 221 | ||
| 216 | std::list<std::string> FileWatcherFSEvents::directories() { | 222 | std::vector<std::string> FileWatcherFSEvents::directories() { |
| 217 | std::list<std::string> dirs; | 223 | std::vector<std::string> dirs; |
| 218 | 224 | ||
| 219 | Lock lock( mWatchesLock ); | 225 | Lock lock( mWatchesLock ); |
| 220 | 226 | ||
| 227 | dirs.reserve( mWatches.size() ); | ||
| 228 | |||
| 221 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | 229 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { |
| 222 | dirs.push_back( std::string( it->second->Directory ) ); | 230 | dirs.push_back( std::string( it->second->Directory ) ); |
| 223 | } | 231 | } |
diff --git a/src/3rdParty/efsw/FileWatcherFSEvents.hpp b/src/3rdParty/efsw/FileWatcherFSEvents.hpp index 5279847..daa538c 100755..100644 --- a/src/3rdParty/efsw/FileWatcherFSEvents.hpp +++ b/src/3rdParty/efsw/FileWatcherFSEvents.hpp | |||
| @@ -7,33 +7,15 @@ | |||
| 7 | 7 | ||
| 8 | #include <CoreFoundation/CoreFoundation.h> | 8 | #include <CoreFoundation/CoreFoundation.h> |
| 9 | #include <CoreServices/CoreServices.h> | 9 | #include <CoreServices/CoreServices.h> |
| 10 | #include <dispatch/dispatch.h> | ||
| 10 | #include <efsw/WatcherFSEvents.hpp> | 11 | #include <efsw/WatcherFSEvents.hpp> |
| 11 | #include <list> | ||
| 12 | #include <map> | 12 | #include <map> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <condition_variable> | ||
| 15 | #include <mutex> | ||
| 14 | 16 | ||
| 15 | namespace efsw { | 17 | namespace efsw { |
| 16 | 18 | ||
| 17 | /* OSX < 10.7 has no file events */ | ||
| 18 | /* So i declare the events constants */ | ||
| 19 | enum FSEventEvents { | ||
| 20 | efswFSEventStreamCreateFlagFileEvents = 0x00000010, | ||
| 21 | efswFSEventStreamEventFlagItemCreated = 0x00000100, | ||
| 22 | efswFSEventStreamEventFlagItemRemoved = 0x00000200, | ||
| 23 | efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, | ||
| 24 | efswFSEventStreamEventFlagItemRenamed = 0x00000800, | ||
| 25 | efswFSEventStreamEventFlagItemModified = 0x00001000, | ||
| 26 | efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, | ||
| 27 | efswFSEventStreamEventFlagItemChangeOwner = 0x00004000, | ||
| 28 | efswFSEventStreamEventFlagItemXattrMod = 0x00008000, | ||
| 29 | efswFSEventStreamEventFlagItemIsFile = 0x00010000, | ||
| 30 | efswFSEventStreamEventFlagItemIsDir = 0x00020000, | ||
| 31 | efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, | ||
| 32 | efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | | ||
| 33 | efswFSEventStreamEventFlagItemModified | | ||
| 34 | efswFSEventStreamEventFlagItemInodeMetaMod | ||
| 35 | }; | ||
| 36 | |||
| 37 | /// Implementation for Win32 based on ReadDirectoryChangesW. | 19 | /// Implementation for Win32 based on ReadDirectoryChangesW. |
| 38 | /// @class FileWatcherFSEvents | 20 | /// @class FileWatcherFSEvents |
| 39 | class FileWatcherFSEvents : public FileWatcherImpl { | 21 | class FileWatcherFSEvents : public FileWatcherImpl { |
| @@ -52,48 +34,43 @@ class FileWatcherFSEvents : public FileWatcherImpl { | |||
| 52 | 34 | ||
| 53 | /// Add a directory watch | 35 | /// Add a directory watch |
| 54 | /// On error returns WatchID with Error type. | 36 | /// On error returns WatchID with Error type. |
| 55 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 37 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 38 | const std::vector<WatcherOption> &options ) override; | ||
| 56 | 39 | ||
| 57 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 40 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 58 | void removeWatch( const std::string& directory ); | 41 | void removeWatch( const std::string& directory ) override; |
| 59 | 42 | ||
| 60 | /// Remove a directory watch. This is a map lookup O(logn). | 43 | /// Remove a directory watch. This is a map lookup O(logn). |
| 61 | void removeWatch( WatchID watchid ); | 44 | void removeWatch( WatchID watchid ) override; |
| 62 | 45 | ||
| 63 | /// Updates the watcher. Must be called often. | 46 | /// Updates the watcher. Must be called often. |
| 64 | void watch(); | 47 | void watch() override; |
| 65 | 48 | ||
| 66 | /// Handles the action | 49 | /// Handles the action |
| 67 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 50 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 68 | std::string oldFilename = "" ); | 51 | std::string oldFilename = "" ) override; |
| 69 | 52 | ||
| 70 | /// @return Returns a list of the directories that are being watched | 53 | /// @return Returns a list of the directories that are being watched |
| 71 | std::list<std::string> directories(); | 54 | std::vector<std::string> directories() override; |
| 72 | 55 | ||
| 73 | protected: | 56 | protected: |
| 74 | static void FSEventCallback( ConstFSEventStreamRef streamRef, void* userData, size_t numEvents, | 57 | static void FSEventCallback( ConstFSEventStreamRef streamRef, void* userData, size_t numEvents, |
| 75 | void* eventPaths, const FSEventStreamEventFlags eventFlags[], | 58 | void* eventPaths, const FSEventStreamEventFlags eventFlags[], |
| 76 | const FSEventStreamEventId eventIds[] ); | 59 | const FSEventStreamEventId eventIds[] ); |
| 77 | 60 | ||
| 78 | Atomic<CFRunLoopRef> mRunLoopRef; | ||
| 79 | |||
| 80 | /// Vector of WatcherWin32 pointers | 61 | /// Vector of WatcherWin32 pointers |
| 81 | WatchMap mWatches; | 62 | WatchMap mWatches; |
| 82 | 63 | ||
| 83 | /// The last watchid | 64 | /// The last watchid |
| 84 | WatchID mLastWatchID; | 65 | WatchID mLastWatchID; |
| 85 | 66 | ||
| 86 | Thread* mThread; | ||
| 87 | |||
| 88 | Mutex mWatchesLock; | 67 | Mutex mWatchesLock; |
| 89 | 68 | ||
| 90 | bool pathInWatches( const std::string& path ); | 69 | bool pathInWatches( const std::string& path ) override; |
| 91 | 70 | ||
| 92 | std::vector<WatcherFSEvents*> mNeedInit; | 71 | std::mutex mWatchesMutex; |
| 93 | Mutex mNeedInitMutex; | 72 | std::condition_variable mWatchCond; |
| 94 | 73 | ||
| 95 | private: | ||
| 96 | void run(); | ||
| 97 | }; | 74 | }; |
| 98 | 75 | ||
| 99 | } // namespace efsw | 76 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/FileWatcherGeneric.cpp b/src/3rdParty/efsw/FileWatcherGeneric.cpp index 074cff1..3f3c52e 100755..100644 --- a/src/3rdParty/efsw/FileWatcherGeneric.cpp +++ b/src/3rdParty/efsw/FileWatcherGeneric.cpp | |||
| @@ -25,7 +25,7 @@ FileWatcherGeneric::~FileWatcherGeneric() { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, | 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 28 | bool recursive ) { | 28 | bool recursive, const std::vector<WatcherOption>& options ) { |
| 29 | std::string dir( directory ); | 29 | std::string dir( directory ); |
| 30 | 30 | ||
| 31 | FileSystem::dirAddSlashAtEnd( dir ); | 31 | FileSystem::dirAddSlashAtEnd( dir ); |
| @@ -127,11 +127,13 @@ void FileWatcherGeneric::handleAction( Watcher*, const std::string&, unsigned lo | |||
| 127 | /// Not used | 127 | /// Not used |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | std::list<std::string> FileWatcherGeneric::directories() { | 130 | std::vector<std::string> FileWatcherGeneric::directories() { |
| 131 | std::list<std::string> dirs; | 131 | std::vector<std::string> dirs; |
| 132 | 132 | ||
| 133 | Lock lock( mWatchesLock ); | 133 | Lock lock( mWatchesLock ); |
| 134 | 134 | ||
| 135 | dirs.reserve( mWatches.size() ); | ||
| 136 | |||
| 135 | WatchList::iterator it = mWatches.begin(); | 137 | WatchList::iterator it = mWatches.begin(); |
| 136 | 138 | ||
| 137 | for ( ; it != mWatches.end(); ++it ) { | 139 | for ( ; it != mWatches.end(); ++it ) { |
diff --git a/src/3rdParty/efsw/FileWatcherGeneric.hpp b/src/3rdParty/efsw/FileWatcherGeneric.hpp index 4cb0b67..47f7e04 100755..100644 --- a/src/3rdParty/efsw/FileWatcherGeneric.hpp +++ b/src/3rdParty/efsw/FileWatcherGeneric.hpp | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | #include <efsw/DirWatcherGeneric.hpp> | 4 | #include <efsw/DirWatcherGeneric.hpp> |
| 5 | #include <efsw/FileWatcherImpl.hpp> | 5 | #include <efsw/FileWatcherImpl.hpp> |
| 6 | #include <efsw/WatcherGeneric.hpp> | 6 | #include <efsw/WatcherGeneric.hpp> |
| 7 | #include <list> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | namespace efsw { | 9 | namespace efsw { |
| 10 | 10 | ||
| @@ -12,7 +12,7 @@ namespace efsw { | |||
| 12 | /// @class FileWatcherGeneric | 12 | /// @class FileWatcherGeneric |
| 13 | class FileWatcherGeneric : public FileWatcherImpl { | 13 | class FileWatcherGeneric : public FileWatcherImpl { |
| 14 | public: | 14 | public: |
| 15 | typedef std::list<WatcherGeneric*> WatchList; | 15 | typedef std::vector<WatcherGeneric*> WatchList; |
| 16 | 16 | ||
| 17 | FileWatcherGeneric( FileWatcher* parent ); | 17 | FileWatcherGeneric( FileWatcher* parent ); |
| 18 | 18 | ||
| @@ -20,23 +20,24 @@ class FileWatcherGeneric : public FileWatcherImpl { | |||
| 20 | 20 | ||
| 21 | /// Add a directory watch | 21 | /// Add a directory watch |
| 22 | /// On error returns WatchID with Error type. | 22 | /// On error returns WatchID with Error type. |
| 23 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 23 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 24 | const std::vector<WatcherOption> &options ) override; | ||
| 24 | 25 | ||
| 25 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 26 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 26 | void removeWatch( const std::string& directory ); | 27 | void removeWatch( const std::string& directory ) override; |
| 27 | 28 | ||
| 28 | /// Remove a directory watch. This is a map lookup O(logn). | 29 | /// Remove a directory watch. This is a map lookup O(logn). |
| 29 | void removeWatch( WatchID watchid ); | 30 | void removeWatch( WatchID watchid ) override; |
| 30 | 31 | ||
| 31 | /// Updates the watcher. Must be called often. | 32 | /// Updates the watcher. Must be called often. |
| 32 | void watch(); | 33 | void watch() override; |
| 33 | 34 | ||
| 34 | /// Handles the action | 35 | /// Handles the action |
| 35 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 36 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 36 | std::string oldFilename = "" ); | 37 | std::string oldFilename = "" ) override; |
| 37 | 38 | ||
| 38 | /// @return Returns a list of the directories that are being watched | 39 | /// @return Returns a list of the directories that are being watched |
| 39 | std::list<std::string> directories(); | 40 | std::vector<std::string> directories() override; |
| 40 | 41 | ||
| 41 | protected: | 42 | protected: |
| 42 | Thread* mThread; | 43 | Thread* mThread; |
| @@ -49,7 +50,7 @@ class FileWatcherGeneric : public FileWatcherImpl { | |||
| 49 | 50 | ||
| 50 | Mutex mWatchesLock; | 51 | Mutex mWatchesLock; |
| 51 | 52 | ||
| 52 | bool pathInWatches( const std::string& path ); | 53 | bool pathInWatches( const std::string& path ) override; |
| 53 | 54 | ||
| 54 | private: | 55 | private: |
| 55 | void run(); | 56 | void run(); |
diff --git a/src/3rdParty/efsw/FileWatcherImpl.cpp b/src/3rdParty/efsw/FileWatcherImpl.cpp index f6b86a5..bf69a45 100755..100644 --- a/src/3rdParty/efsw/FileWatcherImpl.cpp +++ b/src/3rdParty/efsw/FileWatcherImpl.cpp | |||
| @@ -1,23 +1,34 @@ | |||
| 1 | #include <efsw/FileWatcherImpl.hpp> | 1 | #include <efsw/FileWatcherImpl.hpp> |
| 2 | #include <efsw/String.hpp> | 2 | #include <efsw/String.hpp> |
| 3 | #include <efsw/System.hpp> | 3 | #include <efsw/System.hpp> |
| 4 | 4 | ||
| 5 | namespace efsw { | 5 | namespace efsw { |
| 6 | 6 | ||
| 7 | FileWatcherImpl::FileWatcherImpl( FileWatcher* parent ) : | 7 | FileWatcherImpl::FileWatcherImpl( FileWatcher* parent ) : |
| 8 | mFileWatcher( parent ), mInitOK( false ), mIsGeneric( false ) { | 8 | mFileWatcher( parent ), mInitOK( false ), mIsGeneric( false ) { |
| 9 | System::maxFD(); | 9 | System::maxFD(); |
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | FileWatcherImpl::~FileWatcherImpl() {} | 12 | FileWatcherImpl::~FileWatcherImpl() {} |
| 13 | 13 | ||
| 14 | bool FileWatcherImpl::initOK() { | 14 | bool FileWatcherImpl::initOK() { |
| 15 | return static_cast<bool>( mInitOK ); | 15 | return static_cast<bool>( mInitOK ); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) { | 18 | bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link ) { |
| 19 | return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || | 19 | return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || |
| 20 | -1 != String::strStartsWith( curPath, link ); | 20 | -1 != String::strStartsWith( curPath, link ); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | } // namespace efsw | 23 | int FileWatcherImpl::getOptionValue( const std::vector<WatcherOption>& options, Option option, |
| 24 | int defaultValue ) { | ||
| 25 | for ( size_t i = 0; i < options.size(); i++ ) { | ||
| 26 | if ( options[i].mOption == option ) { | ||
| 27 | return options[i].mValue; | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | return defaultValue; | ||
| 32 | } | ||
| 33 | |||
| 34 | } // namespace efsw | ||
diff --git a/src/3rdParty/efsw/FileWatcherImpl.hpp b/src/3rdParty/efsw/FileWatcherImpl.hpp index ea1beb8..a6ec472 100755..100644 --- a/src/3rdParty/efsw/FileWatcherImpl.hpp +++ b/src/3rdParty/efsw/FileWatcherImpl.hpp | |||
| @@ -1,57 +1,64 @@ | |||
| 1 | #ifndef EFSW_FILEWATCHERIMPL_HPP | 1 | #ifndef EFSW_FILEWATCHERIMPL_HPP |
| 2 | #define EFSW_FILEWATCHERIMPL_HPP | 2 | #define EFSW_FILEWATCHERIMPL_HPP |
| 3 | 3 | ||
| 4 | #include <efsw/Atomic.hpp> | 4 | #include <efsw/Atomic.hpp> |
| 5 | #include <efsw/Mutex.hpp> | 5 | #include <efsw/Mutex.hpp> |
| 6 | #include <efsw/Thread.hpp> | 6 | #include <efsw/Thread.hpp> |
| 7 | #include <efsw/Watcher.hpp> | 7 | #include <efsw/Watcher.hpp> |
| 8 | #include <efsw/base.hpp> | 8 | #include <efsw/base.hpp> |
| 9 | #include <efsw/efsw.hpp> | 9 | #include <efsw/efsw.hpp> |
| 10 | 10 | ||
| 11 | namespace efsw { | 11 | namespace efsw { |
| 12 | 12 | ||
| 13 | class FileWatcherImpl { | 13 | class FileWatcherImpl { |
| 14 | public: | 14 | public: |
| 15 | FileWatcherImpl( FileWatcher* parent ); | 15 | FileWatcherImpl( FileWatcher* parent ); |
| 16 | 16 | ||
| 17 | virtual ~FileWatcherImpl(); | 17 | virtual ~FileWatcherImpl(); |
| 18 | 18 | ||
| 19 | /// Add a directory watch | 19 | /// Add a directory watch |
| 20 | /// On error returns WatchID with Error type. | 20 | /// On error returns WatchID with Error type. |
| 21 | virtual WatchID addWatch( const std::string& directory, FileWatchListener* watcher, | 21 | virtual WatchID addWatch( const std::string& directory, FileWatchListener* watcher, |
| 22 | bool recursive ) = 0; | 22 | bool recursive, const std::vector<WatcherOption>& options = {} ) = 0; |
| 23 | 23 | ||
| 24 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 24 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 25 | virtual void removeWatch( const std::string& directory ) = 0; | 25 | virtual void removeWatch( const std::string& directory ) = 0; |
| 26 | 26 | ||
| 27 | /// Remove a directory watch. This is a map lookup O(logn). | 27 | /// Remove a directory watch. This is a map lookup O(logn). |
| 28 | virtual void removeWatch( WatchID watchid ) = 0; | 28 | virtual void removeWatch( WatchID watchid ) = 0; |
| 29 | 29 | ||
| 30 | /// Updates the watcher. Must be called often. | 30 | /// Updates the watcher. Must be called often. |
| 31 | virtual void watch() = 0; | 31 | virtual void watch() = 0; |
| 32 | 32 | ||
| 33 | /// Handles the action | 33 | /// Handles the action |
| 34 | virtual void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 34 | virtual void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 35 | std::string oldFilename = "" ) = 0; | 35 | std::string oldFilename = "" ) = 0; |
| 36 | 36 | ||
| 37 | /// @return Returns a list of the directories that are being watched | 37 | /// @return Returns a list of the directories that are being watched |
| 38 | virtual std::list<std::string> directories() = 0; | 38 | virtual std::vector<std::string> directories() = 0; |
| 39 | 39 | ||
| 40 | /// @return true if the backend init successfully | 40 | /// @return true if the backend init successfully |
| 41 | virtual bool initOK(); | 41 | virtual bool initOK(); |
| 42 | 42 | ||
| 43 | /// @return If the link is allowed according to the current path and the state of out scope | 43 | /// @return If the link is allowed according to the current path and the state of out scope |
| 44 | /// links | 44 | /// links |
| 45 | virtual bool linkAllowed( const std::string& curPath, const std::string& link ); | 45 | virtual bool linkAllowed( const std::string& curPath, const std::string& link ); |
| 46 | 46 | ||
| 47 | /// Search if a directory already exists in the watches | 47 | /// Search if a directory already exists in the watches |
| 48 | virtual bool pathInWatches( const std::string& path ) = 0; | 48 | virtual bool pathInWatches( const std::string& path ) = 0; |
| 49 | 49 | ||
| 50 | FileWatcher* mFileWatcher; | 50 | protected: |
| 51 | Atomic<bool> mInitOK; | 51 | friend class FileWatcher; |
| 52 | bool mIsGeneric; | 52 | friend class DirWatcherGeneric; |
| 53 | }; | 53 | |
| 54 | 54 | FileWatcher* mFileWatcher; | |
| 55 | } // namespace efsw | 55 | Atomic<bool> mInitOK; |
| 56 | 56 | bool mIsGeneric; | |
| 57 | #endif | 57 | |
| 58 | int getOptionValue( const std::vector<WatcherOption>& options, Option option, | ||
| 59 | int defaultValue ); | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace efsw | ||
| 63 | |||
| 64 | #endif | ||
diff --git a/src/3rdParty/efsw/FileWatcherInotify.cpp b/src/3rdParty/efsw/FileWatcherInotify.cpp index e0da76b..1ec3d48 100755..100644 --- a/src/3rdParty/efsw/FileWatcherInotify.cpp +++ b/src/3rdParty/efsw/FileWatcherInotify.cpp | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #include <algorithm> | ||
| 1 | #include <efsw/FileWatcherInotify.hpp> | 2 | #include <efsw/FileWatcherInotify.hpp> |
| 2 | 3 | ||
| 3 | #if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY | 4 | #if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY |
| @@ -26,7 +27,7 @@ | |||
| 26 | namespace efsw { | 27 | namespace efsw { |
| 27 | 28 | ||
| 28 | FileWatcherInotify::FileWatcherInotify( FileWatcher* parent ) : | 29 | FileWatcherInotify::FileWatcherInotify( FileWatcher* parent ) : |
| 29 | FileWatcherImpl( parent ), mFD( -1 ), mThread( NULL ) { | 30 | FileWatcherImpl( parent ), mFD( -1 ), mThread( NULL ), mIsTakingAction( false ) { |
| 30 | mFD = inotify_init(); | 31 | mFD = inotify_init(); |
| 31 | 32 | ||
| 32 | if ( mFD < 0 ) { | 33 | if ( mFD < 0 ) { |
| @@ -38,13 +39,20 @@ FileWatcherInotify::FileWatcherInotify( FileWatcher* parent ) : | |||
| 38 | 39 | ||
| 39 | FileWatcherInotify::~FileWatcherInotify() { | 40 | FileWatcherInotify::~FileWatcherInotify() { |
| 40 | mInitOK = false; | 41 | mInitOK = false; |
| 41 | 42 | // There is deadlock when release FileWatcherInotify instance since its handAction | |
| 43 | // function is still running and hangs in requiring lock without init lock captured. | ||
| 44 | while ( mIsTakingAction ) { | ||
| 45 | // It'd use condition-wait instead of sleep. Actually efsw has no such | ||
| 46 | // implementation so we just skip and sleep while for that to avoid deadlock. | ||
| 47 | usleep( 1000 ); | ||
| 48 | }; | ||
| 42 | Lock initLock( mInitLock ); | 49 | Lock initLock( mInitLock ); |
| 43 | 50 | ||
| 44 | efSAFE_DELETE( mThread ); | 51 | efSAFE_DELETE( mThread ); |
| 45 | 52 | ||
| 46 | Lock l( mWatchesLock ); | 53 | Lock l( mWatchesLock ); |
| 47 | Lock l2( mRealWatchesLock ); | 54 | Lock l2( mRealWatchesLock ); |
| 55 | |||
| 48 | WatchMap::iterator iter = mWatches.begin(); | 56 | WatchMap::iterator iter = mWatches.begin(); |
| 49 | WatchMap::iterator end = mWatches.end(); | 57 | WatchMap::iterator end = mWatches.end(); |
| 50 | 58 | ||
| @@ -61,15 +69,17 @@ FileWatcherInotify::~FileWatcherInotify() { | |||
| 61 | } | 69 | } |
| 62 | 70 | ||
| 63 | WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, | 71 | WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 64 | bool recursive ) { | 72 | bool recursive, const std::vector<WatcherOption>& options ) { |
| 65 | if ( !mInitOK ) | 73 | if ( !mInitOK ) |
| 66 | return Errors::Log::createLastError( Errors::Unspecified, directory ); | 74 | return Errors::Log::createLastError( Errors::Unspecified, directory ); |
| 67 | Lock initLock( mInitLock ); | 75 | Lock initLock( mInitLock ); |
| 68 | return addWatch( directory, watcher, recursive, NULL ); | 76 | bool syntheticEvents = getOptionValue( options, Options::LinuxProduceSyntheticEvents, 0 ) != 0; |
| 77 | return addWatch( directory, watcher, recursive, syntheticEvents, NULL ); | ||
| 69 | } | 78 | } |
| 70 | 79 | ||
| 71 | WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, | 80 | WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 72 | bool recursive, WatcherInotify* parent ) { | 81 | bool recursive, bool syntheticEvents, |
| 82 | WatcherInotify* parent, bool fromInternalEvent ) { | ||
| 73 | std::string dir( directory ); | 83 | std::string dir( directory ); |
| 74 | 84 | ||
| 75 | FileSystem::dirAddSlashAtEnd( dir ); | 85 | FileSystem::dirAddSlashAtEnd( dir ); |
| @@ -133,6 +143,7 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis | |||
| 133 | { | 143 | { |
| 134 | Lock lock( mWatchesLock ); | 144 | Lock lock( mWatchesLock ); |
| 135 | mWatches.insert( std::make_pair( wd, pWatch ) ); | 145 | mWatches.insert( std::make_pair( wd, pWatch ) ); |
| 146 | mWatchesRef[pWatch->Directory] = wd; | ||
| 136 | } | 147 | } |
| 137 | 148 | ||
| 138 | if ( NULL == pWatch->Parent ) { | 149 | if ( NULL == pWatch->Parent ) { |
| @@ -151,7 +162,17 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis | |||
| 151 | const FileInfo& cfi = it->second; | 162 | const FileInfo& cfi = it->second; |
| 152 | 163 | ||
| 153 | if ( cfi.isDirectory() && cfi.isReadable() ) { | 164 | if ( cfi.isDirectory() && cfi.isReadable() ) { |
| 154 | addWatch( cfi.Filepath, watcher, recursive, pWatch ); | 165 | addWatch( cfi.Filepath, watcher, recursive, syntheticEvents, pWatch ); |
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | if ( fromInternalEvent && parent != NULL && syntheticEvents ) { | ||
| 170 | for ( const auto& file : files ) { | ||
| 171 | if ( file.second.isRegularFile() ) { | ||
| 172 | pWatch->Listener->handleFileAction( | ||
| 173 | pWatch->ID, pWatch->Directory, | ||
| 174 | FileSystem::fileNameFromPath( file.second.Filepath ), Actions::Add ); | ||
| 175 | } | ||
| 155 | } | 176 | } |
| 156 | } | 177 | } |
| 157 | } | 178 | } |
| @@ -161,6 +182,8 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis | |||
| 161 | 182 | ||
| 162 | void FileWatcherInotify::removeWatchLocked( WatchID watchid ) { | 183 | void FileWatcherInotify::removeWatchLocked( WatchID watchid ) { |
| 163 | WatchMap::iterator iter = mWatches.find( watchid ); | 184 | WatchMap::iterator iter = mWatches.find( watchid ); |
| 185 | if ( iter == mWatches.end() ) | ||
| 186 | return; | ||
| 164 | 187 | ||
| 165 | WatcherInotify* watch = iter->second; | 188 | WatcherInotify* watch = iter->second; |
| 166 | 189 | ||
| @@ -173,22 +196,21 @@ void FileWatcherInotify::removeWatchLocked( WatchID watchid ) { | |||
| 173 | } | 196 | } |
| 174 | } | 197 | } |
| 175 | 198 | ||
| 176 | if ( watch->Recursive ) { | 199 | if ( watch->Recursive && NULL == watch->Parent ) { |
| 177 | WatchMap::iterator it = mWatches.begin(); | 200 | WatchMap::iterator it = mWatches.begin(); |
| 178 | std::list<WatchID> eraseWatches; | 201 | std::vector<WatchID> eraseWatches; |
| 179 | 202 | ||
| 180 | for ( ; it != mWatches.end(); ++it ) { | 203 | for ( ; it != mWatches.end(); ++it ) |
| 181 | if ( it->second != watch && it->second->inParentTree( watch ) ) { | 204 | if ( it->second != watch && it->second->inParentTree( watch ) ) |
| 182 | eraseWatches.push_back( it->second->InotifyID ); | 205 | eraseWatches.push_back( it->second->InotifyID ); |
| 183 | } | ||
| 184 | } | ||
| 185 | 206 | ||
| 186 | for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); | 207 | for ( std::vector<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); |
| 187 | ++eit ) { | 208 | ++eit ) { |
| 188 | removeWatch( *eit ); | 209 | removeWatch( *eit ); |
| 189 | } | 210 | } |
| 190 | } | 211 | } |
| 191 | 212 | ||
| 213 | mWatchesRef.erase( watch->Directory ); | ||
| 192 | mWatches.erase( iter ); | 214 | mWatches.erase( iter ); |
| 193 | 215 | ||
| 194 | if ( NULL == watch->Parent ) { | 216 | if ( NULL == watch->Parent ) { |
| @@ -217,52 +239,11 @@ void FileWatcherInotify::removeWatch( const std::string& directory ) { | |||
| 217 | Lock lock( mWatchesLock ); | 239 | Lock lock( mWatchesLock ); |
| 218 | Lock l( mRealWatchesLock ); | 240 | Lock l( mRealWatchesLock ); |
| 219 | 241 | ||
| 220 | WatchMap::iterator iter = mWatches.begin(); | 242 | std::unordered_map<std::string, WatchID>::iterator ref = mWatchesRef.find( directory ); |
| 221 | 243 | if ( ref == mWatchesRef.end() ) | |
| 222 | for ( ; iter != mWatches.end(); ++iter ) { | 244 | return; |
| 223 | if ( directory == iter->second->Directory ) { | ||
| 224 | WatcherInotify* watch = iter->second; | ||
| 225 | |||
| 226 | if ( watch->Recursive ) { | ||
| 227 | WatchMap::iterator it = mWatches.begin(); | ||
| 228 | std::list<WatchID> eraseWatches; | ||
| 229 | |||
| 230 | for ( ; it != mWatches.end(); ++it ) { | ||
| 231 | if ( it->second->inParentTree( watch ) ) { | ||
| 232 | eraseWatches.push_back( it->second->InotifyID ); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); | ||
| 237 | eit != eraseWatches.end(); ++eit ) { | ||
| 238 | removeWatchLocked( *eit ); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | mWatches.erase( iter ); | ||
| 243 | |||
| 244 | if ( NULL == watch->Parent ) { | ||
| 245 | WatchMap::iterator eraseit = mRealWatches.find( watch->InotifyID ); | ||
| 246 | |||
| 247 | if ( eraseit != mRealWatches.end() ) { | ||
| 248 | mRealWatches.erase( eraseit ); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | int err = inotify_rm_watch( mFD, watch->InotifyID ); | ||
| 253 | |||
| 254 | if ( err < 0 ) { | ||
| 255 | efDEBUG( "Error removing watch %d: %s\n", watch->InotifyID, strerror( errno ) ); | ||
| 256 | } else { | ||
| 257 | efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), | ||
| 258 | watch->InotifyID ); | ||
| 259 | } | ||
| 260 | |||
| 261 | efSAFE_DELETE( watch ); | ||
| 262 | 245 | ||
| 263 | break; | 246 | removeWatchLocked( ref->second ); |
| 264 | } | ||
| 265 | } | ||
| 266 | } | 247 | } |
| 267 | 248 | ||
| 268 | void FileWatcherInotify::removeWatch( WatchID watchid ) { | 249 | void FileWatcherInotify::removeWatch( WatchID watchid ) { |
| @@ -270,13 +251,6 @@ void FileWatcherInotify::removeWatch( WatchID watchid ) { | |||
| 270 | return; | 251 | return; |
| 271 | Lock initLock( mInitLock ); | 252 | Lock initLock( mInitLock ); |
| 272 | Lock lock( mWatchesLock ); | 253 | Lock lock( mWatchesLock ); |
| 273 | |||
| 274 | WatchMap::iterator iter = mWatches.find( watchid ); | ||
| 275 | |||
| 276 | if ( iter == mWatches.end() ) { | ||
| 277 | return; | ||
| 278 | } | ||
| 279 | |||
| 280 | removeWatchLocked( watchid ); | 254 | removeWatchLocked( watchid ); |
| 281 | } | 255 | } |
| 282 | 256 | ||
| @@ -295,10 +269,8 @@ Watcher* FileWatcherInotify::watcherContainsDirectory( std::string dir ) { | |||
| 295 | 269 | ||
| 296 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | 270 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { |
| 297 | Watcher* watcher = it->second; | 271 | Watcher* watcher = it->second; |
| 298 | 272 | if ( watcher->Directory == watcherPath ) | |
| 299 | if ( watcher->Directory == watcherPath ) { | ||
| 300 | return watcher; | 273 | return watcher; |
| 301 | } | ||
| 302 | } | 274 | } |
| 303 | 275 | ||
| 304 | return NULL; | 276 | return NULL; |
| @@ -422,7 +394,7 @@ void FileWatcherInotify::run() { | |||
| 422 | const std::string& oldFileName = ( *it ).second; | 394 | const std::string& oldFileName = ( *it ).second; |
| 423 | 395 | ||
| 424 | /// Check if the file move was a folder already being watched | 396 | /// Check if the file move was a folder already being watched |
| 425 | std::list<Watcher*> eraseWatches; | 397 | std::vector<Watcher*> eraseWatches; |
| 426 | 398 | ||
| 427 | { | 399 | { |
| 428 | Lock lock( mWatchesLock ); | 400 | Lock lock( mWatchesLock ); |
| @@ -439,12 +411,15 @@ void FileWatcherInotify::run() { | |||
| 439 | } | 411 | } |
| 440 | 412 | ||
| 441 | /// Remove invalid watches | 413 | /// Remove invalid watches |
| 442 | eraseWatches.sort(); | 414 | std::stable_sort( eraseWatches.begin(), eraseWatches.end(), |
| 415 | []( const Watcher* left, const Watcher* right ) { | ||
| 416 | return left->Directory < right->Directory; | ||
| 417 | } ); | ||
| 443 | 418 | ||
| 444 | if ( eraseWatches.empty() ) { | 419 | if ( eraseWatches.empty() ) { |
| 445 | handleAction( watch, oldFileName, IN_DELETE ); | 420 | handleAction( watch, oldFileName, IN_DELETE ); |
| 446 | } else { | 421 | } else { |
| 447 | for ( std::list<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); | 422 | for ( std::vector<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); |
| 448 | eit != eraseWatches.rend(); ++eit ) { | 423 | eit != eraseWatches.rend(); ++eit ) { |
| 449 | Watcher* rmWatch = *eit; | 424 | Watcher* rmWatch = *eit; |
| 450 | 425 | ||
| @@ -485,8 +460,9 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) | |||
| 485 | } | 460 | } |
| 486 | 461 | ||
| 487 | if ( !found ) { | 462 | if ( !found ) { |
| 488 | addWatch( fpath, watch->Listener, watch->Recursive, | 463 | WatcherInotify* iWatch = static_cast<WatcherInotify*>( watch ); |
| 489 | static_cast<WatcherInotify*>( watch ) ); | 464 | addWatch( fpath, watch->Listener, watch->Recursive, iWatch->syntheticEvents, |
| 465 | static_cast<WatcherInotify*>( watch ), true ); | ||
| 490 | } | 466 | } |
| 491 | } | 467 | } |
| 492 | } | 468 | } |
| @@ -496,7 +472,7 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena | |||
| 496 | if ( !watch || !watch->Listener || !mInitOK ) { | 472 | if ( !watch || !watch->Listener || !mInitOK ) { |
| 497 | return; | 473 | return; |
| 498 | } | 474 | } |
| 499 | 475 | mIsTakingAction = true; | |
| 500 | Lock initLock( mInitLock ); | 476 | Lock initLock( mInitLock ); |
| 501 | 477 | ||
| 502 | std::string fpath( watch->Directory + filename ); | 478 | std::string fpath( watch->Directory + filename ); |
| @@ -563,18 +539,20 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena | |||
| 563 | } | 539 | } |
| 564 | } | 540 | } |
| 565 | } | 541 | } |
| 542 | mIsTakingAction = false; | ||
| 566 | } | 543 | } |
| 567 | 544 | ||
| 568 | std::list<std::string> FileWatcherInotify::directories() { | 545 | std::vector<std::string> FileWatcherInotify::directories() { |
| 569 | std::list<std::string> dirs; | 546 | std::vector<std::string> dirs; |
| 570 | 547 | ||
| 571 | Lock l( mRealWatchesLock ); | 548 | Lock l( mRealWatchesLock ); |
| 572 | 549 | ||
| 550 | dirs.reserve( mRealWatches.size() ); | ||
| 551 | |||
| 573 | WatchMap::iterator it = mRealWatches.begin(); | 552 | WatchMap::iterator it = mRealWatches.begin(); |
| 574 | 553 | ||
| 575 | for ( ; it != mRealWatches.end(); ++it ) { | 554 | for ( ; it != mRealWatches.end(); ++it ) |
| 576 | dirs.push_back( it->second->Directory ); | 555 | dirs.push_back( it->second->Directory ); |
| 577 | } | ||
| 578 | 556 | ||
| 579 | return dirs; | 557 | return dirs; |
| 580 | } | 558 | } |
| @@ -585,11 +563,9 @@ bool FileWatcherInotify::pathInWatches( const std::string& path ) { | |||
| 585 | /// Search in the real watches, since it must allow adding a watch already watched as a subdir | 563 | /// Search in the real watches, since it must allow adding a watch already watched as a subdir |
| 586 | WatchMap::iterator it = mRealWatches.begin(); | 564 | WatchMap::iterator it = mRealWatches.begin(); |
| 587 | 565 | ||
| 588 | for ( ; it != mRealWatches.end(); ++it ) { | 566 | for ( ; it != mRealWatches.end(); ++it ) |
| 589 | if ( it->second->Directory == path ) { | 567 | if ( it->second->Directory == path ) |
| 590 | return true; | 568 | return true; |
| 591 | } | ||
| 592 | } | ||
| 593 | 569 | ||
| 594 | return false; | 570 | return false; |
| 595 | } | 571 | } |
diff --git a/src/3rdParty/efsw/FileWatcherInotify.hpp b/src/3rdParty/efsw/FileWatcherInotify.hpp index dc922ac..26d2c0b 100755..100644 --- a/src/3rdParty/efsw/FileWatcherInotify.hpp +++ b/src/3rdParty/efsw/FileWatcherInotify.hpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include <efsw/WatcherInotify.hpp> | 8 | #include <efsw/WatcherInotify.hpp> |
| 9 | #include <map> | 9 | #include <map> |
| 10 | #include <unordered_map> | ||
| 10 | #include <vector> | 11 | #include <vector> |
| 11 | 12 | ||
| 12 | namespace efsw { | 13 | namespace efsw { |
| @@ -24,23 +25,24 @@ class FileWatcherInotify : public FileWatcherImpl { | |||
| 24 | 25 | ||
| 25 | /// Add a directory watch | 26 | /// Add a directory watch |
| 26 | /// On error returns WatchID with Error type. | 27 | /// On error returns WatchID with Error type. |
| 27 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 28 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 29 | const std::vector<WatcherOption>& options ) override; | ||
| 28 | 30 | ||
| 29 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 31 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 30 | void removeWatch( const std::string& directory ); | 32 | void removeWatch( const std::string& directory ) override; |
| 31 | 33 | ||
| 32 | /// Remove a directory watch. This is a map lookup O(logn). | 34 | /// Remove a directory watch. This is a map lookup O(logn). |
| 33 | void removeWatch( WatchID watchid ); | 35 | void removeWatch( WatchID watchid ) override; |
| 34 | 36 | ||
| 35 | /// Updates the watcher. Must be called often. | 37 | /// Updates the watcher. Must be called often. |
| 36 | void watch(); | 38 | void watch() override; |
| 37 | 39 | ||
| 38 | /// Handles the action | 40 | /// Handles the action |
| 39 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 41 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 40 | std::string oldFilename = "" ); | 42 | std::string oldFilename = "" ) override; |
| 41 | 43 | ||
| 42 | /// @return Returns a list of the directories that are being watched | 44 | /// @return Returns a list of the directories that are being watched |
| 43 | std::list<std::string> directories(); | 45 | std::vector<std::string> directories() override; |
| 44 | 46 | ||
| 45 | protected: | 47 | protected: |
| 46 | /// Map of WatchID to WatchStruct pointers | 48 | /// Map of WatchID to WatchStruct pointers |
| @@ -49,6 +51,8 @@ class FileWatcherInotify : public FileWatcherImpl { | |||
| 49 | /// User added watches | 51 | /// User added watches |
| 50 | WatchMap mRealWatches; | 52 | WatchMap mRealWatches; |
| 51 | 53 | ||
| 54 | std::unordered_map<std::string, WatchID> mWatchesRef; | ||
| 55 | |||
| 52 | /// inotify file descriptor | 56 | /// inotify file descriptor |
| 53 | int mFD; | 57 | int mFD; |
| 54 | 58 | ||
| @@ -57,12 +61,14 @@ class FileWatcherInotify : public FileWatcherImpl { | |||
| 57 | Mutex mWatchesLock; | 61 | Mutex mWatchesLock; |
| 58 | Mutex mRealWatchesLock; | 62 | Mutex mRealWatchesLock; |
| 59 | Mutex mInitLock; | 63 | Mutex mInitLock; |
| 64 | bool mIsTakingAction; | ||
| 60 | std::vector<std::pair<WatcherInotify*, std::string>> mMovedOutsideWatches; | 65 | std::vector<std::pair<WatcherInotify*, std::string>> mMovedOutsideWatches; |
| 61 | 66 | ||
| 62 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, | 67 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 63 | WatcherInotify* parent = NULL ); | 68 | bool syntheticEvents, WatcherInotify* parent = NULL, |
| 69 | bool fromInternalEvent = false ); | ||
| 64 | 70 | ||
| 65 | bool pathInWatches( const std::string& path ); | 71 | bool pathInWatches( const std::string& path ) override; |
| 66 | 72 | ||
| 67 | private: | 73 | private: |
| 68 | void run(); | 74 | void run(); |
diff --git a/src/3rdParty/efsw/FileWatcherKqueue.cpp b/src/3rdParty/efsw/FileWatcherKqueue.cpp index 38ffad9..ad03036 100755..100644 --- a/src/3rdParty/efsw/FileWatcherKqueue.cpp +++ b/src/3rdParty/efsw/FileWatcherKqueue.cpp | |||
| @@ -45,7 +45,7 @@ FileWatcherKqueue::~FileWatcherKqueue() { | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | WatchID FileWatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, | 47 | WatchID FileWatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 48 | bool recursive ) { | 48 | bool recursive, const std::vector<WatcherOption>& /*options*/ ) { |
| 49 | static bool s_ug = false; | 49 | static bool s_ug = false; |
| 50 | 50 | ||
| 51 | std::string dir( directory ); | 51 | std::string dir( directory ); |
| @@ -184,11 +184,13 @@ void FileWatcherKqueue::run() { | |||
| 184 | void FileWatcherKqueue::handleAction( Watcher* /*watch*/, const std::string& /*filename*/, | 184 | void FileWatcherKqueue::handleAction( Watcher* /*watch*/, const std::string& /*filename*/, |
| 185 | unsigned long /*action*/, std::string /*oldFilename*/ ) {} | 185 | unsigned long /*action*/, std::string /*oldFilename*/ ) {} |
| 186 | 186 | ||
| 187 | std::list<std::string> FileWatcherKqueue::directories() { | 187 | std::vector<std::string> FileWatcherKqueue::directories() { |
| 188 | std::list<std::string> dirs; | 188 | std::vector<std::string> dirs; |
| 189 | 189 | ||
| 190 | Lock lock( mWatchesLock ); | 190 | Lock lock( mWatchesLock ); |
| 191 | 191 | ||
| 192 | dirs.reserve( mWatches.size() ); | ||
| 193 | |||
| 192 | WatchMap::iterator it = mWatches.begin(); | 194 | WatchMap::iterator it = mWatches.begin(); |
| 193 | 195 | ||
| 194 | for ( ; it != mWatches.end(); ++it ) { | 196 | for ( ; it != mWatches.end(); ++it ) { |
diff --git a/src/3rdParty/efsw/FileWatcherKqueue.hpp b/src/3rdParty/efsw/FileWatcherKqueue.hpp index 1bf3755..ff5327b 100755..100644 --- a/src/3rdParty/efsw/FileWatcherKqueue.hpp +++ b/src/3rdParty/efsw/FileWatcherKqueue.hpp | |||
| @@ -21,23 +21,24 @@ class FileWatcherKqueue : public FileWatcherImpl { | |||
| 21 | 21 | ||
| 22 | /// Add a directory watch | 22 | /// Add a directory watch |
| 23 | /// On error returns WatchID with Error type. | 23 | /// On error returns WatchID with Error type. |
| 24 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 24 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 25 | const std::vector<WatcherOption> &options ) override; | ||
| 25 | 26 | ||
| 26 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 27 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 27 | void removeWatch( const std::string& directory ); | 28 | void removeWatch( const std::string& directory ) override; |
| 28 | 29 | ||
| 29 | /// Remove a directory watch. This is a map lookup O(logn). | 30 | /// Remove a directory watch. This is a map lookup O(logn). |
| 30 | void removeWatch( WatchID watchid ); | 31 | void removeWatch( WatchID watchid ) override; |
| 31 | 32 | ||
| 32 | /// Updates the watcher. Must be called often. | 33 | /// Updates the watcher. Must be called often. |
| 33 | void watch(); | 34 | void watch() override; |
| 34 | 35 | ||
| 35 | /// Handles the action | 36 | /// Handles the action |
| 36 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 37 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 37 | std::string oldFilename = "" ); | 38 | std::string oldFilename = "" ) override; |
| 38 | 39 | ||
| 39 | /// @return Returns a list of the directories that are being watched | 40 | /// @return Returns a list of the directories that are being watched |
| 40 | std::list<std::string> directories(); | 41 | std::vector<std::string> directories() override; |
| 41 | 42 | ||
| 42 | protected: | 43 | protected: |
| 43 | /// Map of WatchID to WatchStruct pointers | 44 | /// Map of WatchID to WatchStruct pointers |
| @@ -53,7 +54,7 @@ class FileWatcherKqueue : public FileWatcherImpl { | |||
| 53 | 54 | ||
| 54 | Mutex mWatchesLock; | 55 | Mutex mWatchesLock; |
| 55 | 56 | ||
| 56 | std::list<WatchID> mRemoveList; | 57 | std::vector<WatchID> mRemoveList; |
| 57 | 58 | ||
| 58 | long mFileDescriptorCount; | 59 | long mFileDescriptorCount; |
| 59 | 60 | ||
| @@ -61,7 +62,7 @@ class FileWatcherKqueue : public FileWatcherImpl { | |||
| 61 | 62 | ||
| 62 | bool isAddingWatcher() const; | 63 | bool isAddingWatcher() const; |
| 63 | 64 | ||
| 64 | bool pathInWatches( const std::string& path ); | 65 | bool pathInWatches( const std::string& path ) override; |
| 65 | 66 | ||
| 66 | void addFD(); | 67 | void addFD(); |
| 67 | 68 | ||
diff --git a/src/3rdParty/efsw/FileWatcherWin32.cpp b/src/3rdParty/efsw/FileWatcherWin32.cpp index 963dc98..19b71d7 100755..100644 --- a/src/3rdParty/efsw/FileWatcherWin32.cpp +++ b/src/3rdParty/efsw/FileWatcherWin32.cpp | |||
| @@ -1,257 +1,267 @@ | |||
| 1 | #include <efsw/FileSystem.hpp> | 1 | #include <efsw/FileSystem.hpp> |
| 2 | #include <efsw/FileWatcherWin32.hpp> | 2 | #include <efsw/FileWatcherWin32.hpp> |
| 3 | #include <efsw/Lock.hpp> | 3 | #include <efsw/Lock.hpp> |
| 4 | #include <efsw/String.hpp> | 4 | #include <efsw/String.hpp> |
| 5 | #include <efsw/System.hpp> | 5 | #include <efsw/System.hpp> |
| 6 | 6 | ||
| 7 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 | 7 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 |
| 8 | 8 | ||
| 9 | namespace efsw { | 9 | namespace efsw { |
| 10 | 10 | ||
| 11 | FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : | 11 | FileWatcherWin32::FileWatcherWin32( FileWatcher* parent ) : |
| 12 | FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) { | 12 | FileWatcherImpl( parent ), mLastWatchID( 0 ), mThread( NULL ) { |
| 13 | mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ); | 13 | mIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ); |
| 14 | if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) | 14 | if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) |
| 15 | mInitOK = true; | 15 | mInitOK = true; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | FileWatcherWin32::~FileWatcherWin32() { | 18 | FileWatcherWin32::~FileWatcherWin32() { |
| 19 | mInitOK = false; | 19 | mInitOK = false; |
| 20 | 20 | ||
| 21 | if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) { | 21 | if ( mIOCP && mIOCP != INVALID_HANDLE_VALUE ) { |
| 22 | PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL ); | 22 | PostQueuedCompletionStatus( mIOCP, 0, reinterpret_cast<ULONG_PTR>( this ), NULL ); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | efSAFE_DELETE( mThread ); | 25 | efSAFE_DELETE( mThread ); |
| 26 | 26 | ||
| 27 | removeAllWatches(); | 27 | removeAllWatches(); |
| 28 | 28 | ||
| 29 | CloseHandle( mIOCP ); | 29 | if ( mIOCP ) |
| 30 | } | 30 | CloseHandle( mIOCP ); |
| 31 | 31 | } | |
| 32 | WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, | 32 | |
| 33 | bool recursive ) { | 33 | WatchID FileWatcherWin32::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 34 | std::string dir( directory ); | 34 | bool recursive, const std::vector<WatcherOption> &options ) { |
| 35 | 35 | std::string dir( directory ); | |
| 36 | FileInfo fi( dir ); | 36 | |
| 37 | 37 | FileInfo fi( dir ); | |
| 38 | if ( !fi.isDirectory() ) { | 38 | |
| 39 | return Errors::Log::createLastError( Errors::FileNotFound, dir ); | 39 | if ( !fi.isDirectory() ) { |
| 40 | } else if ( !fi.isReadable() ) { | 40 | return Errors::Log::createLastError( Errors::FileNotFound, dir ); |
| 41 | return Errors::Log::createLastError( Errors::FileNotReadable, dir ); | 41 | } else if ( !fi.isReadable() ) { |
| 42 | } | 42 | return Errors::Log::createLastError( Errors::FileNotReadable, dir ); |
| 43 | 43 | } | |
| 44 | FileSystem::dirAddSlashAtEnd( dir ); | 44 | |
| 45 | 45 | FileSystem::dirAddSlashAtEnd( dir ); | |
| 46 | Lock lock( mWatchesLock ); | 46 | |
| 47 | 47 | Lock lock( mWatchesLock ); | |
| 48 | if ( pathInWatches( dir ) ) { | 48 | |
| 49 | return Errors::Log::createLastError( Errors::FileRepeated, dir ); | 49 | if ( pathInWatches( dir ) ) { |
| 50 | } | 50 | return Errors::Log::createLastError( Errors::FileRepeated, dir ); |
| 51 | 51 | } | |
| 52 | WatchID watchid = ++mLastWatchID; | 52 | |
| 53 | 53 | WatchID watchid = ++mLastWatchID; | |
| 54 | WatcherStructWin32* watch = CreateWatch( | 54 | |
| 55 | String::fromUtf8( dir ).toWideString().c_str(), recursive, | 55 | DWORD bufferSize = static_cast<DWORD>( getOptionValue(options, Option::WinBufferSize, 63 * 1024) ); |
| 56 | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME | | 56 | DWORD notifyFilter = static_cast<DWORD>( getOptionValue(options, Option::WinNotifyFilter, |
| 57 | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE, | 57 | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | |
| 58 | mIOCP ); | 58 | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | |
| 59 | 59 | FILE_NOTIFY_CHANGE_SIZE) ); | |
| 60 | if ( NULL == watch ) { | 60 | |
| 61 | return Errors::Log::createLastError( Errors::FileNotFound, dir ); | 61 | WatcherStructWin32* watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), |
| 62 | } | 62 | recursive, bufferSize, notifyFilter, mIOCP ); |
| 63 | 63 | ||
| 64 | // Add the handle to the handles vector | 64 | if ( NULL == watch ) { |
| 65 | watch->Watch->ID = watchid; | 65 | return Errors::Log::createLastError( Errors::FileNotFound, dir ); |
| 66 | watch->Watch->Watch = this; | 66 | } |
| 67 | watch->Watch->Listener = watcher; | 67 | |
| 68 | watch->Watch->DirName = new char[dir.length() + 1]; | 68 | // Add the handle to the handles vector |
| 69 | strcpy( watch->Watch->DirName, dir.c_str() ); | 69 | watch->Watch->ID = watchid; |
| 70 | 70 | watch->Watch->Watch = this; | |
| 71 | mWatches.insert( watch ); | 71 | watch->Watch->Listener = watcher; |
| 72 | 72 | watch->Watch->DirName = new char[dir.length() + 1]; | |
| 73 | return watchid; | 73 | strcpy( watch->Watch->DirName, dir.c_str() ); |
| 74 | } | 74 | |
| 75 | 75 | mWatches.insert( watch ); | |
| 76 | void FileWatcherWin32::removeWatch( const std::string& directory ) { | 76 | |
| 77 | Lock lock( mWatchesLock ); | 77 | return watchid; |
| 78 | 78 | } | |
| 79 | Watches::iterator iter = mWatches.begin(); | 79 | |
| 80 | 80 | void FileWatcherWin32::removeWatch( const std::string& directory ) { | |
| 81 | for ( ; iter != mWatches.end(); ++iter ) { | 81 | Lock lock( mWatchesLock ); |
| 82 | if ( directory == ( *iter )->Watch->DirName ) { | 82 | |
| 83 | removeWatch( *iter ); | 83 | Watches::iterator iter = mWatches.begin(); |
| 84 | break; | 84 | |
| 85 | } | 85 | for ( ; iter != mWatches.end(); ++iter ) { |
| 86 | } | 86 | if ( directory == ( *iter )->Watch->DirName ) { |
| 87 | } | 87 | removeWatch( *iter ); |
| 88 | 88 | break; | |
| 89 | void FileWatcherWin32::removeWatch( WatchID watchid ) { | 89 | } |
| 90 | Lock lock( mWatchesLock ); | 90 | } |
| 91 | 91 | } | |
| 92 | Watches::iterator iter = mWatches.begin(); | 92 | |
| 93 | 93 | void FileWatcherWin32::removeWatch( WatchID watchid ) { | |
| 94 | for ( ; iter != mWatches.end(); ++iter ) { | 94 | Lock lock( mWatchesLock ); |
| 95 | // Find the watch ID | 95 | |
| 96 | if ( ( *iter )->Watch->ID == watchid ) { | 96 | Watches::iterator iter = mWatches.begin(); |
| 97 | removeWatch( *iter ); | 97 | |
| 98 | return; | 98 | for ( ; iter != mWatches.end(); ++iter ) { |
| 99 | } | 99 | // Find the watch ID |
| 100 | } | 100 | if ( ( *iter )->Watch->ID == watchid ) { |
| 101 | } | 101 | removeWatch( *iter ); |
| 102 | 102 | return; | |
| 103 | void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { | 103 | } |
| 104 | Lock lock( mWatchesLock ); | 104 | } |
| 105 | 105 | } | |
| 106 | DestroyWatch( watch ); | 106 | |
| 107 | mWatches.erase( watch ); | 107 | void FileWatcherWin32::removeWatch( WatcherStructWin32* watch ) { |
| 108 | } | 108 | Lock lock( mWatchesLock ); |
| 109 | 109 | ||
| 110 | void FileWatcherWin32::watch() { | 110 | DestroyWatch( watch ); |
| 111 | if ( NULL == mThread ) { | 111 | mWatches.erase( watch ); |
| 112 | mThread = new Thread( &FileWatcherWin32::run, this ); | 112 | } |
| 113 | mThread->launch(); | 113 | |
| 114 | } | 114 | void FileWatcherWin32::watch() { |
| 115 | } | 115 | if ( NULL == mThread ) { |
| 116 | 116 | mThread = new Thread( &FileWatcherWin32::run, this ); | |
| 117 | void FileWatcherWin32::removeAllWatches() { | 117 | mThread->launch(); |
| 118 | Lock lock( mWatchesLock ); | 118 | } |
| 119 | 119 | } | |
| 120 | Watches::iterator iter = mWatches.begin(); | 120 | |
| 121 | 121 | void FileWatcherWin32::removeAllWatches() { | |
| 122 | for ( ; iter != mWatches.end(); ++iter ) { | 122 | Lock lock( mWatchesLock ); |
| 123 | DestroyWatch( ( *iter ) ); | 123 | |
| 124 | } | 124 | Watches::iterator iter = mWatches.begin(); |
| 125 | 125 | ||
| 126 | mWatches.clear(); | 126 | for ( ; iter != mWatches.end(); ++iter ) { |
| 127 | } | 127 | DestroyWatch( ( *iter ) ); |
| 128 | 128 | } | |
| 129 | void FileWatcherWin32::run() { | 129 | |
| 130 | do { | 130 | mWatches.clear(); |
| 131 | if ( mInitOK && !mWatches.empty() ) { | 131 | } |
| 132 | DWORD numOfBytes = 0; | 132 | |
| 133 | OVERLAPPED* ov = NULL; | 133 | void FileWatcherWin32::run() { |
| 134 | ULONG_PTR compKey = 0; | 134 | do { |
| 135 | BOOL res = FALSE; | 135 | if ( mInitOK && !mWatches.empty() ) { |
| 136 | 136 | DWORD numOfBytes = 0; | |
| 137 | while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov, | 137 | OVERLAPPED* ov = NULL; |
| 138 | INFINITE ) ) != FALSE ) { | 138 | ULONG_PTR compKey = 0; |
| 139 | if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) { | 139 | BOOL res = FALSE; |
| 140 | break; | 140 | |
| 141 | } else { | 141 | while ( ( res = GetQueuedCompletionStatus( mIOCP, &numOfBytes, &compKey, &ov, |
| 142 | Lock lock( mWatchesLock ); | 142 | INFINITE ) ) != FALSE ) { |
| 143 | WatchCallback( numOfBytes, ov ); | 143 | if ( compKey != 0 && compKey == reinterpret_cast<ULONG_PTR>( this ) ) { |
| 144 | } | 144 | break; |
| 145 | } | 145 | } else { |
| 146 | } else { | 146 | Lock lock( mWatchesLock ); |
| 147 | System::sleep( 10 ); | 147 | if (mWatches.find( (WatcherStructWin32*)ov ) != mWatches.end()) |
| 148 | } | 148 | WatchCallback( numOfBytes, ov ); |
| 149 | } while ( mInitOK ); | 149 | } |
| 150 | 150 | } | |
| 151 | removeAllWatches(); | 151 | } else { |
| 152 | } | 152 | System::sleep( 10 ); |
| 153 | 153 | } | |
| 154 | void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename, | 154 | } while ( mInitOK ); |
| 155 | unsigned long action, std::string /*oldFilename*/ ) { | 155 | |
| 156 | Action fwAction; | 156 | removeAllWatches(); |
| 157 | 157 | } | |
| 158 | switch ( action ) { | 158 | |
| 159 | case FILE_ACTION_RENAMED_OLD_NAME: | 159 | void FileWatcherWin32::handleAction( Watcher* watch, const std::string& filename, |
| 160 | watch->OldFileName = filename; | 160 | unsigned long action, std::string /*oldFilename*/ ) { |
| 161 | return; | 161 | Action fwAction; |
| 162 | case FILE_ACTION_ADDED: | 162 | |
| 163 | fwAction = Actions::Add; | 163 | switch ( action ) { |
| 164 | break; | 164 | case FILE_ACTION_RENAMED_OLD_NAME: |
| 165 | case FILE_ACTION_RENAMED_NEW_NAME: { | 165 | watch->OldFileName = filename; |
| 166 | fwAction = Actions::Moved; | 166 | return; |
| 167 | 167 | case FILE_ACTION_ADDED: | |
| 168 | std::string fpath( watch->Directory + filename ); | 168 | fwAction = Actions::Add; |
| 169 | 169 | break; | |
| 170 | // Update the directory path | 170 | case FILE_ACTION_RENAMED_NEW_NAME: { |
| 171 | if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { | 171 | fwAction = Actions::Moved; |
| 172 | // Update the new directory path | 172 | |
| 173 | std::string opath( watch->Directory + watch->OldFileName ); | 173 | std::string fpath( watch->Directory + filename ); |
| 174 | FileSystem::dirAddSlashAtEnd( opath ); | 174 | |
| 175 | FileSystem::dirAddSlashAtEnd( fpath ); | 175 | // Update the directory path |
| 176 | 176 | if ( watch->Recursive && FileSystem::isDirectory( fpath ) ) { | |
| 177 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | 177 | // Update the new directory path |
| 178 | if ( ( *it )->Watch->Directory == opath ) { | 178 | std::string opath( watch->Directory + watch->OldFileName ); |
| 179 | ( *it )->Watch->Directory = fpath; | 179 | FileSystem::dirAddSlashAtEnd( opath ); |
| 180 | 180 | FileSystem::dirAddSlashAtEnd( fpath ); | |
| 181 | break; | 181 | |
| 182 | } | 182 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { |
| 183 | } | 183 | if ( ( *it )->Watch->Directory == opath ) { |
| 184 | } | 184 | ( *it )->Watch->Directory = fpath; |
| 185 | 185 | ||
| 186 | std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); | 186 | break; |
| 187 | std::string realFilename = filename; | 187 | } |
| 188 | std::size_t sepPos = filename.find_last_of( "/\\" ); | 188 | } |
| 189 | std::string oldFolderPath = | 189 | } |
| 190 | static_cast<WatcherWin32*>( watch )->DirName + | 190 | |
| 191 | watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) ); | 191 | std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); |
| 192 | 192 | std::string realFilename = filename; | |
| 193 | if ( sepPos != std::string::npos ) { | 193 | std::size_t sepPos = filename.find_last_of( "/\\" ); |
| 194 | folderPath += filename.substr( 0, sepPos ); | 194 | std::string oldFolderPath = |
| 195 | realFilename = filename.substr( sepPos + 1 ); | 195 | static_cast<WatcherWin32*>( watch )->DirName + |
| 196 | } | 196 | watch->OldFileName.substr( 0, watch->OldFileName.find_last_of( "/\\" ) ); |
| 197 | 197 | ||
| 198 | if ( folderPath == oldFolderPath ) { | 198 | if ( sepPos != std::string::npos ) { |
| 199 | watch->Listener->handleFileAction( | 199 | folderPath += |
| 200 | watch->ID, folderPath, realFilename, fwAction, | 200 | filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); |
| 201 | FileSystem::fileNameFromPath( watch->OldFileName ) ); | 201 | realFilename = filename.substr( sepPos + 1 ); |
| 202 | } else { | 202 | } |
| 203 | watch->Listener->handleFileAction( watch->ID, | 203 | |
| 204 | static_cast<WatcherWin32*>( watch )->DirName, | 204 | if ( folderPath == oldFolderPath ) { |
| 205 | filename, fwAction, watch->OldFileName ); | 205 | watch->Listener->handleFileAction( |
| 206 | } | 206 | watch->ID, folderPath, realFilename, fwAction, |
| 207 | return; | 207 | FileSystem::fileNameFromPath( watch->OldFileName ) ); |
| 208 | } | 208 | } else { |
| 209 | case FILE_ACTION_REMOVED: | 209 | watch->Listener->handleFileAction( watch->ID, |
| 210 | fwAction = Actions::Delete; | 210 | static_cast<WatcherWin32*>( watch )->DirName, |
| 211 | break; | 211 | filename, fwAction, watch->OldFileName ); |
| 212 | case FILE_ACTION_MODIFIED: | 212 | } |
| 213 | fwAction = Actions::Modified; | 213 | return; |
| 214 | break; | 214 | } |
| 215 | default: | 215 | case FILE_ACTION_REMOVED: |
| 216 | return; | 216 | fwAction = Actions::Delete; |
| 217 | }; | 217 | break; |
| 218 | 218 | case FILE_ACTION_MODIFIED: | |
| 219 | std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); | 219 | fwAction = Actions::Modified; |
| 220 | std::string realFilename = filename; | 220 | break; |
| 221 | std::size_t sepPos = filename.find_last_of( "/\\" ); | 221 | default: |
| 222 | 222 | return; | |
| 223 | if ( sepPos != std::string::npos ) { | 223 | }; |
| 224 | folderPath += filename.substr( 0, sepPos ); | 224 | |
| 225 | realFilename = filename.substr( sepPos + 1 ); | 225 | std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); |
| 226 | } | 226 | std::string realFilename = filename; |
| 227 | 227 | std::size_t sepPos = filename.find_last_of( "/\\" ); | |
| 228 | watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction ); | 228 | |
| 229 | } | 229 | if ( sepPos != std::string::npos ) { |
| 230 | 230 | folderPath += filename.substr( 0, sepPos + 1 < filename.size() ? sepPos + 1 : sepPos ); | |
| 231 | std::list<std::string> FileWatcherWin32::directories() { | 231 | realFilename = filename.substr( sepPos + 1 ); |
| 232 | std::list<std::string> dirs; | 232 | } |
| 233 | 233 | ||
| 234 | Lock lock( mWatchesLock ); | 234 | FileSystem::dirAddSlashAtEnd( folderPath ); |
| 235 | 235 | ||
| 236 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | 236 | watch->Listener->handleFileAction( watch->ID, folderPath, realFilename, fwAction ); |
| 237 | dirs.push_back( std::string( ( *it )->Watch->DirName ) ); | 237 | } |
| 238 | } | 238 | |
| 239 | 239 | std::vector<std::string> FileWatcherWin32::directories() { | |
| 240 | return dirs; | 240 | std::vector<std::string> dirs; |
| 241 | } | 241 | |
| 242 | 242 | Lock lock( mWatchesLock ); | |
| 243 | bool FileWatcherWin32::pathInWatches( const std::string& path ) { | 243 | |
| 244 | Lock lock( mWatchesLock ); | 244 | dirs.reserve( mWatches.size() ); |
| 245 | 245 | ||
| 246 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | 246 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { |
| 247 | if ( ( *it )->Watch->DirName == path ) { | 247 | dirs.push_back( std::string( ( *it )->Watch->DirName ) ); |
| 248 | return true; | 248 | } |
| 249 | } | 249 | |
| 250 | } | 250 | return dirs; |
| 251 | 251 | } | |
| 252 | return false; | 252 | |
| 253 | } | 253 | bool FileWatcherWin32::pathInWatches( const std::string& path ) { |
| 254 | 254 | Lock lock( mWatchesLock ); | |
| 255 | } // namespace efsw | 255 | |
| 256 | 256 | for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { | |
| 257 | #endif | 257 | if ( ( *it )->Watch->DirName == path ) { |
| 258 | return true; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | return false; | ||
| 263 | } | ||
| 264 | |||
| 265 | } // namespace efsw | ||
| 266 | |||
| 267 | #endif | ||
diff --git a/src/3rdParty/efsw/FileWatcherWin32.hpp b/src/3rdParty/efsw/FileWatcherWin32.hpp index 94439cf..3016aac 100755..100644 --- a/src/3rdParty/efsw/FileWatcherWin32.hpp +++ b/src/3rdParty/efsw/FileWatcherWin32.hpp | |||
| @@ -1,70 +1,71 @@ | |||
| 1 | #ifndef EFSW_FILEWATCHERWIN32_HPP | 1 | #ifndef EFSW_FILEWATCHERWIN32_HPP |
| 2 | #define EFSW_FILEWATCHERWIN32_HPP | 2 | #define EFSW_FILEWATCHERWIN32_HPP |
| 3 | 3 | ||
| 4 | #include <efsw/base.hpp> | 4 | #include <efsw/base.hpp> |
| 5 | 5 | ||
| 6 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 | 6 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 |
| 7 | 7 | ||
| 8 | #include <efsw/WatcherWin32.hpp> | 8 | #include <efsw/WatcherWin32.hpp> |
| 9 | #include <map> | 9 | #include <map> |
| 10 | #include <set> | 10 | #include <unordered_set> |
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | namespace efsw { | 13 | namespace efsw { |
| 14 | 14 | ||
| 15 | /// Implementation for Win32 based on ReadDirectoryChangesW. | 15 | /// Implementation for Win32 based on ReadDirectoryChangesW. |
| 16 | /// @class FileWatcherWin32 | 16 | /// @class FileWatcherWin32 |
| 17 | class FileWatcherWin32 : public FileWatcherImpl { | 17 | class FileWatcherWin32 : public FileWatcherImpl { |
| 18 | public: | 18 | public: |
| 19 | /// type for a map from WatchID to WatcherWin32 pointer | 19 | /// type for a map from WatchID to WatcherWin32 pointer |
| 20 | typedef std::set<WatcherStructWin32*> Watches; | 20 | typedef std::unordered_set<WatcherStructWin32*> Watches; |
| 21 | 21 | ||
| 22 | FileWatcherWin32( FileWatcher* parent ); | 22 | FileWatcherWin32( FileWatcher* parent ); |
| 23 | 23 | ||
| 24 | virtual ~FileWatcherWin32(); | 24 | virtual ~FileWatcherWin32(); |
| 25 | 25 | ||
| 26 | /// Add a directory watch | 26 | /// Add a directory watch |
| 27 | /// On error returns WatchID with Error type. | 27 | /// On error returns WatchID with Error type. |
| 28 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 28 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 29 | 29 | const std::vector<WatcherOption> &options ) override; | |
| 30 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). | 30 | |
| 31 | void removeWatch( const std::string& directory ); | 31 | /// Remove a directory watch. This is a brute force lazy search O(nlogn). |
| 32 | 32 | void removeWatch( const std::string& directory ) override; | |
| 33 | /// Remove a directory watch. This is a map lookup O(logn). | 33 | |
| 34 | void removeWatch( WatchID watchid ); | 34 | /// Remove a directory watch. This is a map lookup O(logn). |
| 35 | 35 | void removeWatch( WatchID watchid ) override; | |
| 36 | /// Updates the watcher. Must be called often. | 36 | |
| 37 | void watch(); | 37 | /// Updates the watcher. Must be called often. |
| 38 | 38 | void watch() override; | |
| 39 | /// Handles the action | 39 | |
| 40 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, | 40 | /// Handles the action |
| 41 | std::string oldFilename = "" ); | 41 | void handleAction( Watcher* watch, const std::string& filename, unsigned long action, |
| 42 | 42 | std::string oldFilename = "" ) override; | |
| 43 | /// @return Returns a list of the directories that are being watched | 43 | |
| 44 | std::list<std::string> directories(); | 44 | /// @return Returns a list of the directories that are being watched |
| 45 | 45 | std::vector<std::string> directories() override; | |
| 46 | protected: | 46 | |
| 47 | HANDLE mIOCP; | 47 | protected: |
| 48 | Watches mWatches; | 48 | HANDLE mIOCP; |
| 49 | 49 | Watches mWatches; | |
| 50 | /// The last watchid | 50 | |
| 51 | WatchID mLastWatchID; | 51 | /// The last watchid |
| 52 | Thread* mThread; | 52 | WatchID mLastWatchID; |
| 53 | Mutex mWatchesLock; | 53 | Thread* mThread; |
| 54 | 54 | Mutex mWatchesLock; | |
| 55 | bool pathInWatches( const std::string& path ); | 55 | |
| 56 | 56 | bool pathInWatches( const std::string& path ) override; | |
| 57 | /// Remove all directory watches. | 57 | |
| 58 | void removeAllWatches(); | 58 | /// Remove all directory watches. |
| 59 | 59 | void removeAllWatches(); | |
| 60 | void removeWatch( WatcherStructWin32* watch ); | 60 | |
| 61 | 61 | void removeWatch( WatcherStructWin32* watch ); | |
| 62 | private: | 62 | |
| 63 | void run(); | 63 | private: |
| 64 | }; | 64 | void run(); |
| 65 | 65 | }; | |
| 66 | } // namespace efsw | 66 | |
| 67 | 67 | } // namespace efsw | |
| 68 | #endif | 68 | |
| 69 | 69 | #endif | |
| 70 | #endif | 70 | |
| 71 | #endif | ||
diff --git a/src/3rdParty/efsw/LICENSE b/src/3rdParty/efsw/LICENSE index 37f354a..37f354a 100755..100644 --- a/src/3rdParty/efsw/LICENSE +++ b/src/3rdParty/efsw/LICENSE | |||
diff --git a/src/3rdParty/efsw/Lock.hpp b/src/3rdParty/efsw/Lock.hpp index e8c522a..e8c522a 100755..100644 --- a/src/3rdParty/efsw/Lock.hpp +++ b/src/3rdParty/efsw/Lock.hpp | |||
diff --git a/src/3rdParty/efsw/Log.cpp b/src/3rdParty/efsw/Log.cpp index ddf7a62..6f32df7 100755..100644 --- a/src/3rdParty/efsw/Log.cpp +++ b/src/3rdParty/efsw/Log.cpp | |||
| @@ -1,20 +1,31 @@ | |||
| 1 | #include <efsw/efsw.hpp> | 1 | #include <efsw/efsw.hpp> |
| 2 | #include <efsw/Debug.hpp> | ||
| 2 | 3 | ||
| 3 | namespace efsw { namespace Errors { | 4 | namespace efsw { namespace Errors { |
| 4 | 5 | ||
| 5 | static std::string LastError; | 6 | static std::string LastError = ""; |
| 7 | static Error LastErrorCode = NoError; | ||
| 6 | 8 | ||
| 7 | std::string Log::getLastErrorLog() { | 9 | std::string Log::getLastErrorLog() { |
| 8 | return LastError; | 10 | return LastError; |
| 9 | } | 11 | } |
| 10 | 12 | ||
| 13 | Error Log::getLastErrorCode() { | ||
| 14 | return LastErrorCode; | ||
| 15 | } | ||
| 16 | |||
| 17 | void Log::clearLastError() { | ||
| 18 | LastErrorCode = NoError; | ||
| 19 | LastError = ""; | ||
| 20 | } | ||
| 21 | |||
| 11 | Error Log::createLastError( Error err, std::string log ) { | 22 | Error Log::createLastError( Error err, std::string log ) { |
| 12 | switch ( err ) { | 23 | switch ( err ) { |
| 13 | case FileNotFound: | 24 | case FileNotFound: |
| 14 | LastError = "File not found ( " + log + " )"; | 25 | LastError = "File not found ( " + log + " )"; |
| 15 | break; | 26 | break; |
| 16 | case FileRepeated: | 27 | case FileRepeated: |
| 17 | LastError = "File reapeated in watches ( " + log + " )"; | 28 | LastError = "File repeated in watches ( " + log + " )"; |
| 18 | break; | 29 | break; |
| 19 | case FileOutOfScope: | 30 | case FileOutOfScope: |
| 20 | LastError = "Symlink file out of scope ( " + log + " )"; | 31 | LastError = "Symlink file out of scope ( " + log + " )"; |
| @@ -23,11 +34,15 @@ Error Log::createLastError( Error err, std::string log ) { | |||
| 23 | LastError = | 34 | LastError = |
| 24 | "File is located in a remote file system, use a generic watcher. ( " + log + " )"; | 35 | "File is located in a remote file system, use a generic watcher. ( " + log + " )"; |
| 25 | break; | 36 | break; |
| 37 | case WatcherFailed: | ||
| 38 | LastError = "File system watcher failed ( " + log + " )"; | ||
| 39 | break; | ||
| 26 | case Unspecified: | 40 | case Unspecified: |
| 27 | default: | 41 | default: |
| 28 | LastError = log; | 42 | LastError = log; |
| 29 | } | 43 | } |
| 30 | 44 | ||
| 45 | efDEBUG( "%s\n", LastError.c_str() ); | ||
| 31 | return err; | 46 | return err; |
| 32 | } | 47 | } |
| 33 | 48 | ||
diff --git a/src/3rdParty/efsw/Mutex.cpp b/src/3rdParty/efsw/Mutex.cpp index c961db1..c961db1 100755..100644 --- a/src/3rdParty/efsw/Mutex.cpp +++ b/src/3rdParty/efsw/Mutex.cpp | |||
diff --git a/src/3rdParty/efsw/Mutex.hpp b/src/3rdParty/efsw/Mutex.hpp index d98ad17..d98ad17 100755..100644 --- a/src/3rdParty/efsw/Mutex.hpp +++ b/src/3rdParty/efsw/Mutex.hpp | |||
diff --git a/src/3rdParty/efsw/String.cpp b/src/3rdParty/efsw/String.cpp index e3ba68f..e3ba68f 100755..100644 --- a/src/3rdParty/efsw/String.cpp +++ b/src/3rdParty/efsw/String.cpp | |||
diff --git a/src/3rdParty/efsw/String.hpp b/src/3rdParty/efsw/String.hpp index 65bce33..b42b945 100755..100644 --- a/src/3rdParty/efsw/String.hpp +++ b/src/3rdParty/efsw/String.hpp | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include <cstdlib> | 11 | #include <cstdlib> |
| 12 | #include <cstring> | 12 | #include <cstring> |
| 13 | #include <efsw/base.hpp> | 13 | #include <efsw/base.hpp> |
| 14 | #include <fstream> | ||
| 15 | #include <iostream> | 14 | #include <iostream> |
| 16 | #include <locale> | 15 | #include <locale> |
| 17 | #include <sstream> | 16 | #include <sstream> |
| @@ -24,7 +23,7 @@ namespace efsw { | |||
| 24 | * **/ | 23 | * **/ |
| 25 | class String { | 24 | class String { |
| 26 | public: | 25 | public: |
| 27 | typedef Uint32 StringBaseType; | 26 | typedef char32_t StringBaseType; |
| 28 | typedef std::basic_string<StringBaseType> StringType; | 27 | typedef std::basic_string<StringBaseType> StringType; |
| 29 | typedef StringType::iterator Iterator; //! Iterator type | 28 | typedef StringType::iterator Iterator; //! Iterator type |
| 30 | typedef StringType::const_iterator ConstIterator; //! Constant iterator type | 29 | typedef StringType::const_iterator ConstIterator; //! Constant iterator type |
diff --git a/src/3rdParty/efsw/System.cpp b/src/3rdParty/efsw/System.cpp index ba68bf4..ba68bf4 100755..100644 --- a/src/3rdParty/efsw/System.cpp +++ b/src/3rdParty/efsw/System.cpp | |||
diff --git a/src/3rdParty/efsw/System.hpp b/src/3rdParty/efsw/System.hpp index 498e121..498e121 100755..100644 --- a/src/3rdParty/efsw/System.hpp +++ b/src/3rdParty/efsw/System.hpp | |||
diff --git a/src/3rdParty/efsw/Thread.cpp b/src/3rdParty/efsw/Thread.cpp index e3f0fa0..cfa88b4 100755..100644 --- a/src/3rdParty/efsw/Thread.cpp +++ b/src/3rdParty/efsw/Thread.cpp | |||
| @@ -34,7 +34,8 @@ void Thread::terminate() { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | void Thread::run() { | 36 | void Thread::run() { |
| 37 | mEntryPoint->run(); | 37 | if ( mEntryPoint ) |
| 38 | mEntryPoint->run(); | ||
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | } // namespace efsw | 41 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/Thread.hpp b/src/3rdParty/efsw/Thread.hpp index b60373c..b60373c 100755..100644 --- a/src/3rdParty/efsw/Thread.hpp +++ b/src/3rdParty/efsw/Thread.hpp | |||
diff --git a/src/3rdParty/efsw/Utf.hpp b/src/3rdParty/efsw/Utf.hpp index 6e9ea71..1b042cd 100755..100644 --- a/src/3rdParty/efsw/Utf.hpp +++ b/src/3rdParty/efsw/Utf.hpp | |||
| @@ -1,721 +1,721 @@ | |||
| 1 | /** NOTE: | 1 | /** NOTE: |
| 2 | * This code is based on the Utf implementation from SFML2. License zlib/png ( | 2 | * This code is based on the Utf implementation from SFML2. License zlib/png ( |
| 3 | *http://www.sfml-dev.org/license.php ) The class was modified to fit efsw own needs. This is not | 3 | *http://www.sfml-dev.org/license.php ) The class was modified to fit efsw own needs. This is not |
| 4 | *the original implementation from SFML2. | 4 | *the original implementation from SFML2. |
| 5 | * */ | 5 | * */ |
| 6 | 6 | ||
| 7 | #ifndef EFSW_UTF_HPP | 7 | #ifndef EFSW_UTF_HPP |
| 8 | #define EFSW_UTF_HPP | 8 | #define EFSW_UTF_HPP |
| 9 | 9 | ||
| 10 | //////////////////////////////////////////////////////////// | 10 | //////////////////////////////////////////////////////////// |
| 11 | // Headers | 11 | // Headers |
| 12 | //////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////// |
| 13 | #include <cstdlib> | 13 | #include <cstdlib> |
| 14 | #include <efsw/base.hpp> | 14 | #include <efsw/base.hpp> |
| 15 | #include <locale> | 15 | #include <locale> |
| 16 | #include <string> | 16 | #include <string> |
| 17 | 17 | ||
| 18 | namespace efsw { | 18 | namespace efsw { |
| 19 | 19 | ||
| 20 | template <unsigned int N> class Utf; | 20 | template <unsigned int N> class Utf; |
| 21 | 21 | ||
| 22 | //////////////////////////////////////////////////////////// | 22 | //////////////////////////////////////////////////////////// |
| 23 | /// \brief Specialization of the Utf template for UTF-8 | 23 | /// \brief Specialization of the Utf template for UTF-8 |
| 24 | /// | 24 | /// |
| 25 | //////////////////////////////////////////////////////////// | 25 | //////////////////////////////////////////////////////////// |
| 26 | template <> class Utf<8> { | 26 | template <> class Utf<8> { |
| 27 | public: | 27 | public: |
| 28 | //////////////////////////////////////////////////////////// | 28 | //////////////////////////////////////////////////////////// |
| 29 | /// \brief Decode a single UTF-8 character | 29 | /// \brief Decode a single UTF-8 character |
| 30 | /// | 30 | /// |
| 31 | /// Decoding a character means finding its unique 32-bits | 31 | /// Decoding a character means finding its unique 32-bits |
| 32 | /// code (called the codepoint) in the Unicode standard. | 32 | /// code (called the codepoint) in the Unicode standard. |
| 33 | /// | 33 | /// |
| 34 | /// \param begin Iterator pointing to the beginning of the input sequence | 34 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 35 | /// \param end Iterator pointing to the end of the input sequence | 35 | /// \param end Iterator pointing to the end of the input sequence |
| 36 | /// \param output Codepoint of the decoded UTF-8 character | 36 | /// \param output Codepoint of the decoded UTF-8 character |
| 37 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid | 37 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid |
| 38 | /// | 38 | /// |
| 39 | /// \return Iterator pointing to one past the last read element of the input sequence | 39 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 40 | /// | 40 | /// |
| 41 | //////////////////////////////////////////////////////////// | 41 | //////////////////////////////////////////////////////////// |
| 42 | template <typename In> | 42 | template <typename In> |
| 43 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); | 43 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); |
| 44 | 44 | ||
| 45 | //////////////////////////////////////////////////////////// | 45 | //////////////////////////////////////////////////////////// |
| 46 | /// \brief Encode a single UTF-8 character | 46 | /// \brief Encode a single UTF-8 character |
| 47 | /// | 47 | /// |
| 48 | /// Encoding a character means converting a unique 32-bits | 48 | /// Encoding a character means converting a unique 32-bits |
| 49 | /// code (called the codepoint) in the target encoding, UTF-8. | 49 | /// code (called the codepoint) in the target encoding, UTF-8. |
| 50 | /// | 50 | /// |
| 51 | /// \param input Codepoint to encode as UTF-8 | 51 | /// \param input Codepoint to encode as UTF-8 |
| 52 | /// \param output Iterator pointing to the beginning of the output sequence | 52 | /// \param output Iterator pointing to the beginning of the output sequence |
| 53 | /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) | 53 | /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) |
| 54 | /// | 54 | /// |
| 55 | /// \return Iterator to the end of the output sequence which has been written | 55 | /// \return Iterator to the end of the output sequence which has been written |
| 56 | /// | 56 | /// |
| 57 | //////////////////////////////////////////////////////////// | 57 | //////////////////////////////////////////////////////////// |
| 58 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint8 replacement = 0 ); | 58 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint8 replacement = 0 ); |
| 59 | 59 | ||
| 60 | //////////////////////////////////////////////////////////// | 60 | //////////////////////////////////////////////////////////// |
| 61 | /// \brief Advance to the next UTF-8 character | 61 | /// \brief Advance to the next UTF-8 character |
| 62 | /// | 62 | /// |
| 63 | /// This function is necessary for multi-elements encodings, as | 63 | /// This function is necessary for multi-elements encodings, as |
| 64 | /// a single character may use more than 1 storage element. | 64 | /// a single character may use more than 1 storage element. |
| 65 | /// | 65 | /// |
| 66 | /// \param begin Iterator pointing to the beginning of the input sequence | 66 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 67 | /// \param end Iterator pointing to the end of the input sequence | 67 | /// \param end Iterator pointing to the end of the input sequence |
| 68 | /// | 68 | /// |
| 69 | /// \return Iterator pointing to one past the last read element of the input sequence | 69 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 70 | /// | 70 | /// |
| 71 | //////////////////////////////////////////////////////////// | 71 | //////////////////////////////////////////////////////////// |
| 72 | template <typename In> static In Next( In begin, In end ); | 72 | template <typename In> static In Next( In begin, In end ); |
| 73 | 73 | ||
| 74 | //////////////////////////////////////////////////////////// | 74 | //////////////////////////////////////////////////////////// |
| 75 | /// \brief Count the number of characters of a UTF-8 sequence | 75 | /// \brief Count the number of characters of a UTF-8 sequence |
| 76 | /// | 76 | /// |
| 77 | /// This function is necessary for multi-elements encodings, as | 77 | /// This function is necessary for multi-elements encodings, as |
| 78 | /// a single character may use more than 1 storage element, thus the | 78 | /// a single character may use more than 1 storage element, thus the |
| 79 | /// total size can be different from (begin - end). | 79 | /// total size can be different from (begin - end). |
| 80 | /// | 80 | /// |
| 81 | /// \param begin Iterator pointing to the beginning of the input sequence | 81 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 82 | /// \param end Iterator pointing to the end of the input sequence | 82 | /// \param end Iterator pointing to the end of the input sequence |
| 83 | /// | 83 | /// |
| 84 | /// \return Iterator pointing to one past the last read element of the input sequence | 84 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 85 | /// | 85 | /// |
| 86 | //////////////////////////////////////////////////////////// | 86 | //////////////////////////////////////////////////////////// |
| 87 | template <typename In> static std::size_t Count( In begin, In end ); | 87 | template <typename In> static std::size_t Count( In begin, In end ); |
| 88 | 88 | ||
| 89 | //////////////////////////////////////////////////////////// | 89 | //////////////////////////////////////////////////////////// |
| 90 | /// \brief Convert an ANSI characters range to UTF-8 | 90 | /// \brief Convert an ANSI characters range to UTF-8 |
| 91 | /// | 91 | /// |
| 92 | /// The current global locale will be used by default, unless you | 92 | /// The current global locale will be used by default, unless you |
| 93 | /// pass a custom one in the \a locale parameter. | 93 | /// pass a custom one in the \a locale parameter. |
| 94 | /// | 94 | /// |
| 95 | /// \param begin Iterator pointing to the beginning of the input sequence | 95 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 96 | /// \param end Iterator pointing to the end of the input sequence | 96 | /// \param end Iterator pointing to the end of the input sequence |
| 97 | /// \param output Iterator pointing to the beginning of the output sequence | 97 | /// \param output Iterator pointing to the beginning of the output sequence |
| 98 | /// \param locale Locale to use for conversion | 98 | /// \param locale Locale to use for conversion |
| 99 | /// | 99 | /// |
| 100 | /// \return Iterator to the end of the output sequence which has been written | 100 | /// \return Iterator to the end of the output sequence which has been written |
| 101 | /// | 101 | /// |
| 102 | //////////////////////////////////////////////////////////// | 102 | //////////////////////////////////////////////////////////// |
| 103 | template <typename In, typename Out> | 103 | template <typename In, typename Out> |
| 104 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); | 104 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); |
| 105 | 105 | ||
| 106 | //////////////////////////////////////////////////////////// | 106 | //////////////////////////////////////////////////////////// |
| 107 | /// \brief Convert a wide characters range to UTF-8 | 107 | /// \brief Convert a wide characters range to UTF-8 |
| 108 | /// | 108 | /// |
| 109 | /// \param begin Iterator pointing to the beginning of the input sequence | 109 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 110 | /// \param end Iterator pointing to the end of the input sequence | 110 | /// \param end Iterator pointing to the end of the input sequence |
| 111 | /// \param output Iterator pointing to the beginning of the output sequence | 111 | /// \param output Iterator pointing to the beginning of the output sequence |
| 112 | /// | 112 | /// |
| 113 | /// \return Iterator to the end of the output sequence which has been written | 113 | /// \return Iterator to the end of the output sequence which has been written |
| 114 | /// | 114 | /// |
| 115 | //////////////////////////////////////////////////////////// | 115 | //////////////////////////////////////////////////////////// |
| 116 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); | 116 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); |
| 117 | 117 | ||
| 118 | //////////////////////////////////////////////////////////// | 118 | //////////////////////////////////////////////////////////// |
| 119 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 | 119 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 |
| 120 | /// | 120 | /// |
| 121 | /// \param begin Iterator pointing to the beginning of the input sequence | 121 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 122 | /// \param end Iterator pointing to the end of the input sequence | 122 | /// \param end Iterator pointing to the end of the input sequence |
| 123 | /// \param output Iterator pointing to the beginning of the output sequence | 123 | /// \param output Iterator pointing to the beginning of the output sequence |
| 124 | /// \param locale Locale to use for conversion | 124 | /// \param locale Locale to use for conversion |
| 125 | /// | 125 | /// |
| 126 | /// \return Iterator to the end of the output sequence which has been written | 126 | /// \return Iterator to the end of the output sequence which has been written |
| 127 | /// | 127 | /// |
| 128 | //////////////////////////////////////////////////////////// | 128 | //////////////////////////////////////////////////////////// |
| 129 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); | 129 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); |
| 130 | 130 | ||
| 131 | //////////////////////////////////////////////////////////// | 131 | //////////////////////////////////////////////////////////// |
| 132 | /// \brief Convert an UTF-8 characters range to ANSI characters | 132 | /// \brief Convert an UTF-8 characters range to ANSI characters |
| 133 | /// | 133 | /// |
| 134 | /// The current global locale will be used by default, unless you | 134 | /// The current global locale will be used by default, unless you |
| 135 | /// pass a custom one in the \a locale parameter. | 135 | /// pass a custom one in the \a locale parameter. |
| 136 | /// | 136 | /// |
| 137 | /// \param begin Iterator pointing to the beginning of the input sequence | 137 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 138 | /// \param end Iterator pointing to the end of the input sequence | 138 | /// \param end Iterator pointing to the end of the input sequence |
| 139 | /// \param output Iterator pointing to the beginning of the output sequence | 139 | /// \param output Iterator pointing to the beginning of the output sequence |
| 140 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) | 140 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) |
| 141 | /// \param locale Locale to use for conversion | 141 | /// \param locale Locale to use for conversion |
| 142 | /// | 142 | /// |
| 143 | /// \return Iterator to the end of the output sequence which has been written | 143 | /// \return Iterator to the end of the output sequence which has been written |
| 144 | /// | 144 | /// |
| 145 | //////////////////////////////////////////////////////////// | 145 | //////////////////////////////////////////////////////////// |
| 146 | template <typename In, typename Out> | 146 | template <typename In, typename Out> |
| 147 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, | 147 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, |
| 148 | const std::locale& locale = std::locale() ); | 148 | const std::locale& locale = std::locale() ); |
| 149 | 149 | ||
| 150 | #ifndef EFSW_NO_WIDECHAR | 150 | #ifndef EFSW_NO_WIDECHAR |
| 151 | //////////////////////////////////////////////////////////// | 151 | //////////////////////////////////////////////////////////// |
| 152 | /// \brief Convert an UTF-8 characters range to wide characters | 152 | /// \brief Convert an UTF-8 characters range to wide characters |
| 153 | /// | 153 | /// |
| 154 | /// \param begin Iterator pointing to the beginning of the input sequence | 154 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 155 | /// \param end Iterator pointing to the end of the input sequence | 155 | /// \param end Iterator pointing to the end of the input sequence |
| 156 | /// \param output Iterator pointing to the beginning of the output sequence | 156 | /// \param output Iterator pointing to the beginning of the output sequence |
| 157 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 157 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 158 | /// | 158 | /// |
| 159 | /// \return Iterator to the end of the output sequence which has been written | 159 | /// \return Iterator to the end of the output sequence which has been written |
| 160 | /// | 160 | /// |
| 161 | //////////////////////////////////////////////////////////// | 161 | //////////////////////////////////////////////////////////// |
| 162 | template <typename In, typename Out> | 162 | template <typename In, typename Out> |
| 163 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); | 163 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); |
| 164 | #endif | 164 | #endif |
| 165 | 165 | ||
| 166 | //////////////////////////////////////////////////////////// | 166 | //////////////////////////////////////////////////////////// |
| 167 | /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters | 167 | /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters |
| 168 | /// | 168 | /// |
| 169 | /// \param begin Iterator pointing to the beginning of the input sequence | 169 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 170 | /// \param end Iterator pointing to the end of the input sequence | 170 | /// \param end Iterator pointing to the end of the input sequence |
| 171 | /// \param output Iterator pointing to the beginning of the output sequence | 171 | /// \param output Iterator pointing to the beginning of the output sequence |
| 172 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 172 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 173 | /// | 173 | /// |
| 174 | /// \return Iterator to the end of the output sequence which has been written | 174 | /// \return Iterator to the end of the output sequence which has been written |
| 175 | /// | 175 | /// |
| 176 | //////////////////////////////////////////////////////////// | 176 | //////////////////////////////////////////////////////////// |
| 177 | template <typename In, typename Out> | 177 | template <typename In, typename Out> |
| 178 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); | 178 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); |
| 179 | 179 | ||
| 180 | //////////////////////////////////////////////////////////// | 180 | //////////////////////////////////////////////////////////// |
| 181 | /// \brief Convert a UTF-8 characters range to UTF-8 | 181 | /// \brief Convert a UTF-8 characters range to UTF-8 |
| 182 | /// | 182 | /// |
| 183 | /// This functions does nothing more than a direct copy; | 183 | /// This functions does nothing more than a direct copy; |
| 184 | /// it is defined only to provide the same interface as other | 184 | /// it is defined only to provide the same interface as other |
| 185 | /// specializations of the efsw::Utf<> template, and allow | 185 | /// specializations of the efsw::Utf<> template, and allow |
| 186 | /// generic code to be written on top of it. | 186 | /// generic code to be written on top of it. |
| 187 | /// | 187 | /// |
| 188 | /// \param begin Iterator pointing to the beginning of the input sequence | 188 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 189 | /// \param end Iterator pointing to the end of the input sequence | 189 | /// \param end Iterator pointing to the end of the input sequence |
| 190 | /// \param output Iterator pointing to the beginning of the output sequence | 190 | /// \param output Iterator pointing to the beginning of the output sequence |
| 191 | /// | 191 | /// |
| 192 | /// \return Iterator to the end of the output sequence which has been written | 192 | /// \return Iterator to the end of the output sequence which has been written |
| 193 | /// | 193 | /// |
| 194 | //////////////////////////////////////////////////////////// | 194 | //////////////////////////////////////////////////////////// |
| 195 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); | 195 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); |
| 196 | 196 | ||
| 197 | //////////////////////////////////////////////////////////// | 197 | //////////////////////////////////////////////////////////// |
| 198 | /// \brief Convert a UTF-8 characters range to UTF-16 | 198 | /// \brief Convert a UTF-8 characters range to UTF-16 |
| 199 | /// | 199 | /// |
| 200 | /// \param begin Iterator pointing to the beginning of the input sequence | 200 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 201 | /// \param end Iterator pointing to the end of the input sequence | 201 | /// \param end Iterator pointing to the end of the input sequence |
| 202 | /// \param output Iterator pointing to the beginning of the output sequence | 202 | /// \param output Iterator pointing to the beginning of the output sequence |
| 203 | /// | 203 | /// |
| 204 | /// \return Iterator to the end of the output sequence which has been written | 204 | /// \return Iterator to the end of the output sequence which has been written |
| 205 | /// | 205 | /// |
| 206 | //////////////////////////////////////////////////////////// | 206 | //////////////////////////////////////////////////////////// |
| 207 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); | 207 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); |
| 208 | 208 | ||
| 209 | //////////////////////////////////////////////////////////// | 209 | //////////////////////////////////////////////////////////// |
| 210 | /// \brief Convert a UTF-8 characters range to UTF-32 | 210 | /// \brief Convert a UTF-8 characters range to UTF-32 |
| 211 | /// | 211 | /// |
| 212 | /// \param begin Iterator pointing to the beginning of the input sequence | 212 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 213 | /// \param end Iterator pointing to the end of the input sequence | 213 | /// \param end Iterator pointing to the end of the input sequence |
| 214 | /// \param output Iterator pointing to the beginning of the output sequence | 214 | /// \param output Iterator pointing to the beginning of the output sequence |
| 215 | /// | 215 | /// |
| 216 | /// \return Iterator to the end of the output sequence which has been written | 216 | /// \return Iterator to the end of the output sequence which has been written |
| 217 | /// | 217 | /// |
| 218 | //////////////////////////////////////////////////////////// | 218 | //////////////////////////////////////////////////////////// |
| 219 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); | 219 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); |
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | //////////////////////////////////////////////////////////// | 222 | //////////////////////////////////////////////////////////// |
| 223 | /// \brief Specialization of the Utf template for UTF-16 | 223 | /// \brief Specialization of the Utf template for UTF-16 |
| 224 | /// | 224 | /// |
| 225 | //////////////////////////////////////////////////////////// | 225 | //////////////////////////////////////////////////////////// |
| 226 | template <> class Utf<16> { | 226 | template <> class Utf<16> { |
| 227 | public: | 227 | public: |
| 228 | //////////////////////////////////////////////////////////// | 228 | //////////////////////////////////////////////////////////// |
| 229 | /// \brief Decode a single UTF-16 character | 229 | /// \brief Decode a single UTF-16 character |
| 230 | /// | 230 | /// |
| 231 | /// Decoding a character means finding its unique 32-bits | 231 | /// Decoding a character means finding its unique 32-bits |
| 232 | /// code (called the codepoint) in the Unicode standard. | 232 | /// code (called the codepoint) in the Unicode standard. |
| 233 | /// | 233 | /// |
| 234 | /// \param begin Iterator pointing to the beginning of the input sequence | 234 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 235 | /// \param end Iterator pointing to the end of the input sequence | 235 | /// \param end Iterator pointing to the end of the input sequence |
| 236 | /// \param output Codepoint of the decoded UTF-16 character | 236 | /// \param output Codepoint of the decoded UTF-16 character |
| 237 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid | 237 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid |
| 238 | /// | 238 | /// |
| 239 | /// \return Iterator pointing to one past the last read element of the input sequence | 239 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 240 | /// | 240 | /// |
| 241 | //////////////////////////////////////////////////////////// | 241 | //////////////////////////////////////////////////////////// |
| 242 | template <typename In> | 242 | template <typename In> |
| 243 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); | 243 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); |
| 244 | 244 | ||
| 245 | //////////////////////////////////////////////////////////// | 245 | //////////////////////////////////////////////////////////// |
| 246 | /// \brief Encode a single UTF-16 character | 246 | /// \brief Encode a single UTF-16 character |
| 247 | /// | 247 | /// |
| 248 | /// Encoding a character means converting a unique 32-bits | 248 | /// Encoding a character means converting a unique 32-bits |
| 249 | /// code (called the codepoint) in the target encoding, UTF-16. | 249 | /// code (called the codepoint) in the target encoding, UTF-16. |
| 250 | /// | 250 | /// |
| 251 | /// \param input Codepoint to encode as UTF-16 | 251 | /// \param input Codepoint to encode as UTF-16 |
| 252 | /// \param output Iterator pointing to the beginning of the output sequence | 252 | /// \param output Iterator pointing to the beginning of the output sequence |
| 253 | /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) | 253 | /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) |
| 254 | /// | 254 | /// |
| 255 | /// \return Iterator to the end of the output sequence which has been written | 255 | /// \return Iterator to the end of the output sequence which has been written |
| 256 | /// | 256 | /// |
| 257 | //////////////////////////////////////////////////////////// | 257 | //////////////////////////////////////////////////////////// |
| 258 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint16 replacement = 0 ); | 258 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint16 replacement = 0 ); |
| 259 | 259 | ||
| 260 | //////////////////////////////////////////////////////////// | 260 | //////////////////////////////////////////////////////////// |
| 261 | /// \brief Advance to the next UTF-16 character | 261 | /// \brief Advance to the next UTF-16 character |
| 262 | /// | 262 | /// |
| 263 | /// This function is necessary for multi-elements encodings, as | 263 | /// This function is necessary for multi-elements encodings, as |
| 264 | /// a single character may use more than 1 storage element. | 264 | /// a single character may use more than 1 storage element. |
| 265 | /// | 265 | /// |
| 266 | /// \param begin Iterator pointing to the beginning of the input sequence | 266 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 267 | /// \param end Iterator pointing to the end of the input sequence | 267 | /// \param end Iterator pointing to the end of the input sequence |
| 268 | /// | 268 | /// |
| 269 | /// \return Iterator pointing to one past the last read element of the input sequence | 269 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 270 | /// | 270 | /// |
| 271 | //////////////////////////////////////////////////////////// | 271 | //////////////////////////////////////////////////////////// |
| 272 | template <typename In> static In Next( In begin, In end ); | 272 | template <typename In> static In Next( In begin, In end ); |
| 273 | 273 | ||
| 274 | //////////////////////////////////////////////////////////// | 274 | //////////////////////////////////////////////////////////// |
| 275 | /// \brief Count the number of characters of a UTF-16 sequence | 275 | /// \brief Count the number of characters of a UTF-16 sequence |
| 276 | /// | 276 | /// |
| 277 | /// This function is necessary for multi-elements encodings, as | 277 | /// This function is necessary for multi-elements encodings, as |
| 278 | /// a single character may use more than 1 storage element, thus the | 278 | /// a single character may use more than 1 storage element, thus the |
| 279 | /// total size can be different from (begin - end). | 279 | /// total size can be different from (begin - end). |
| 280 | /// | 280 | /// |
| 281 | /// \param begin Iterator pointing to the beginning of the input sequence | 281 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 282 | /// \param end Iterator pointing to the end of the input sequence | 282 | /// \param end Iterator pointing to the end of the input sequence |
| 283 | /// | 283 | /// |
| 284 | /// \return Iterator pointing to one past the last read element of the input sequence | 284 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 285 | /// | 285 | /// |
| 286 | //////////////////////////////////////////////////////////// | 286 | //////////////////////////////////////////////////////////// |
| 287 | template <typename In> static std::size_t Count( In begin, In end ); | 287 | template <typename In> static std::size_t Count( In begin, In end ); |
| 288 | 288 | ||
| 289 | //////////////////////////////////////////////////////////// | 289 | //////////////////////////////////////////////////////////// |
| 290 | /// \brief Convert an ANSI characters range to UTF-16 | 290 | /// \brief Convert an ANSI characters range to UTF-16 |
| 291 | /// | 291 | /// |
| 292 | /// The current global locale will be used by default, unless you | 292 | /// The current global locale will be used by default, unless you |
| 293 | /// pass a custom one in the \a locale parameter. | 293 | /// pass a custom one in the \a locale parameter. |
| 294 | /// | 294 | /// |
| 295 | /// \param begin Iterator pointing to the beginning of the input sequence | 295 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 296 | /// \param end Iterator pointing to the end of the input sequence | 296 | /// \param end Iterator pointing to the end of the input sequence |
| 297 | /// \param output Iterator pointing to the beginning of the output sequence | 297 | /// \param output Iterator pointing to the beginning of the output sequence |
| 298 | /// \param locale Locale to use for conversion | 298 | /// \param locale Locale to use for conversion |
| 299 | /// | 299 | /// |
| 300 | /// \return Iterator to the end of the output sequence which has been written | 300 | /// \return Iterator to the end of the output sequence which has been written |
| 301 | /// | 301 | /// |
| 302 | //////////////////////////////////////////////////////////// | 302 | //////////////////////////////////////////////////////////// |
| 303 | template <typename In, typename Out> | 303 | template <typename In, typename Out> |
| 304 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); | 304 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); |
| 305 | 305 | ||
| 306 | //////////////////////////////////////////////////////////// | 306 | //////////////////////////////////////////////////////////// |
| 307 | /// \brief Convert a wide characters range to UTF-16 | 307 | /// \brief Convert a wide characters range to UTF-16 |
| 308 | /// | 308 | /// |
| 309 | /// \param begin Iterator pointing to the beginning of the input sequence | 309 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 310 | /// \param end Iterator pointing to the end of the input sequence | 310 | /// \param end Iterator pointing to the end of the input sequence |
| 311 | /// \param output Iterator pointing to the beginning of the output sequence | 311 | /// \param output Iterator pointing to the beginning of the output sequence |
| 312 | /// | 312 | /// |
| 313 | /// \return Iterator to the end of the output sequence which has been written | 313 | /// \return Iterator to the end of the output sequence which has been written |
| 314 | /// | 314 | /// |
| 315 | //////////////////////////////////////////////////////////// | 315 | //////////////////////////////////////////////////////////// |
| 316 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); | 316 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); |
| 317 | 317 | ||
| 318 | //////////////////////////////////////////////////////////// | 318 | //////////////////////////////////////////////////////////// |
| 319 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 | 319 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 |
| 320 | /// | 320 | /// |
| 321 | /// \param begin Iterator pointing to the beginning of the input sequence | 321 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 322 | /// \param end Iterator pointing to the end of the input sequence | 322 | /// \param end Iterator pointing to the end of the input sequence |
| 323 | /// \param output Iterator pointing to the beginning of the output sequence | 323 | /// \param output Iterator pointing to the beginning of the output sequence |
| 324 | /// \param locale Locale to use for conversion | 324 | /// \param locale Locale to use for conversion |
| 325 | /// | 325 | /// |
| 326 | /// \return Iterator to the end of the output sequence which has been written | 326 | /// \return Iterator to the end of the output sequence which has been written |
| 327 | /// | 327 | /// |
| 328 | //////////////////////////////////////////////////////////// | 328 | //////////////////////////////////////////////////////////// |
| 329 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); | 329 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); |
| 330 | 330 | ||
| 331 | //////////////////////////////////////////////////////////// | 331 | //////////////////////////////////////////////////////////// |
| 332 | /// \brief Convert an UTF-16 characters range to ANSI characters | 332 | /// \brief Convert an UTF-16 characters range to ANSI characters |
| 333 | /// | 333 | /// |
| 334 | /// The current global locale will be used by default, unless you | 334 | /// The current global locale will be used by default, unless you |
| 335 | /// pass a custom one in the \a locale parameter. | 335 | /// pass a custom one in the \a locale parameter. |
| 336 | /// | 336 | /// |
| 337 | /// \param begin Iterator pointing to the beginning of the input sequence | 337 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 338 | /// \param end Iterator pointing to the end of the input sequence | 338 | /// \param end Iterator pointing to the end of the input sequence |
| 339 | /// \param output Iterator pointing to the beginning of the output sequence | 339 | /// \param output Iterator pointing to the beginning of the output sequence |
| 340 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) | 340 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) |
| 341 | /// \param locale Locale to use for conversion | 341 | /// \param locale Locale to use for conversion |
| 342 | /// | 342 | /// |
| 343 | /// \return Iterator to the end of the output sequence which has been written | 343 | /// \return Iterator to the end of the output sequence which has been written |
| 344 | /// | 344 | /// |
| 345 | //////////////////////////////////////////////////////////// | 345 | //////////////////////////////////////////////////////////// |
| 346 | template <typename In, typename Out> | 346 | template <typename In, typename Out> |
| 347 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, | 347 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, |
| 348 | const std::locale& locale = std::locale() ); | 348 | const std::locale& locale = std::locale() ); |
| 349 | 349 | ||
| 350 | #ifndef EFSW_NO_WIDECHAR | 350 | #ifndef EFSW_NO_WIDECHAR |
| 351 | //////////////////////////////////////////////////////////// | 351 | //////////////////////////////////////////////////////////// |
| 352 | /// \brief Convert an UTF-16 characters range to wide characters | 352 | /// \brief Convert an UTF-16 characters range to wide characters |
| 353 | /// | 353 | /// |
| 354 | /// \param begin Iterator pointing to the beginning of the input sequence | 354 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 355 | /// \param end Iterator pointing to the end of the input sequence | 355 | /// \param end Iterator pointing to the end of the input sequence |
| 356 | /// \param output Iterator pointing to the beginning of the output sequence | 356 | /// \param output Iterator pointing to the beginning of the output sequence |
| 357 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 357 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 358 | /// | 358 | /// |
| 359 | /// \return Iterator to the end of the output sequence which has been written | 359 | /// \return Iterator to the end of the output sequence which has been written |
| 360 | /// | 360 | /// |
| 361 | //////////////////////////////////////////////////////////// | 361 | //////////////////////////////////////////////////////////// |
| 362 | template <typename In, typename Out> | 362 | template <typename In, typename Out> |
| 363 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); | 363 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); |
| 364 | #endif | 364 | #endif |
| 365 | 365 | ||
| 366 | //////////////////////////////////////////////////////////// | 366 | //////////////////////////////////////////////////////////// |
| 367 | /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters | 367 | /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters |
| 368 | /// | 368 | /// |
| 369 | /// \param begin Iterator pointing to the beginning of the input sequence | 369 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 370 | /// \param end Iterator pointing to the end of the input sequence | 370 | /// \param end Iterator pointing to the end of the input sequence |
| 371 | /// \param output Iterator pointing to the beginning of the output sequence | 371 | /// \param output Iterator pointing to the beginning of the output sequence |
| 372 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 372 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 373 | /// | 373 | /// |
| 374 | /// \return Iterator to the end of the output sequence which has been written | 374 | /// \return Iterator to the end of the output sequence which has been written |
| 375 | /// | 375 | /// |
| 376 | //////////////////////////////////////////////////////////// | 376 | //////////////////////////////////////////////////////////// |
| 377 | template <typename In, typename Out> | 377 | template <typename In, typename Out> |
| 378 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); | 378 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); |
| 379 | 379 | ||
| 380 | //////////////////////////////////////////////////////////// | 380 | //////////////////////////////////////////////////////////// |
| 381 | /// \brief Convert a UTF-16 characters range to UTF-8 | 381 | /// \brief Convert a UTF-16 characters range to UTF-8 |
| 382 | /// | 382 | /// |
| 383 | /// \param begin Iterator pointing to the beginning of the input sequence | 383 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 384 | /// \param end Iterator pointing to the end of the input sequence | 384 | /// \param end Iterator pointing to the end of the input sequence |
| 385 | /// \param output Iterator pointing to the beginning of the output sequence | 385 | /// \param output Iterator pointing to the beginning of the output sequence |
| 386 | /// | 386 | /// |
| 387 | /// \return Iterator to the end of the output sequence which has been written | 387 | /// \return Iterator to the end of the output sequence which has been written |
| 388 | /// | 388 | /// |
| 389 | //////////////////////////////////////////////////////////// | 389 | //////////////////////////////////////////////////////////// |
| 390 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); | 390 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); |
| 391 | 391 | ||
| 392 | //////////////////////////////////////////////////////////// | 392 | //////////////////////////////////////////////////////////// |
| 393 | /// \brief Convert a UTF-16 characters range to UTF-16 | 393 | /// \brief Convert a UTF-16 characters range to UTF-16 |
| 394 | /// | 394 | /// |
| 395 | /// This functions does nothing more than a direct copy; | 395 | /// This functions does nothing more than a direct copy; |
| 396 | /// it is defined only to provide the same interface as other | 396 | /// it is defined only to provide the same interface as other |
| 397 | /// specializations of the efsw::Utf<> template, and allow | 397 | /// specializations of the efsw::Utf<> template, and allow |
| 398 | /// generic code to be written on top of it. | 398 | /// generic code to be written on top of it. |
| 399 | /// | 399 | /// |
| 400 | /// \param begin Iterator pointing to the beginning of the input sequence | 400 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 401 | /// \param end Iterator pointing to the end of the input sequence | 401 | /// \param end Iterator pointing to the end of the input sequence |
| 402 | /// \param output Iterator pointing to the beginning of the output sequence | 402 | /// \param output Iterator pointing to the beginning of the output sequence |
| 403 | /// | 403 | /// |
| 404 | /// \return Iterator to the end of the output sequence which has been written | 404 | /// \return Iterator to the end of the output sequence which has been written |
| 405 | /// | 405 | /// |
| 406 | //////////////////////////////////////////////////////////// | 406 | //////////////////////////////////////////////////////////// |
| 407 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); | 407 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); |
| 408 | 408 | ||
| 409 | //////////////////////////////////////////////////////////// | 409 | //////////////////////////////////////////////////////////// |
| 410 | /// \brief Convert a UTF-16 characters range to UTF-32 | 410 | /// \brief Convert a UTF-16 characters range to UTF-32 |
| 411 | /// | 411 | /// |
| 412 | /// \param begin Iterator pointing to the beginning of the input sequence | 412 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 413 | /// \param end Iterator pointing to the end of the input sequence | 413 | /// \param end Iterator pointing to the end of the input sequence |
| 414 | /// \param output Iterator pointing to the beginning of the output sequence | 414 | /// \param output Iterator pointing to the beginning of the output sequence |
| 415 | /// | 415 | /// |
| 416 | /// \return Iterator to the end of the output sequence which has been written | 416 | /// \return Iterator to the end of the output sequence which has been written |
| 417 | /// | 417 | /// |
| 418 | //////////////////////////////////////////////////////////// | 418 | //////////////////////////////////////////////////////////// |
| 419 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); | 419 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); |
| 420 | }; | 420 | }; |
| 421 | 421 | ||
| 422 | //////////////////////////////////////////////////////////// | 422 | //////////////////////////////////////////////////////////// |
| 423 | /// \brief Specialization of the Utf template for UTF-32 | 423 | /// \brief Specialization of the Utf template for UTF-32 |
| 424 | /// | 424 | /// |
| 425 | //////////////////////////////////////////////////////////// | 425 | //////////////////////////////////////////////////////////// |
| 426 | template <> class Utf<32> { | 426 | template <> class Utf<32> { |
| 427 | public: | 427 | public: |
| 428 | //////////////////////////////////////////////////////////// | 428 | //////////////////////////////////////////////////////////// |
| 429 | /// \brief Decode a single UTF-32 character | 429 | /// \brief Decode a single UTF-32 character |
| 430 | /// | 430 | /// |
| 431 | /// Decoding a character means finding its unique 32-bits | 431 | /// Decoding a character means finding its unique 32-bits |
| 432 | /// code (called the codepoint) in the Unicode standard. | 432 | /// code (called the codepoint) in the Unicode standard. |
| 433 | /// For UTF-32, the character value is the same as the codepoint. | 433 | /// For UTF-32, the character value is the same as the codepoint. |
| 434 | /// | 434 | /// |
| 435 | /// \param begin Iterator pointing to the beginning of the input sequence | 435 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 436 | /// \param end Iterator pointing to the end of the input sequence | 436 | /// \param end Iterator pointing to the end of the input sequence |
| 437 | /// \param output Codepoint of the decoded UTF-32 character | 437 | /// \param output Codepoint of the decoded UTF-32 character |
| 438 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid | 438 | /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid |
| 439 | /// | 439 | /// |
| 440 | /// \return Iterator pointing to one past the last read element of the input sequence | 440 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 441 | /// | 441 | /// |
| 442 | //////////////////////////////////////////////////////////// | 442 | //////////////////////////////////////////////////////////// |
| 443 | template <typename In> | 443 | template <typename In> |
| 444 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); | 444 | static In Decode( In begin, In end, Uint32& output, Uint32 replacement = 0 ); |
| 445 | 445 | ||
| 446 | //////////////////////////////////////////////////////////// | 446 | //////////////////////////////////////////////////////////// |
| 447 | /// \brief Encode a single UTF-32 character | 447 | /// \brief Encode a single UTF-32 character |
| 448 | /// | 448 | /// |
| 449 | /// Encoding a character means converting a unique 32-bits | 449 | /// Encoding a character means converting a unique 32-bits |
| 450 | /// code (called the codepoint) in the target encoding, UTF-32. | 450 | /// code (called the codepoint) in the target encoding, UTF-32. |
| 451 | /// For UTF-32, the codepoint is the same as the character value. | 451 | /// For UTF-32, the codepoint is the same as the character value. |
| 452 | /// | 452 | /// |
| 453 | /// \param input Codepoint to encode as UTF-32 | 453 | /// \param input Codepoint to encode as UTF-32 |
| 454 | /// \param output Iterator pointing to the beginning of the output sequence | 454 | /// \param output Iterator pointing to the beginning of the output sequence |
| 455 | /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) | 455 | /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) |
| 456 | /// | 456 | /// |
| 457 | /// \return Iterator to the end of the output sequence which has been written | 457 | /// \return Iterator to the end of the output sequence which has been written |
| 458 | /// | 458 | /// |
| 459 | //////////////////////////////////////////////////////////// | 459 | //////////////////////////////////////////////////////////// |
| 460 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint32 replacement = 0 ); | 460 | template <typename Out> static Out Encode( Uint32 input, Out output, Uint32 replacement = 0 ); |
| 461 | 461 | ||
| 462 | //////////////////////////////////////////////////////////// | 462 | //////////////////////////////////////////////////////////// |
| 463 | /// \brief Advance to the next UTF-32 character | 463 | /// \brief Advance to the next UTF-32 character |
| 464 | /// | 464 | /// |
| 465 | /// This function is trivial for UTF-32, which can store | 465 | /// This function is trivial for UTF-32, which can store |
| 466 | /// every character in a single storage element. | 466 | /// every character in a single storage element. |
| 467 | /// | 467 | /// |
| 468 | /// \param begin Iterator pointing to the beginning of the input sequence | 468 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 469 | /// \param end Iterator pointing to the end of the input sequence | 469 | /// \param end Iterator pointing to the end of the input sequence |
| 470 | /// | 470 | /// |
| 471 | /// \return Iterator pointing to one past the last read element of the input sequence | 471 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 472 | /// | 472 | /// |
| 473 | //////////////////////////////////////////////////////////// | 473 | //////////////////////////////////////////////////////////// |
| 474 | template <typename In> static In Next( In begin, In end ); | 474 | template <typename In> static In Next( In begin, In end ); |
| 475 | 475 | ||
| 476 | //////////////////////////////////////////////////////////// | 476 | //////////////////////////////////////////////////////////// |
| 477 | /// \brief Count the number of characters of a UTF-32 sequence | 477 | /// \brief Count the number of characters of a UTF-32 sequence |
| 478 | /// | 478 | /// |
| 479 | /// This function is trivial for UTF-32, which can store | 479 | /// This function is trivial for UTF-32, which can store |
| 480 | /// every character in a single storage element. | 480 | /// every character in a single storage element. |
| 481 | /// | 481 | /// |
| 482 | /// \param begin Iterator pointing to the beginning of the input sequence | 482 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 483 | /// \param end Iterator pointing to the end of the input sequence | 483 | /// \param end Iterator pointing to the end of the input sequence |
| 484 | /// | 484 | /// |
| 485 | /// \return Iterator pointing to one past the last read element of the input sequence | 485 | /// \return Iterator pointing to one past the last read element of the input sequence |
| 486 | /// | 486 | /// |
| 487 | //////////////////////////////////////////////////////////// | 487 | //////////////////////////////////////////////////////////// |
| 488 | template <typename In> static std::size_t Count( In begin, In end ); | 488 | template <typename In> static std::size_t Count( In begin, In end ); |
| 489 | 489 | ||
| 490 | //////////////////////////////////////////////////////////// | 490 | //////////////////////////////////////////////////////////// |
| 491 | /// \brief Convert an ANSI characters range to UTF-32 | 491 | /// \brief Convert an ANSI characters range to UTF-32 |
| 492 | /// | 492 | /// |
| 493 | /// The current global locale will be used by default, unless you | 493 | /// The current global locale will be used by default, unless you |
| 494 | /// pass a custom one in the \a locale parameter. | 494 | /// pass a custom one in the \a locale parameter. |
| 495 | /// | 495 | /// |
| 496 | /// \param begin Iterator pointing to the beginning of the input sequence | 496 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 497 | /// \param end Iterator pointing to the end of the input sequence | 497 | /// \param end Iterator pointing to the end of the input sequence |
| 498 | /// \param output Iterator pointing to the beginning of the output sequence | 498 | /// \param output Iterator pointing to the beginning of the output sequence |
| 499 | /// \param locale Locale to use for conversion | 499 | /// \param locale Locale to use for conversion |
| 500 | /// | 500 | /// |
| 501 | /// \return Iterator to the end of the output sequence which has been written | 501 | /// \return Iterator to the end of the output sequence which has been written |
| 502 | /// | 502 | /// |
| 503 | //////////////////////////////////////////////////////////// | 503 | //////////////////////////////////////////////////////////// |
| 504 | template <typename In, typename Out> | 504 | template <typename In, typename Out> |
| 505 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); | 505 | static Out FromAnsi( In begin, In end, Out output, const std::locale& locale = std::locale() ); |
| 506 | 506 | ||
| 507 | //////////////////////////////////////////////////////////// | 507 | //////////////////////////////////////////////////////////// |
| 508 | /// \brief Convert a wide characters range to UTF-32 | 508 | /// \brief Convert a wide characters range to UTF-32 |
| 509 | /// | 509 | /// |
| 510 | /// \param begin Iterator pointing to the beginning of the input sequence | 510 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 511 | /// \param end Iterator pointing to the end of the input sequence | 511 | /// \param end Iterator pointing to the end of the input sequence |
| 512 | /// \param output Iterator pointing to the beginning of the output sequence | 512 | /// \param output Iterator pointing to the beginning of the output sequence |
| 513 | /// | 513 | /// |
| 514 | /// \return Iterator to the end of the output sequence which has been written | 514 | /// \return Iterator to the end of the output sequence which has been written |
| 515 | /// | 515 | /// |
| 516 | //////////////////////////////////////////////////////////// | 516 | //////////////////////////////////////////////////////////// |
| 517 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); | 517 | template <typename In, typename Out> static Out FromWide( In begin, In end, Out output ); |
| 518 | 518 | ||
| 519 | //////////////////////////////////////////////////////////// | 519 | //////////////////////////////////////////////////////////// |
| 520 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 | 520 | /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 |
| 521 | /// | 521 | /// |
| 522 | /// \param begin Iterator pointing to the beginning of the input sequence | 522 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 523 | /// \param end Iterator pointing to the end of the input sequence | 523 | /// \param end Iterator pointing to the end of the input sequence |
| 524 | /// \param output Iterator pointing to the beginning of the output sequence | 524 | /// \param output Iterator pointing to the beginning of the output sequence |
| 525 | /// \param locale Locale to use for conversion | 525 | /// \param locale Locale to use for conversion |
| 526 | /// | 526 | /// |
| 527 | /// \return Iterator to the end of the output sequence which has been written | 527 | /// \return Iterator to the end of the output sequence which has been written |
| 528 | /// | 528 | /// |
| 529 | //////////////////////////////////////////////////////////// | 529 | //////////////////////////////////////////////////////////// |
| 530 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); | 530 | template <typename In, typename Out> static Out FromLatin1( In begin, In end, Out output ); |
| 531 | 531 | ||
| 532 | //////////////////////////////////////////////////////////// | 532 | //////////////////////////////////////////////////////////// |
| 533 | /// \brief Convert an UTF-32 characters range to ANSI characters | 533 | /// \brief Convert an UTF-32 characters range to ANSI characters |
| 534 | /// | 534 | /// |
| 535 | /// The current global locale will be used by default, unless you | 535 | /// The current global locale will be used by default, unless you |
| 536 | /// pass a custom one in the \a locale parameter. | 536 | /// pass a custom one in the \a locale parameter. |
| 537 | /// | 537 | /// |
| 538 | /// \param begin Iterator pointing to the beginning of the input sequence | 538 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 539 | /// \param end Iterator pointing to the end of the input sequence | 539 | /// \param end Iterator pointing to the end of the input sequence |
| 540 | /// \param output Iterator pointing to the beginning of the output sequence | 540 | /// \param output Iterator pointing to the beginning of the output sequence |
| 541 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) | 541 | /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) |
| 542 | /// \param locale Locale to use for conversion | 542 | /// \param locale Locale to use for conversion |
| 543 | /// | 543 | /// |
| 544 | /// \return Iterator to the end of the output sequence which has been written | 544 | /// \return Iterator to the end of the output sequence which has been written |
| 545 | /// | 545 | /// |
| 546 | //////////////////////////////////////////////////////////// | 546 | //////////////////////////////////////////////////////////// |
| 547 | template <typename In, typename Out> | 547 | template <typename In, typename Out> |
| 548 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, | 548 | static Out ToAnsi( In begin, In end, Out output, char replacement = 0, |
| 549 | const std::locale& locale = std::locale() ); | 549 | const std::locale& locale = std::locale() ); |
| 550 | 550 | ||
| 551 | #ifndef EFSW_NO_WIDECHAR | 551 | #ifndef EFSW_NO_WIDECHAR |
| 552 | //////////////////////////////////////////////////////////// | 552 | //////////////////////////////////////////////////////////// |
| 553 | /// \brief Convert an UTF-32 characters range to wide characters | 553 | /// \brief Convert an UTF-32 characters range to wide characters |
| 554 | /// | 554 | /// |
| 555 | /// \param begin Iterator pointing to the beginning of the input sequence | 555 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 556 | /// \param end Iterator pointing to the end of the input sequence | 556 | /// \param end Iterator pointing to the end of the input sequence |
| 557 | /// \param output Iterator pointing to the beginning of the output sequence | 557 | /// \param output Iterator pointing to the beginning of the output sequence |
| 558 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 558 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 559 | /// | 559 | /// |
| 560 | /// \return Iterator to the end of the output sequence which has been written | 560 | /// \return Iterator to the end of the output sequence which has been written |
| 561 | /// | 561 | /// |
| 562 | //////////////////////////////////////////////////////////// | 562 | //////////////////////////////////////////////////////////// |
| 563 | template <typename In, typename Out> | 563 | template <typename In, typename Out> |
| 564 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); | 564 | static Out ToWide( In begin, In end, Out output, wchar_t replacement = 0 ); |
| 565 | #endif | 565 | #endif |
| 566 | 566 | ||
| 567 | //////////////////////////////////////////////////////////// | 567 | //////////////////////////////////////////////////////////// |
| 568 | /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters | 568 | /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters |
| 569 | /// | 569 | /// |
| 570 | /// \param begin Iterator pointing to the beginning of the input sequence | 570 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 571 | /// \param end Iterator pointing to the end of the input sequence | 571 | /// \param end Iterator pointing to the end of the input sequence |
| 572 | /// \param output Iterator pointing to the beginning of the output sequence | 572 | /// \param output Iterator pointing to the beginning of the output sequence |
| 573 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) | 573 | /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) |
| 574 | /// | 574 | /// |
| 575 | /// \return Iterator to the end of the output sequence which has been written | 575 | /// \return Iterator to the end of the output sequence which has been written |
| 576 | /// | 576 | /// |
| 577 | //////////////////////////////////////////////////////////// | 577 | //////////////////////////////////////////////////////////// |
| 578 | template <typename In, typename Out> | 578 | template <typename In, typename Out> |
| 579 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); | 579 | static Out ToLatin1( In begin, In end, Out output, char replacement = 0 ); |
| 580 | 580 | ||
| 581 | //////////////////////////////////////////////////////////// | 581 | //////////////////////////////////////////////////////////// |
| 582 | /// \brief Convert a UTF-32 characters range to UTF-8 | 582 | /// \brief Convert a UTF-32 characters range to UTF-8 |
| 583 | /// | 583 | /// |
| 584 | /// \param begin Iterator pointing to the beginning of the input sequence | 584 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 585 | /// \param end Iterator pointing to the end of the input sequence | 585 | /// \param end Iterator pointing to the end of the input sequence |
| 586 | /// \param output Iterator pointing to the beginning of the output sequence | 586 | /// \param output Iterator pointing to the beginning of the output sequence |
| 587 | /// | 587 | /// |
| 588 | /// \return Iterator to the end of the output sequence which has been written | 588 | /// \return Iterator to the end of the output sequence which has been written |
| 589 | /// | 589 | /// |
| 590 | //////////////////////////////////////////////////////////// | 590 | //////////////////////////////////////////////////////////// |
| 591 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); | 591 | template <typename In, typename Out> static Out toUtf8( In begin, In end, Out output ); |
| 592 | 592 | ||
| 593 | //////////////////////////////////////////////////////////// | 593 | //////////////////////////////////////////////////////////// |
| 594 | /// \brief Convert a UTF-32 characters range to UTF-16 | 594 | /// \brief Convert a UTF-32 characters range to UTF-16 |
| 595 | /// | 595 | /// |
| 596 | /// \param begin Iterator pointing to the beginning of the input sequence | 596 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 597 | /// \param end Iterator pointing to the end of the input sequence | 597 | /// \param end Iterator pointing to the end of the input sequence |
| 598 | /// \param output Iterator pointing to the beginning of the output sequence | 598 | /// \param output Iterator pointing to the beginning of the output sequence |
| 599 | /// | 599 | /// |
| 600 | /// \return Iterator to the end of the output sequence which has been written | 600 | /// \return Iterator to the end of the output sequence which has been written |
| 601 | /// | 601 | /// |
| 602 | //////////////////////////////////////////////////////////// | 602 | //////////////////////////////////////////////////////////// |
| 603 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); | 603 | template <typename In, typename Out> static Out ToUtf16( In begin, In end, Out output ); |
| 604 | 604 | ||
| 605 | //////////////////////////////////////////////////////////// | 605 | //////////////////////////////////////////////////////////// |
| 606 | /// \brief Convert a UTF-32 characters range to UTF-32 | 606 | /// \brief Convert a UTF-32 characters range to UTF-32 |
| 607 | /// | 607 | /// |
| 608 | /// This functions does nothing more than a direct copy; | 608 | /// This functions does nothing more than a direct copy; |
| 609 | /// it is defined only to provide the same interface as other | 609 | /// it is defined only to provide the same interface as other |
| 610 | /// specializations of the efsw::Utf<> template, and allow | 610 | /// specializations of the efsw::Utf<> template, and allow |
| 611 | /// generic code to be written on top of it. | 611 | /// generic code to be written on top of it. |
| 612 | /// | 612 | /// |
| 613 | /// \param begin Iterator pointing to the beginning of the input sequence | 613 | /// \param begin Iterator pointing to the beginning of the input sequence |
| 614 | /// \param end Iterator pointing to the end of the input sequence | 614 | /// \param end Iterator pointing to the end of the input sequence |
| 615 | /// \param output Iterator pointing to the beginning of the output sequence | 615 | /// \param output Iterator pointing to the beginning of the output sequence |
| 616 | /// | 616 | /// |
| 617 | /// \return Iterator to the end of the output sequence which has been written | 617 | /// \return Iterator to the end of the output sequence which has been written |
| 618 | /// | 618 | /// |
| 619 | //////////////////////////////////////////////////////////// | 619 | //////////////////////////////////////////////////////////// |
| 620 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); | 620 | template <typename In, typename Out> static Out ToUtf32( In begin, In end, Out output ); |
| 621 | 621 | ||
| 622 | //////////////////////////////////////////////////////////// | 622 | //////////////////////////////////////////////////////////// |
| 623 | /// \brief Decode a single ANSI character to UTF-32 | 623 | /// \brief Decode a single ANSI character to UTF-32 |
| 624 | /// | 624 | /// |
| 625 | /// This function does not exist in other specializations | 625 | /// This function does not exist in other specializations |
| 626 | /// of efsw::Utf<>, it is defined for convenience (it is used by | 626 | /// of efsw::Utf<>, it is defined for convenience (it is used by |
| 627 | /// several other conversion functions). | 627 | /// several other conversion functions). |
| 628 | /// | 628 | /// |
| 629 | /// \param input Input ANSI character | 629 | /// \param input Input ANSI character |
| 630 | /// \param locale Locale to use for conversion | 630 | /// \param locale Locale to use for conversion |
| 631 | /// | 631 | /// |
| 632 | /// \return Converted character | 632 | /// \return Converted character |
| 633 | /// | 633 | /// |
| 634 | //////////////////////////////////////////////////////////// | 634 | //////////////////////////////////////////////////////////// |
| 635 | template <typename In> | 635 | template <typename In> |
| 636 | static Uint32 DecodeAnsi( In input, const std::locale& locale = std::locale() ); | 636 | static Uint32 DecodeAnsi( In input, const std::locale& locale = std::locale() ); |
| 637 | 637 | ||
| 638 | //////////////////////////////////////////////////////////// | 638 | //////////////////////////////////////////////////////////// |
| 639 | /// \brief Decode a single wide character to UTF-32 | 639 | /// \brief Decode a single wide character to UTF-32 |
| 640 | /// | 640 | /// |
| 641 | /// This function does not exist in other specializations | 641 | /// This function does not exist in other specializations |
| 642 | /// of efsw::Utf<>, it is defined for convenience (it is used by | 642 | /// of efsw::Utf<>, it is defined for convenience (it is used by |
| 643 | /// several other conversion functions). | 643 | /// several other conversion functions). |
| 644 | /// | 644 | /// |
| 645 | /// \param input Input wide character | 645 | /// \param input Input wide character |
| 646 | /// | 646 | /// |
| 647 | /// \return Converted character | 647 | /// \return Converted character |
| 648 | /// | 648 | /// |
| 649 | //////////////////////////////////////////////////////////// | 649 | //////////////////////////////////////////////////////////// |
| 650 | template <typename In> static Uint32 DecodeWide( In input ); | 650 | template <typename In> static Uint32 DecodeWide( In input ); |
| 651 | 651 | ||
| 652 | //////////////////////////////////////////////////////////// | 652 | //////////////////////////////////////////////////////////// |
| 653 | /// \brief Encode a single UTF-32 character to ANSI | 653 | /// \brief Encode a single UTF-32 character to ANSI |
| 654 | /// | 654 | /// |
| 655 | /// This function does not exist in other specializations | 655 | /// This function does not exist in other specializations |
| 656 | /// of efsw::Utf<>, it is defined for convenience (it is used by | 656 | /// of efsw::Utf<>, it is defined for convenience (it is used by |
| 657 | /// several other conversion functions). | 657 | /// several other conversion functions). |
| 658 | /// | 658 | /// |
| 659 | /// \param codepoint Iterator pointing to the beginning of the input sequence | 659 | /// \param codepoint Iterator pointing to the beginning of the input sequence |
| 660 | /// \param output Iterator pointing to the beginning of the output sequence | 660 | /// \param output Iterator pointing to the beginning of the output sequence |
| 661 | /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to | 661 | /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to |
| 662 | /// skip it) \param locale Locale to use for conversion | 662 | /// skip it) \param locale Locale to use for conversion |
| 663 | /// | 663 | /// |
| 664 | /// \return Iterator to the end of the output sequence which has been written | 664 | /// \return Iterator to the end of the output sequence which has been written |
| 665 | /// | 665 | /// |
| 666 | //////////////////////////////////////////////////////////// | 666 | //////////////////////////////////////////////////////////// |
| 667 | template <typename Out> | 667 | template <typename Out> |
| 668 | static Out EncodeAnsi( Uint32 codepoint, Out output, char replacement = 0, | 668 | static Out EncodeAnsi( Uint32 codepoint, Out output, char replacement = 0, |
| 669 | const std::locale& locale = std::locale() ); | 669 | const std::locale& locale = std::locale() ); |
| 670 | 670 | ||
| 671 | #ifndef EFSW_NO_WIDECHAR | 671 | #ifndef EFSW_NO_WIDECHAR |
| 672 | //////////////////////////////////////////////////////////// | 672 | //////////////////////////////////////////////////////////// |
| 673 | /// \brief Encode a single UTF-32 character to wide | 673 | /// \brief Encode a single UTF-32 character to wide |
| 674 | /// | 674 | /// |
| 675 | /// This function does not exist in other specializations | 675 | /// This function does not exist in other specializations |
| 676 | /// of efsw::Utf<>, it is defined for convenience (it is used by | 676 | /// of efsw::Utf<>, it is defined for convenience (it is used by |
| 677 | /// several other conversion functions). | 677 | /// several other conversion functions). |
| 678 | /// | 678 | /// |
| 679 | /// \param codepoint Iterator pointing to the beginning of the input sequence | 679 | /// \param codepoint Iterator pointing to the beginning of the input sequence |
| 680 | /// \param output Iterator pointing to the beginning of the output sequence | 680 | /// \param output Iterator pointing to the beginning of the output sequence |
| 681 | /// \param replacement Replacement if the input character is not convertible to wide (use 0 to | 681 | /// \param replacement Replacement if the input character is not convertible to wide (use 0 to |
| 682 | /// skip it) | 682 | /// skip it) |
| 683 | /// | 683 | /// |
| 684 | /// \return Iterator to the end of the output sequence which has been written | 684 | /// \return Iterator to the end of the output sequence which has been written |
| 685 | /// | 685 | /// |
| 686 | //////////////////////////////////////////////////////////// | 686 | //////////////////////////////////////////////////////////// |
| 687 | template <typename Out> | 687 | template <typename Out> |
| 688 | static Out EncodeWide( Uint32 codepoint, Out output, wchar_t replacement = 0 ); | 688 | static Out EncodeWide( Uint32 codepoint, Out output, wchar_t replacement = 0 ); |
| 689 | #endif | 689 | #endif |
| 690 | }; | 690 | }; |
| 691 | 691 | ||
| 692 | #include "Utf.inl" | 692 | #include "Utf.inl" |
| 693 | 693 | ||
| 694 | // Make typedefs to get rid of the template syntax | 694 | // Make typedefs to get rid of the template syntax |
| 695 | typedef Utf<8> Utf8; | 695 | typedef Utf<8> Utf8; |
| 696 | typedef Utf<16> Utf16; | 696 | typedef Utf<16> Utf16; |
| 697 | typedef Utf<32> Utf32; | 697 | typedef Utf<32> Utf32; |
| 698 | 698 | ||
| 699 | } // namespace efsw | 699 | } // namespace efsw |
| 700 | #endif | 700 | #endif |
| 701 | 701 | ||
| 702 | //////////////////////////////////////////////////////////// | 702 | //////////////////////////////////////////////////////////// |
| 703 | /// \class efsw::Utf | 703 | /// \class efsw::Utf |
| 704 | /// \ingroup system | 704 | /// \ingroup system |
| 705 | /// | 705 | /// |
| 706 | /// Utility class providing generic functions for UTF conversions. | 706 | /// Utility class providing generic functions for UTF conversions. |
| 707 | /// | 707 | /// |
| 708 | /// efsw::Utf is a low-level, generic interface for counting, iterating, | 708 | /// efsw::Utf is a low-level, generic interface for counting, iterating, |
| 709 | /// encoding and decoding Unicode characters and strings. It is able | 709 | /// encoding and decoding Unicode characters and strings. It is able |
| 710 | /// to handle ANSI, wide, UTF-8, UTF-16 and UTF-32 encodings. | 710 | /// to handle ANSI, wide, UTF-8, UTF-16 and UTF-32 encodings. |
| 711 | /// | 711 | /// |
| 712 | /// efsw::Utf<X> functions are all static, these classes are not meant to | 712 | /// efsw::Utf<X> functions are all static, these classes are not meant to |
| 713 | /// be instanciated. All the functions are template, so that you | 713 | /// be instanciated. All the functions are template, so that you |
| 714 | /// can use any character / string type for a given encoding. | 714 | /// can use any character / string type for a given encoding. |
| 715 | /// | 715 | /// |
| 716 | /// It has 3 specializations: | 716 | /// It has 3 specializations: |
| 717 | /// \li efsw::Utf<8> (typedef'd to efsw::Utf8) | 717 | /// \li efsw::Utf<8> (typedef'd to efsw::Utf8) |
| 718 | /// \li efsw::Utf<16> (typedef'd to efsw::Utf16) | 718 | /// \li efsw::Utf<16> (typedef'd to efsw::Utf16) |
| 719 | /// \li efsw::Utf<32> (typedef'd to efsw::Utf32) | 719 | /// \li efsw::Utf<32> (typedef'd to efsw::Utf32) |
| 720 | /// | 720 | /// |
| 721 | //////////////////////////////////////////////////////////// | 721 | //////////////////////////////////////////////////////////// |
diff --git a/src/3rdParty/efsw/Utf.inl b/src/3rdParty/efsw/Utf.inl index 5b6c2e0..5c9d7a3 100755..100644 --- a/src/3rdParty/efsw/Utf.inl +++ b/src/3rdParty/efsw/Utf.inl | |||
| @@ -1,576 +1,576 @@ | |||
| 1 | // References : | 1 | // References : |
| 2 | // http://www.unicode.org/ | 2 | // http://www.unicode.org/ |
| 3 | // http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c | 3 | // http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c |
| 4 | // http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h | 4 | // http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h |
| 5 | // http://people.w3.org/rishida/scripts/uniview/conversion | 5 | // http://people.w3.org/rishida/scripts/uniview/conversion |
| 6 | //////////////////////////////////////////////////////////// | 6 | //////////////////////////////////////////////////////////// |
| 7 | 7 | ||
| 8 | template <typename In> In Utf<8>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { | 8 | template <typename In> In Utf<8>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { |
| 9 | // Some useful precomputed data | 9 | // Some useful precomputed data |
| 10 | static const int trailing[256] = { | 10 | static const int trailing[256] = { |
| 11 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 11 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 14 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 14 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 17 | 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, | 17 | 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, |
| 18 | 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, | 18 | 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, |
| 19 | 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; | 19 | 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 }; |
| 20 | static const Uint32 offsets[6] = { 0x00000000, 0x00003080, 0x000E2080, | 20 | static const Uint32 offsets[6] = { 0x00000000, 0x00003080, 0x000E2080, |
| 21 | 0x03C82080, 0xFA082080, 0x82082080 }; | 21 | 0x03C82080, 0xFA082080, 0x82082080 }; |
| 22 | 22 | ||
| 23 | // Decode the character | 23 | // Decode the character |
| 24 | int trailingBytes = trailing[static_cast<Uint8>( *begin )]; | 24 | int trailingBytes = trailing[static_cast<Uint8>( *begin )]; |
| 25 | if ( begin + trailingBytes < end ) { | 25 | if ( begin + trailingBytes < end ) { |
| 26 | output = 0; | 26 | output = 0; |
| 27 | switch ( trailingBytes ) { | 27 | switch ( trailingBytes ) { |
| 28 | case 5: | 28 | case 5: |
| 29 | output += static_cast<Uint8>( *begin++ ); | 29 | output += static_cast<Uint8>( *begin++ ); |
| 30 | output <<= 6; | 30 | output <<= 6; |
| 31 | case 4: | 31 | case 4: |
| 32 | output += static_cast<Uint8>( *begin++ ); | 32 | output += static_cast<Uint8>( *begin++ ); |
| 33 | output <<= 6; | 33 | output <<= 6; |
| 34 | case 3: | 34 | case 3: |
| 35 | output += static_cast<Uint8>( *begin++ ); | 35 | output += static_cast<Uint8>( *begin++ ); |
| 36 | output <<= 6; | 36 | output <<= 6; |
| 37 | case 2: | 37 | case 2: |
| 38 | output += static_cast<Uint8>( *begin++ ); | 38 | output += static_cast<Uint8>( *begin++ ); |
| 39 | output <<= 6; | 39 | output <<= 6; |
| 40 | case 1: | 40 | case 1: |
| 41 | output += static_cast<Uint8>( *begin++ ); | 41 | output += static_cast<Uint8>( *begin++ ); |
| 42 | output <<= 6; | 42 | output <<= 6; |
| 43 | case 0: | 43 | case 0: |
| 44 | output += static_cast<Uint8>( *begin++ ); | 44 | output += static_cast<Uint8>( *begin++ ); |
| 45 | } | 45 | } |
| 46 | output -= offsets[trailingBytes]; | 46 | output -= offsets[trailingBytes]; |
| 47 | } else { | 47 | } else { |
| 48 | // Incomplete character | 48 | // Incomplete character |
| 49 | begin = end; | 49 | begin = end; |
| 50 | output = replacement; | 50 | output = replacement; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | return begin; | 53 | return begin; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | template <typename Out> Out Utf<8>::Encode( Uint32 input, Out output, Uint8 replacement ) { | 56 | template <typename Out> Out Utf<8>::Encode( Uint32 input, Out output, Uint8 replacement ) { |
| 57 | // Some useful precomputed data | 57 | // Some useful precomputed data |
| 58 | static const Uint8 firstBytes[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; | 58 | static const Uint8 firstBytes[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; |
| 59 | 59 | ||
| 60 | // Encode the character | 60 | // Encode the character |
| 61 | if ( ( input > 0x0010FFFF ) || ( ( input >= 0xD800 ) && ( input <= 0xDBFF ) ) ) { | 61 | if ( ( input > 0x0010FFFF ) || ( ( input >= 0xD800 ) && ( input <= 0xDBFF ) ) ) { |
| 62 | // Invalid character | 62 | // Invalid character |
| 63 | if ( replacement ) | 63 | if ( replacement ) |
| 64 | *output++ = replacement; | 64 | *output++ = replacement; |
| 65 | } else { | 65 | } else { |
| 66 | // Valid character | 66 | // Valid character |
| 67 | 67 | ||
| 68 | // Get the number of bytes to write | 68 | // Get the number of bytes to write |
| 69 | int bytesToWrite = 1; | 69 | int bytesToWrite = 1; |
| 70 | if ( input < 0x80 ) | 70 | if ( input < 0x80 ) |
| 71 | bytesToWrite = 1; | 71 | bytesToWrite = 1; |
| 72 | else if ( input < 0x800 ) | 72 | else if ( input < 0x800 ) |
| 73 | bytesToWrite = 2; | 73 | bytesToWrite = 2; |
| 74 | else if ( input < 0x10000 ) | 74 | else if ( input < 0x10000 ) |
| 75 | bytesToWrite = 3; | 75 | bytesToWrite = 3; |
| 76 | else if ( input <= 0x0010FFFF ) | 76 | else if ( input <= 0x0010FFFF ) |
| 77 | bytesToWrite = 4; | 77 | bytesToWrite = 4; |
| 78 | 78 | ||
| 79 | // Extract the bytes to write | 79 | // Extract the bytes to write |
| 80 | Uint8 bytes[4]; | 80 | Uint8 bytes[4]; |
| 81 | switch ( bytesToWrite ) { | 81 | switch ( bytesToWrite ) { |
| 82 | case 4: | 82 | case 4: |
| 83 | bytes[3] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); | 83 | bytes[3] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); |
| 84 | input >>= 6; | 84 | input >>= 6; |
| 85 | case 3: | 85 | case 3: |
| 86 | bytes[2] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); | 86 | bytes[2] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); |
| 87 | input >>= 6; | 87 | input >>= 6; |
| 88 | case 2: | 88 | case 2: |
| 89 | bytes[1] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); | 89 | bytes[1] = static_cast<Uint8>( ( input | 0x80 ) & 0xBF ); |
| 90 | input >>= 6; | 90 | input >>= 6; |
| 91 | case 1: | 91 | case 1: |
| 92 | bytes[0] = static_cast<Uint8>( input | firstBytes[bytesToWrite] ); | 92 | bytes[0] = static_cast<Uint8>( input | firstBytes[bytesToWrite] ); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | // Add them to the output | 95 | // Add them to the output |
| 96 | const Uint8* currentByte = bytes; | 96 | const Uint8* currentByte = bytes; |
| 97 | switch ( bytesToWrite ) { | 97 | switch ( bytesToWrite ) { |
| 98 | case 4: | 98 | case 4: |
| 99 | *output++ = *currentByte++; | 99 | *output++ = *currentByte++; |
| 100 | case 3: | 100 | case 3: |
| 101 | *output++ = *currentByte++; | 101 | *output++ = *currentByte++; |
| 102 | case 2: | 102 | case 2: |
| 103 | *output++ = *currentByte++; | 103 | *output++ = *currentByte++; |
| 104 | case 1: | 104 | case 1: |
| 105 | *output++ = *currentByte++; | 105 | *output++ = *currentByte++; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | return output; | 109 | return output; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | template <typename In> In Utf<8>::Next( In begin, In end ) { | 112 | template <typename In> In Utf<8>::Next( In begin, In end ) { |
| 113 | Uint32 codepoint; | 113 | Uint32 codepoint; |
| 114 | return Decode( begin, end, codepoint ); | 114 | return Decode( begin, end, codepoint ); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | template <typename In> std::size_t Utf<8>::Count( In begin, In end ) { | 117 | template <typename In> std::size_t Utf<8>::Count( In begin, In end ) { |
| 118 | std::size_t length = 0; | 118 | std::size_t length = 0; |
| 119 | while ( begin < end ) { | 119 | while ( begin < end ) { |
| 120 | begin = Next( begin, end ); | 120 | begin = Next( begin, end ); |
| 121 | ++length; | 121 | ++length; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | return length; | 124 | return length; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | template <typename In, typename Out> | 127 | template <typename In, typename Out> |
| 128 | Out Utf<8>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { | 128 | Out Utf<8>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { |
| 129 | while ( begin < end ) { | 129 | while ( begin < end ) { |
| 130 | Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); | 130 | Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); |
| 131 | output = Encode( codepoint, output ); | 131 | output = Encode( codepoint, output ); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | return output; | 134 | return output; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | template <typename In, typename Out> Out Utf<8>::FromWide( In begin, In end, Out output ) { | 137 | template <typename In, typename Out> Out Utf<8>::FromWide( In begin, In end, Out output ) { |
| 138 | while ( begin < end ) { | 138 | while ( begin < end ) { |
| 139 | Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); | 139 | Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); |
| 140 | output = Encode( codepoint, output ); | 140 | output = Encode( codepoint, output ); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | return output; | 143 | return output; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | template <typename In, typename Out> Out Utf<8>::FromLatin1( In begin, In end, Out output ) { | 146 | template <typename In, typename Out> Out Utf<8>::FromLatin1( In begin, In end, Out output ) { |
| 147 | // Latin-1 is directly compatible with Unicode encodings, | 147 | // Latin-1 is directly compatible with Unicode encodings, |
| 148 | // and can thus be treated as (a sub-range of) UTF-32 | 148 | // and can thus be treated as (a sub-range of) UTF-32 |
| 149 | while ( begin < end ) | 149 | while ( begin < end ) |
| 150 | output = Encode( *begin++, output ); | 150 | output = Encode( *begin++, output ); |
| 151 | 151 | ||
| 152 | return output; | 152 | return output; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | template <typename In, typename Out> | 155 | template <typename In, typename Out> |
| 156 | Out Utf<8>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { | 156 | Out Utf<8>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { |
| 157 | while ( begin < end ) { | 157 | while ( begin < end ) { |
| 158 | Uint32 codepoint; | 158 | Uint32 codepoint; |
| 159 | begin = Decode( begin, end, codepoint ); | 159 | begin = Decode( begin, end, codepoint ); |
| 160 | output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); | 160 | output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | return output; | 163 | return output; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | #ifndef EFSW_NO_WIDECHAR | 166 | #ifndef EFSW_NO_WIDECHAR |
| 167 | template <typename In, typename Out> | 167 | template <typename In, typename Out> |
| 168 | Out Utf<8>::ToWide( In begin, In end, Out output, wchar_t replacement ) { | 168 | Out Utf<8>::ToWide( In begin, In end, Out output, wchar_t replacement ) { |
| 169 | while ( begin < end ) { | 169 | while ( begin < end ) { |
| 170 | Uint32 codepoint; | 170 | Uint32 codepoint; |
| 171 | begin = Decode( begin, end, codepoint ); | 171 | begin = Decode( begin, end, codepoint ); |
| 172 | output = Utf<32>::EncodeWide( codepoint, output, replacement ); | 172 | output = Utf<32>::EncodeWide( codepoint, output, replacement ); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | return output; | 175 | return output; |
| 176 | } | 176 | } |
| 177 | #endif | 177 | #endif |
| 178 | 178 | ||
| 179 | template <typename In, typename Out> | 179 | template <typename In, typename Out> |
| 180 | Out Utf<8>::ToLatin1( In begin, In end, Out output, char replacement ) { | 180 | Out Utf<8>::ToLatin1( In begin, In end, Out output, char replacement ) { |
| 181 | // Latin-1 is directly compatible with Unicode encodings, | 181 | // Latin-1 is directly compatible with Unicode encodings, |
| 182 | // and can thus be treated as (a sub-range of) UTF-32 | 182 | // and can thus be treated as (a sub-range of) UTF-32 |
| 183 | while ( begin < end ) { | 183 | while ( begin < end ) { |
| 184 | Uint32 codepoint; | 184 | Uint32 codepoint; |
| 185 | begin = Decode( begin, end, codepoint ); | 185 | begin = Decode( begin, end, codepoint ); |
| 186 | *output++ = codepoint < 256 ? static_cast<char>( codepoint ) : replacement; | 186 | *output++ = codepoint < 256 ? static_cast<char>( codepoint ) : replacement; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | return output; | 189 | return output; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | template <typename In, typename Out> Out Utf<8>::toUtf8( In begin, In end, Out output ) { | 192 | template <typename In, typename Out> Out Utf<8>::toUtf8( In begin, In end, Out output ) { |
| 193 | while ( begin < end ) | 193 | while ( begin < end ) |
| 194 | *output++ = *begin++; | 194 | *output++ = *begin++; |
| 195 | 195 | ||
| 196 | return output; | 196 | return output; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | template <typename In, typename Out> Out Utf<8>::ToUtf16( In begin, In end, Out output ) { | 199 | template <typename In, typename Out> Out Utf<8>::ToUtf16( In begin, In end, Out output ) { |
| 200 | while ( begin < end ) { | 200 | while ( begin < end ) { |
| 201 | Uint32 codepoint; | 201 | Uint32 codepoint; |
| 202 | begin = Decode( begin, end, codepoint ); | 202 | begin = Decode( begin, end, codepoint ); |
| 203 | output = Utf<16>::Encode( codepoint, output ); | 203 | output = Utf<16>::Encode( codepoint, output ); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | return output; | 206 | return output; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | template <typename In, typename Out> Out Utf<8>::ToUtf32( In begin, In end, Out output ) { | 209 | template <typename In, typename Out> Out Utf<8>::ToUtf32( In begin, In end, Out output ) { |
| 210 | while ( begin < end ) { | 210 | while ( begin < end ) { |
| 211 | Uint32 codepoint; | 211 | Uint32 codepoint; |
| 212 | begin = Decode( begin, end, codepoint ); | 212 | begin = Decode( begin, end, codepoint ); |
| 213 | *output++ = codepoint; | 213 | *output++ = codepoint; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | return output; | 216 | return output; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | template <typename In> In Utf<16>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { | 219 | template <typename In> In Utf<16>::Decode( In begin, In end, Uint32& output, Uint32 replacement ) { |
| 220 | Uint16 first = *begin++; | 220 | Uint16 first = *begin++; |
| 221 | 221 | ||
| 222 | // If it's a surrogate pair, first convert to a single UTF-32 character | 222 | // If it's a surrogate pair, first convert to a single UTF-32 character |
| 223 | if ( ( first >= 0xD800 ) && ( first <= 0xDBFF ) ) { | 223 | if ( ( first >= 0xD800 ) && ( first <= 0xDBFF ) ) { |
| 224 | if ( begin < end ) { | 224 | if ( begin < end ) { |
| 225 | Uint32 second = *begin++; | 225 | Uint32 second = *begin++; |
| 226 | if ( ( second >= 0xDC00 ) && ( second <= 0xDFFF ) ) { | 226 | if ( ( second >= 0xDC00 ) && ( second <= 0xDFFF ) ) { |
| 227 | // The second element is valid: convert the two elements to a UTF-32 character | 227 | // The second element is valid: convert the two elements to a UTF-32 character |
| 228 | output = static_cast<Uint32>( ( ( first - 0xD800 ) << 10 ) + ( second - 0xDC00 ) + | 228 | output = static_cast<Uint32>( ( ( first - 0xD800 ) << 10 ) + ( second - 0xDC00 ) + |
| 229 | 0x0010000 ); | 229 | 0x0010000 ); |
| 230 | } else { | 230 | } else { |
| 231 | // Invalid character | 231 | // Invalid character |
| 232 | output = replacement; | 232 | output = replacement; |
| 233 | } | 233 | } |
| 234 | } else { | 234 | } else { |
| 235 | // Invalid character | 235 | // Invalid character |
| 236 | begin = end; | 236 | begin = end; |
| 237 | output = replacement; | 237 | output = replacement; |
| 238 | } | 238 | } |
| 239 | } else { | 239 | } else { |
| 240 | // We can make a direct copy | 240 | // We can make a direct copy |
| 241 | output = first; | 241 | output = first; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | return begin; | 244 | return begin; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | template <typename Out> Out Utf<16>::Encode( Uint32 input, Out output, Uint16 replacement ) { | 247 | template <typename Out> Out Utf<16>::Encode( Uint32 input, Out output, Uint16 replacement ) { |
| 248 | if ( input < 0xFFFF ) { | 248 | if ( input < 0xFFFF ) { |
| 249 | // The character can be copied directly, we just need to check if it's in the valid range | 249 | // The character can be copied directly, we just need to check if it's in the valid range |
| 250 | if ( ( input >= 0xD800 ) && ( input <= 0xDFFF ) ) { | 250 | if ( ( input >= 0xD800 ) && ( input <= 0xDFFF ) ) { |
| 251 | // Invalid character (this range is reserved) | 251 | // Invalid character (this range is reserved) |
| 252 | if ( replacement ) | 252 | if ( replacement ) |
| 253 | *output++ = replacement; | 253 | *output++ = replacement; |
| 254 | } else { | 254 | } else { |
| 255 | // Valid character directly convertible to a single UTF-16 character | 255 | // Valid character directly convertible to a single UTF-16 character |
| 256 | *output++ = static_cast<Uint16>( input ); | 256 | *output++ = static_cast<Uint16>( input ); |
| 257 | } | 257 | } |
| 258 | } else if ( input > 0x0010FFFF ) { | 258 | } else if ( input > 0x0010FFFF ) { |
| 259 | // Invalid character (greater than the maximum unicode value) | 259 | // Invalid character (greater than the maximum unicode value) |
| 260 | if ( replacement ) | 260 | if ( replacement ) |
| 261 | *output++ = replacement; | 261 | *output++ = replacement; |
| 262 | } else { | 262 | } else { |
| 263 | // The input character will be converted to two UTF-16 elements | 263 | // The input character will be converted to two UTF-16 elements |
| 264 | input -= 0x0010000; | 264 | input -= 0x0010000; |
| 265 | *output++ = static_cast<Uint16>( ( input >> 10 ) + 0xD800 ); | 265 | *output++ = static_cast<Uint16>( ( input >> 10 ) + 0xD800 ); |
| 266 | *output++ = static_cast<Uint16>( ( input & 0x3FFUL ) + 0xDC00 ); | 266 | *output++ = static_cast<Uint16>( ( input & 0x3FFUL ) + 0xDC00 ); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | return output; | 269 | return output; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | template <typename In> In Utf<16>::Next( In begin, In end ) { | 272 | template <typename In> In Utf<16>::Next( In begin, In end ) { |
| 273 | Uint32 codepoint; | 273 | Uint32 codepoint; |
| 274 | return Decode( begin, end, codepoint ); | 274 | return Decode( begin, end, codepoint ); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | template <typename In> std::size_t Utf<16>::Count( In begin, In end ) { | 277 | template <typename In> std::size_t Utf<16>::Count( In begin, In end ) { |
| 278 | std::size_t length = 0; | 278 | std::size_t length = 0; |
| 279 | while ( begin < end ) { | 279 | while ( begin < end ) { |
| 280 | begin = Next( begin, end ); | 280 | begin = Next( begin, end ); |
| 281 | ++length; | 281 | ++length; |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | return length; | 284 | return length; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | template <typename In, typename Out> | 287 | template <typename In, typename Out> |
| 288 | Out Utf<16>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { | 288 | Out Utf<16>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { |
| 289 | while ( begin < end ) { | 289 | while ( begin < end ) { |
| 290 | Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); | 290 | Uint32 codepoint = Utf<32>::DecodeAnsi( *begin++, locale ); |
| 291 | output = Encode( codepoint, output ); | 291 | output = Encode( codepoint, output ); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | return output; | 294 | return output; |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | template <typename In, typename Out> Out Utf<16>::FromWide( In begin, In end, Out output ) { | 297 | template <typename In, typename Out> Out Utf<16>::FromWide( In begin, In end, Out output ) { |
| 298 | while ( begin < end ) { | 298 | while ( begin < end ) { |
| 299 | Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); | 299 | Uint32 codepoint = Utf<32>::DecodeWide( *begin++ ); |
| 300 | output = Encode( codepoint, output ); | 300 | output = Encode( codepoint, output ); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | return output; | 303 | return output; |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | template <typename In, typename Out> Out Utf<16>::FromLatin1( In begin, In end, Out output ) { | 306 | template <typename In, typename Out> Out Utf<16>::FromLatin1( In begin, In end, Out output ) { |
| 307 | // Latin-1 is directly compatible with Unicode encodings, | 307 | // Latin-1 is directly compatible with Unicode encodings, |
| 308 | // and can thus be treated as (a sub-range of) UTF-32 | 308 | // and can thus be treated as (a sub-range of) UTF-32 |
| 309 | while ( begin < end ) | 309 | while ( begin < end ) |
| 310 | *output++ = *begin++; | 310 | *output++ = *begin++; |
| 311 | 311 | ||
| 312 | return output; | 312 | return output; |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | template <typename In, typename Out> | 315 | template <typename In, typename Out> |
| 316 | Out Utf<16>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { | 316 | Out Utf<16>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { |
| 317 | while ( begin < end ) { | 317 | while ( begin < end ) { |
| 318 | Uint32 codepoint; | 318 | Uint32 codepoint; |
| 319 | begin = Decode( begin, end, codepoint ); | 319 | begin = Decode( begin, end, codepoint ); |
| 320 | output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); | 320 | output = Utf<32>::EncodeAnsi( codepoint, output, replacement, locale ); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | return output; | 323 | return output; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | #ifndef EFSW_NO_WIDECHAR | 326 | #ifndef EFSW_NO_WIDECHAR |
| 327 | template <typename In, typename Out> | 327 | template <typename In, typename Out> |
| 328 | Out Utf<16>::ToWide( In begin, In end, Out output, wchar_t replacement ) { | 328 | Out Utf<16>::ToWide( In begin, In end, Out output, wchar_t replacement ) { |
| 329 | while ( begin < end ) { | 329 | while ( begin < end ) { |
| 330 | Uint32 codepoint; | 330 | Uint32 codepoint; |
| 331 | begin = Decode( begin, end, codepoint ); | 331 | begin = Decode( begin, end, codepoint ); |
| 332 | output = Utf<32>::EncodeWide( codepoint, output, replacement ); | 332 | output = Utf<32>::EncodeWide( codepoint, output, replacement ); |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | return output; | 335 | return output; |
| 336 | } | 336 | } |
| 337 | #endif | 337 | #endif |
| 338 | 338 | ||
| 339 | template <typename In, typename Out> | 339 | template <typename In, typename Out> |
| 340 | Out Utf<16>::ToLatin1( In begin, In end, Out output, char replacement ) { | 340 | Out Utf<16>::ToLatin1( In begin, In end, Out output, char replacement ) { |
| 341 | // Latin-1 is directly compatible with Unicode encodings, | 341 | // Latin-1 is directly compatible with Unicode encodings, |
| 342 | // and can thus be treated as (a sub-range of) UTF-32 | 342 | // and can thus be treated as (a sub-range of) UTF-32 |
| 343 | while ( begin < end ) { | 343 | while ( begin < end ) { |
| 344 | *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; | 344 | *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; |
| 345 | begin++; | 345 | begin++; |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | return output; | 348 | return output; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | template <typename In, typename Out> Out Utf<16>::toUtf8( In begin, In end, Out output ) { | 351 | template <typename In, typename Out> Out Utf<16>::toUtf8( In begin, In end, Out output ) { |
| 352 | while ( begin < end ) { | 352 | while ( begin < end ) { |
| 353 | Uint32 codepoint; | 353 | Uint32 codepoint; |
| 354 | begin = Decode( begin, end, codepoint ); | 354 | begin = Decode( begin, end, codepoint ); |
| 355 | output = Utf<8>::Encode( codepoint, output ); | 355 | output = Utf<8>::Encode( codepoint, output ); |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | return output; | 358 | return output; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | template <typename In, typename Out> Out Utf<16>::ToUtf16( In begin, In end, Out output ) { | 361 | template <typename In, typename Out> Out Utf<16>::ToUtf16( In begin, In end, Out output ) { |
| 362 | while ( begin < end ) | 362 | while ( begin < end ) |
| 363 | *output++ = *begin++; | 363 | *output++ = *begin++; |
| 364 | 364 | ||
| 365 | return output; | 365 | return output; |
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | template <typename In, typename Out> Out Utf<16>::ToUtf32( In begin, In end, Out output ) { | 368 | template <typename In, typename Out> Out Utf<16>::ToUtf32( In begin, In end, Out output ) { |
| 369 | while ( begin < end ) { | 369 | while ( begin < end ) { |
| 370 | Uint32 codepoint; | 370 | Uint32 codepoint; |
| 371 | begin = Decode( begin, end, codepoint ); | 371 | begin = Decode( begin, end, codepoint ); |
| 372 | *output++ = codepoint; | 372 | *output++ = codepoint; |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | return output; | 375 | return output; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | template <typename In> In Utf<32>::Decode( In begin, In /*end*/, Uint32& output, Uint32 ) { | 378 | template <typename In> In Utf<32>::Decode( In begin, In /*end*/, Uint32& output, Uint32 ) { |
| 379 | output = *begin++; | 379 | output = *begin++; |
| 380 | return begin; | 380 | return begin; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | template <typename Out> Out Utf<32>::Encode( Uint32 input, Out output, Uint32 /*replacement*/ ) { | 383 | template <typename Out> Out Utf<32>::Encode( Uint32 input, Out output, Uint32 /*replacement*/ ) { |
| 384 | *output++ = input; | 384 | *output++ = input; |
| 385 | return output; | 385 | return output; |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | template <typename In> In Utf<32>::Next( In begin, In /*end*/ ) { | 388 | template <typename In> In Utf<32>::Next( In begin, In /*end*/ ) { |
| 389 | return ++begin; | 389 | return ++begin; |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | template <typename In> std::size_t Utf<32>::Count( In begin, In end ) { | 392 | template <typename In> std::size_t Utf<32>::Count( In begin, In end ) { |
| 393 | return begin - end; | 393 | return begin - end; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | template <typename In, typename Out> | 396 | template <typename In, typename Out> |
| 397 | Out Utf<32>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { | 397 | Out Utf<32>::FromAnsi( In begin, In end, Out output, const std::locale& locale ) { |
| 398 | while ( begin < end ) | 398 | while ( begin < end ) |
| 399 | *output++ = DecodeAnsi( *begin++, locale ); | 399 | *output++ = DecodeAnsi( *begin++, locale ); |
| 400 | 400 | ||
| 401 | return output; | 401 | return output; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | template <typename In, typename Out> Out Utf<32>::FromWide( In begin, In end, Out output ) { | 404 | template <typename In, typename Out> Out Utf<32>::FromWide( In begin, In end, Out output ) { |
| 405 | while ( begin < end ) | 405 | while ( begin < end ) |
| 406 | *output++ = DecodeWide( *begin++ ); | 406 | *output++ = DecodeWide( *begin++ ); |
| 407 | 407 | ||
| 408 | return output; | 408 | return output; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | template <typename In, typename Out> Out Utf<32>::FromLatin1( In begin, In end, Out output ) { | 411 | template <typename In, typename Out> Out Utf<32>::FromLatin1( In begin, In end, Out output ) { |
| 412 | // Latin-1 is directly compatible with Unicode encodings, | 412 | // Latin-1 is directly compatible with Unicode encodings, |
| 413 | // and can thus be treated as (a sub-range of) UTF-32 | 413 | // and can thus be treated as (a sub-range of) UTF-32 |
| 414 | while ( begin < end ) | 414 | while ( begin < end ) |
| 415 | *output++ = *begin++; | 415 | *output++ = *begin++; |
| 416 | 416 | ||
| 417 | return output; | 417 | return output; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | template <typename In, typename Out> | 420 | template <typename In, typename Out> |
| 421 | Out Utf<32>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { | 421 | Out Utf<32>::ToAnsi( In begin, In end, Out output, char replacement, const std::locale& locale ) { |
| 422 | while ( begin < end ) | 422 | while ( begin < end ) |
| 423 | output = EncodeAnsi( *begin++, output, replacement, locale ); | 423 | output = EncodeAnsi( *begin++, output, replacement, locale ); |
| 424 | 424 | ||
| 425 | return output; | 425 | return output; |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | #ifndef EFSW_NO_WIDECHAR | 428 | #ifndef EFSW_NO_WIDECHAR |
| 429 | template <typename In, typename Out> | 429 | template <typename In, typename Out> |
| 430 | Out Utf<32>::ToWide( In begin, In end, Out output, wchar_t replacement ) { | 430 | Out Utf<32>::ToWide( In begin, In end, Out output, wchar_t replacement ) { |
| 431 | while ( begin < end ) | 431 | while ( begin < end ) |
| 432 | output = EncodeWide( *begin++, output, replacement ); | 432 | output = EncodeWide( *begin++, output, replacement ); |
| 433 | 433 | ||
| 434 | return output; | 434 | return output; |
| 435 | } | 435 | } |
| 436 | #endif | 436 | #endif |
| 437 | 437 | ||
| 438 | template <typename In, typename Out> | 438 | template <typename In, typename Out> |
| 439 | Out Utf<32>::ToLatin1( In begin, In end, Out output, char replacement ) { | 439 | Out Utf<32>::ToLatin1( In begin, In end, Out output, char replacement ) { |
| 440 | // Latin-1 is directly compatible with Unicode encodings, | 440 | // Latin-1 is directly compatible with Unicode encodings, |
| 441 | // and can thus be treated as (a sub-range of) UTF-32 | 441 | // and can thus be treated as (a sub-range of) UTF-32 |
| 442 | while ( begin < end ) { | 442 | while ( begin < end ) { |
| 443 | *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; | 443 | *output++ = *begin < 256 ? static_cast<char>( *begin ) : replacement; |
| 444 | begin++; | 444 | begin++; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | return output; | 447 | return output; |
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | template <typename In, typename Out> Out Utf<32>::toUtf8( In begin, In end, Out output ) { | 450 | template <typename In, typename Out> Out Utf<32>::toUtf8( In begin, In end, Out output ) { |
| 451 | while ( begin < end ) | 451 | while ( begin < end ) |
| 452 | output = Utf<8>::Encode( *begin++, output ); | 452 | output = Utf<8>::Encode( *begin++, output ); |
| 453 | 453 | ||
| 454 | return output; | 454 | return output; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | template <typename In, typename Out> Out Utf<32>::ToUtf16( In begin, In end, Out output ) { | 457 | template <typename In, typename Out> Out Utf<32>::ToUtf16( In begin, In end, Out output ) { |
| 458 | while ( begin < end ) | 458 | while ( begin < end ) |
| 459 | output = Utf<16>::Encode( *begin++, output ); | 459 | output = Utf<16>::Encode( *begin++, output ); |
| 460 | 460 | ||
| 461 | return output; | 461 | return output; |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | template <typename In, typename Out> Out Utf<32>::ToUtf32( In begin, In end, Out output ) { | 464 | template <typename In, typename Out> Out Utf<32>::ToUtf32( In begin, In end, Out output ) { |
| 465 | while ( begin < end ) | 465 | while ( begin < end ) |
| 466 | *output++ = *begin++; | 466 | *output++ = *begin++; |
| 467 | 467 | ||
| 468 | return output; | 468 | return output; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | template <typename In> Uint32 Utf<32>::DecodeAnsi( In input, const std::locale& locale ) { | 471 | template <typename In> Uint32 Utf<32>::DecodeAnsi( In input, const std::locale& locale ) { |
| 472 | // On Windows, gcc's standard library (glibc++) has almost | 472 | // On Windows, gcc's standard library (glibc++) has almost |
| 473 | // no support for Unicode stuff. As a consequence, in this | 473 | // no support for Unicode stuff. As a consequence, in this |
| 474 | // context we can only use the default locale and ignore | 474 | // context we can only use the default locale and ignore |
| 475 | // the one passed as parameter. | 475 | // the one passed as parameter. |
| 476 | 476 | ||
| 477 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ | 477 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ |
| 478 | ( defined( __GLIBCPP__ ) || \ | 478 | ( defined( __GLIBCPP__ ) || \ |
| 479 | defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ | 479 | defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ |
| 480 | !( defined( __SGI_STL_PORT ) || \ | 480 | !( defined( __SGI_STL_PORT ) || \ |
| 481 | defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ | 481 | defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ |
| 482 | 482 | ||
| 483 | wchar_t character = 0; | 483 | wchar_t character = 0; |
| 484 | mbtowc( &character, &input, 1 ); | 484 | mbtowc( &character, &input, 1 ); |
| 485 | return static_cast<Uint32>( character ); | 485 | return static_cast<Uint32>( character ); |
| 486 | 486 | ||
| 487 | #else | 487 | #else |
| 488 | // Get the facet of the locale which deals with character conversion | 488 | // Get the facet of the locale which deals with character conversion |
| 489 | #ifndef EFSW_NO_WIDECHAR | 489 | #ifndef EFSW_NO_WIDECHAR |
| 490 | const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); | 490 | const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); |
| 491 | #else | 491 | #else |
| 492 | const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); | 492 | const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); |
| 493 | #endif | 493 | #endif |
| 494 | 494 | ||
| 495 | // Use the facet to convert each character of the input string | 495 | // Use the facet to convert each character of the input string |
| 496 | return static_cast<Uint32>( facet.widen( input ) ); | 496 | return static_cast<Uint32>( facet.widen( input ) ); |
| 497 | 497 | ||
| 498 | #endif | 498 | #endif |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | template <typename In> Uint32 Utf<32>::DecodeWide( In input ) { | 501 | template <typename In> Uint32 Utf<32>::DecodeWide( In input ) { |
| 502 | // The encoding of wide characters is not well defined and is left to the system; | 502 | // The encoding of wide characters is not well defined and is left to the system; |
| 503 | // however we can safely assume that it is UCS-2 on Windows and | 503 | // however we can safely assume that it is UCS-2 on Windows and |
| 504 | // UCS-4 on Unix systems. | 504 | // UCS-4 on Unix systems. |
| 505 | // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, | 505 | // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, |
| 506 | // and UCS-4 *is* UTF-32). | 506 | // and UCS-4 *is* UTF-32). |
| 507 | 507 | ||
| 508 | return input; | 508 | return input; |
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | template <typename Out> | 511 | template <typename Out> |
| 512 | Out Utf<32>::EncodeAnsi( Uint32 codepoint, Out output, char replacement, | 512 | Out Utf<32>::EncodeAnsi( Uint32 codepoint, Out output, char replacement, |
| 513 | const std::locale& locale ) { | 513 | const std::locale& locale ) { |
| 514 | // On Windows, gcc's standard library (glibc++) has almost | 514 | // On Windows, gcc's standard library (glibc++) has almost |
| 515 | // no support for Unicode stuff. As a consequence, in this | 515 | // no support for Unicode stuff. As a consequence, in this |
| 516 | // context we can only use the default locale and ignore | 516 | // context we can only use the default locale and ignore |
| 517 | // the one passed as parameter. | 517 | // the one passed as parameter. |
| 518 | 518 | ||
| 519 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ | 519 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \ |
| 520 | ( defined( __GLIBCPP__ ) || \ | 520 | ( defined( __GLIBCPP__ ) || \ |
| 521 | defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ | 521 | defined( __GLIBCXX__ ) ) && /* ... and standard library is glibc++ ... */ \ |
| 522 | !( defined( __SGI_STL_PORT ) || \ | 522 | !( defined( __SGI_STL_PORT ) || \ |
| 523 | defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ | 523 | defined( _STLPORT_VERSION ) ) /* ... and STLPort is not used on top of it */ |
| 524 | 524 | ||
| 525 | char character = 0; | 525 | char character = 0; |
| 526 | if ( wctomb( &character, static_cast<wchar_t>( codepoint ) ) >= 0 ) | 526 | if ( wctomb( &character, static_cast<wchar_t>( codepoint ) ) >= 0 ) |
| 527 | *output++ = character; | 527 | *output++ = character; |
| 528 | else if ( replacement ) | 528 | else if ( replacement ) |
| 529 | *output++ = replacement; | 529 | *output++ = replacement; |
| 530 | 530 | ||
| 531 | return output; | 531 | return output; |
| 532 | 532 | ||
| 533 | #else | 533 | #else |
| 534 | // Get the facet of the locale which deals with character conversion | 534 | // Get the facet of the locale which deals with character conversion |
| 535 | #ifndef EFSW_NO_WIDECHAR | 535 | #ifndef EFSW_NO_WIDECHAR |
| 536 | const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); | 536 | const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t>>( locale ); |
| 537 | #else | 537 | #else |
| 538 | const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); | 538 | const std::ctype<char>& facet = std::use_facet<std::ctype<char>>( locale ); |
| 539 | #endif | 539 | #endif |
| 540 | 540 | ||
| 541 | // Use the facet to convert each character of the input string | 541 | // Use the facet to convert each character of the input string |
| 542 | *output++ = facet.narrow( static_cast<wchar_t>( codepoint ), replacement ); | 542 | *output++ = facet.narrow( static_cast<wchar_t>( codepoint ), replacement ); |
| 543 | 543 | ||
| 544 | return output; | 544 | return output; |
| 545 | 545 | ||
| 546 | #endif | 546 | #endif |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | #ifndef EFSW_NO_WIDECHAR | 549 | #ifndef EFSW_NO_WIDECHAR |
| 550 | template <typename Out> | 550 | template <typename Out> |
| 551 | Out Utf<32>::EncodeWide( Uint32 codepoint, Out output, wchar_t replacement ) { | 551 | Out Utf<32>::EncodeWide( Uint32 codepoint, Out output, wchar_t replacement ) { |
| 552 | // The encoding of wide characters is not well defined and is left to the system; | 552 | // The encoding of wide characters is not well defined and is left to the system; |
| 553 | // however we can safely assume that it is UCS-2 on Windows and | 553 | // however we can safely assume that it is UCS-2 on Windows and |
| 554 | // UCS-4 on Unix systems. | 554 | // UCS-4 on Unix systems. |
| 555 | // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). | 555 | // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). |
| 556 | // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). | 556 | // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). |
| 557 | 557 | ||
| 558 | switch ( sizeof( wchar_t ) ) { | 558 | switch ( sizeof( wchar_t ) ) { |
| 559 | case 4: { | 559 | case 4: { |
| 560 | *output++ = static_cast<wchar_t>( codepoint ); | 560 | *output++ = static_cast<wchar_t>( codepoint ); |
| 561 | break; | 561 | break; |
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | default: { | 564 | default: { |
| 565 | if ( ( codepoint <= 0xFFFF ) && ( ( codepoint < 0xD800 ) || ( codepoint > 0xDFFF ) ) ) { | 565 | if ( ( codepoint <= 0xFFFF ) && ( ( codepoint < 0xD800 ) || ( codepoint > 0xDFFF ) ) ) { |
| 566 | *output++ = static_cast<wchar_t>( codepoint ); | 566 | *output++ = static_cast<wchar_t>( codepoint ); |
| 567 | } else if ( replacement ) { | 567 | } else if ( replacement ) { |
| 568 | *output++ = replacement; | 568 | *output++ = replacement; |
| 569 | } | 569 | } |
| 570 | break; | 570 | break; |
| 571 | } | 571 | } |
| 572 | } | 572 | } |
| 573 | 573 | ||
| 574 | return output; | 574 | return output; |
| 575 | } | 575 | } |
| 576 | #endif | 576 | #endif |
diff --git a/src/3rdParty/efsw/Watcher.cpp b/src/3rdParty/efsw/Watcher.cpp index 913ae3c..913ae3c 100755..100644 --- a/src/3rdParty/efsw/Watcher.cpp +++ b/src/3rdParty/efsw/Watcher.cpp | |||
diff --git a/src/3rdParty/efsw/Watcher.hpp b/src/3rdParty/efsw/Watcher.hpp index 84f0980..84f0980 100755..100644 --- a/src/3rdParty/efsw/Watcher.hpp +++ b/src/3rdParty/efsw/Watcher.hpp | |||
diff --git a/src/3rdParty/efsw/WatcherFSEvents.cpp b/src/3rdParty/efsw/WatcherFSEvents.cpp index b562d3c..f963374 100755..100644 --- a/src/3rdParty/efsw/WatcherFSEvents.cpp +++ b/src/3rdParty/efsw/WatcherFSEvents.cpp | |||
| @@ -8,22 +8,11 @@ | |||
| 8 | namespace efsw { | 8 | namespace efsw { |
| 9 | 9 | ||
| 10 | WatcherFSEvents::WatcherFSEvents() : | 10 | WatcherFSEvents::WatcherFSEvents() : |
| 11 | Watcher(), FWatcher( NULL ), FSStream( NULL ), WatcherGen( NULL ), initializedAsync( false ) {} | 11 | Watcher(), FWatcher( NULL ), FSStream( NULL ), WatcherGen( NULL ) {} |
| 12 | |||
| 13 | WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener, | ||
| 14 | bool recursive, WatcherFSEvents* /*parent*/ ) : | ||
| 15 | Watcher( id, directory, listener, recursive ), | ||
| 16 | FWatcher( NULL ), | ||
| 17 | FSStream( NULL ), | ||
| 18 | WatcherGen( NULL ), | ||
| 19 | initializedAsync( false ) {} | ||
| 20 | 12 | ||
| 21 | WatcherFSEvents::~WatcherFSEvents() { | 13 | WatcherFSEvents::~WatcherFSEvents() { |
| 22 | if ( NULL != FSStream ) { | 14 | if ( NULL != FSStream ) { |
| 23 | if ( initializedAsync ) { | 15 | FSEventStreamStop( FSStream ); |
| 24 | FSEventStreamStop( FSStream ); | ||
| 25 | } | ||
| 26 | |||
| 27 | FSEventStreamInvalidate( FSStream ); | 16 | FSEventStreamInvalidate( FSStream ); |
| 28 | FSEventStreamRelease( FSStream ); | 17 | FSEventStreamRelease( FSStream ); |
| 29 | } | 18 | } |
| @@ -39,7 +28,9 @@ void WatcherFSEvents::init() { | |||
| 39 | Uint32 streamFlags = kFSEventStreamCreateFlagNone; | 28 | Uint32 streamFlags = kFSEventStreamCreateFlagNone; |
| 40 | 29 | ||
| 41 | if ( FileWatcherFSEvents::isGranular() ) { | 30 | if ( FileWatcherFSEvents::isGranular() ) { |
| 42 | streamFlags = efswFSEventStreamCreateFlagFileEvents; | 31 | streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer | |
| 32 | efswFSEventStreamCreateFlagUseExtendedData | | ||
| 33 | efswFSEventStreamCreateFlagUseCFTypes; | ||
| 43 | } else { | 34 | } else { |
| 44 | WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive ); | 35 | WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive ); |
| 45 | } | 36 | } |
| @@ -52,49 +43,49 @@ void WatcherFSEvents::init() { | |||
| 52 | ctx.release = NULL; | 43 | ctx.release = NULL; |
| 53 | ctx.copyDescription = NULL; | 44 | ctx.copyDescription = NULL; |
| 54 | 45 | ||
| 46 | dispatch_queue_t queue = dispatch_queue_create( NULL, NULL ); | ||
| 47 | |||
| 55 | FSStream = | 48 | FSStream = |
| 56 | FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, | 49 | FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, |
| 57 | CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0.25, streamFlags ); | 50 | CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0., streamFlags ); |
| 58 | FWatcher.load()->mNeedInitMutex.lock(); | ||
| 59 | FWatcher.load()->mNeedInit.push_back( this ); | ||
| 60 | FWatcher.load()->mNeedInitMutex.unlock(); | ||
| 61 | 51 | ||
| 62 | CFRelease( CFDirectoryArray ); | 52 | FSEventStreamSetDispatchQueue( FSStream, queue ); |
| 63 | CFRelease( CFDirectory ); | ||
| 64 | } | ||
| 65 | 53 | ||
| 66 | void WatcherFSEvents::initAsync() { | ||
| 67 | FSEventStreamScheduleWithRunLoop( FSStream, FWatcher.load()->mRunLoopRef.load(), | ||
| 68 | kCFRunLoopDefaultMode ); | ||
| 69 | FSEventStreamStart( FSStream ); | 54 | FSEventStreamStart( FSStream ); |
| 70 | initializedAsync = true; | 55 | |
| 56 | CFRelease( CFDirectoryArray ); | ||
| 57 | CFRelease( CFDirectory ); | ||
| 71 | } | 58 | } |
| 72 | 59 | ||
| 73 | void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, | 60 | void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, |
| 74 | const std::string& filename, Action action, | 61 | const std::string& filename, Action action, |
| 75 | std::string oldFilename ) { | 62 | std::string oldFilename ) { |
| 76 | Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), | 63 | Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), |
| 77 | FileSystem::precomposeFileName( filename ), action, oldFilename ); | 64 | FileSystem::precomposeFileName( filename ), action, |
| 65 | FileSystem::precomposeFileName( oldFilename ) ); | ||
| 78 | } | 66 | } |
| 79 | 67 | ||
| 80 | void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, | 68 | void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, |
| 81 | std::string& dirPath, std::string& filePath ) { | 69 | std::string& dirPath, std::string& filePath, Uint64 inode ) { |
| 82 | if ( flags & efswFSEventStreamEventFlagItemCreated ) { | 70 | if ( ( flags & efswFSEventStreamEventFlagItemCreated ) && FileInfo::exists( path ) && |
| 83 | if ( FileInfo::exists( path ) ) { | 71 | ( !SanitizeEvents || FilesAdded.find( inode ) != FilesAdded.end() ) ) { |
| 84 | sendFileAction( ID, dirPath, filePath, Actions::Add ); | 72 | sendFileAction( ID, dirPath, filePath, Actions::Add ); |
| 85 | } | 73 | |
| 74 | if ( SanitizeEvents ) | ||
| 75 | FilesAdded.insert( inode ); | ||
| 86 | } | 76 | } |
| 87 | 77 | ||
| 88 | if ( flags & efswFSEventsModified ) { | 78 | if ( flags & ModifiedFlags ) { |
| 89 | sendFileAction( ID, dirPath, filePath, Actions::Modified ); | 79 | sendFileAction( ID, dirPath, filePath, Actions::Modified ); |
| 90 | } | 80 | } |
| 91 | 81 | ||
| 92 | if ( flags & efswFSEventStreamEventFlagItemRemoved ) { | 82 | if ( ( flags & efswFSEventStreamEventFlagItemRemoved ) && !FileInfo::exists( path ) ) { |
| 93 | // Since i don't know the order, at least i try to keep the data consistent with the real | 83 | // Since i don't know the order, at least i try to keep the data consistent with the real |
| 94 | // state | 84 | // state |
| 95 | if ( !FileInfo::exists( path ) ) { | 85 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); |
| 96 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); | 86 | |
| 97 | } | 87 | if ( SanitizeEvents ) |
| 88 | FilesAdded.erase( inode ); | ||
| 98 | } | 89 | } |
| 99 | } | 90 | } |
| 100 | 91 | ||
| @@ -136,19 +127,20 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) { | |||
| 136 | // been added modified and erased, but i can't know if first was erased and then added | 127 | // been added modified and erased, but i can't know if first was erased and then added |
| 137 | // and modified, or added, then modified and then erased. I don't know what they were | 128 | // and modified, or added, then modified and then erased. I don't know what they were |
| 138 | // thinking by doing this... | 129 | // thinking by doing this... |
| 139 | efDEBUG( "Event in: %s - flags: %ld\n", event.Path.c_str(), event.Flags ); | 130 | efDEBUG( "Event in: %s - flags: 0x%x\n", event.Path.c_str(), event.Flags ); |
| 140 | 131 | ||
| 141 | if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) { | 132 | if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) { |
| 142 | if ( ( i + 1 < esize ) && | 133 | if ( ( i + 1 < esize ) && |
| 143 | ( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) && | 134 | ( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) && |
| 144 | ( events[i + 1].Id == event.Id + 1 ) ) { | 135 | ( events[i + 1].inode == event.inode ) ) { |
| 145 | FSEvent& nEvent = events[i + 1]; | 136 | FSEvent& nEvent = events[i + 1]; |
| 146 | std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) ); | 137 | std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) ); |
| 147 | std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) ); | 138 | std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) ); |
| 148 | 139 | ||
| 149 | if ( event.Path != nEvent.Path ) { | 140 | if ( event.Path != nEvent.Path ) { |
| 150 | if ( dirPath == newDir ) { | 141 | if ( dirPath == newDir ) { |
| 151 | if ( !FileInfo::exists( event.Path ) ) { | 142 | if ( !FileInfo::exists( event.Path ) || |
| 143 | 0 == strcasecmp( event.Path.c_str(), nEvent.Path.c_str() ) ) { | ||
| 152 | sendFileAction( ID, dirPath, newFilepath, Actions::Moved, | 144 | sendFileAction( ID, dirPath, newFilepath, Actions::Moved, |
| 153 | filePath ); | 145 | filePath ); |
| 154 | } else { | 146 | } else { |
| @@ -159,12 +151,12 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) { | |||
| 159 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); | 151 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); |
| 160 | sendFileAction( ID, newDir, newFilepath, Actions::Add ); | 152 | sendFileAction( ID, newDir, newFilepath, Actions::Add ); |
| 161 | 153 | ||
| 162 | if ( nEvent.Flags & efswFSEventsModified ) { | 154 | if ( nEvent.Flags & ModifiedFlags ) { |
| 163 | sendFileAction( ID, newDir, newFilepath, Actions::Modified ); | 155 | sendFileAction( ID, newDir, newFilepath, Actions::Modified ); |
| 164 | } | 156 | } |
| 165 | } | 157 | } |
| 166 | } else { | 158 | } else { |
| 167 | handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath ); | 159 | handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath, event.inode ); |
| 168 | } | 160 | } |
| 169 | 161 | ||
| 170 | if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated | | 162 | if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated | |
| @@ -180,14 +172,14 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) { | |||
| 180 | } else if ( FileInfo::exists( event.Path ) ) { | 172 | } else if ( FileInfo::exists( event.Path ) ) { |
| 181 | sendFileAction( ID, dirPath, filePath, Actions::Add ); | 173 | sendFileAction( ID, dirPath, filePath, Actions::Add ); |
| 182 | 174 | ||
| 183 | if ( event.Flags & efswFSEventsModified ) { | 175 | if ( event.Flags & ModifiedFlags ) { |
| 184 | sendFileAction( ID, dirPath, filePath, Actions::Modified ); | 176 | sendFileAction( ID, dirPath, filePath, Actions::Modified ); |
| 185 | } | 177 | } |
| 186 | } else { | 178 | } else { |
| 187 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); | 179 | sendFileAction( ID, dirPath, filePath, Actions::Delete ); |
| 188 | } | 180 | } |
| 189 | } else { | 181 | } else { |
| 190 | handleAddModDel( event.Flags, event.Path, dirPath, filePath ); | 182 | handleAddModDel( event.Flags, event.Path, dirPath, filePath, event.inode ); |
| 191 | } | 183 | } |
| 192 | } else { | 184 | } else { |
| 193 | efDEBUG( "Directory: %s changed\n", event.Path.c_str() ); | 185 | efDEBUG( "Directory: %s changed\n", event.Path.c_str() ); |
| @@ -197,7 +189,7 @@ void WatcherFSEvents::handleActions( std::vector<FSEvent>& events ) { | |||
| 197 | } | 189 | } |
| 198 | 190 | ||
| 199 | void WatcherFSEvents::process() { | 191 | void WatcherFSEvents::process() { |
| 200 | std::set<std::string>::iterator it = DirsChanged.begin(); | 192 | std::unordered_set<std::string>::iterator it = DirsChanged.begin(); |
| 201 | 193 | ||
| 202 | for ( ; it != DirsChanged.end(); it++ ) { | 194 | for ( ; it != DirsChanged.end(); it++ ) { |
| 203 | if ( !FileWatcherFSEvents::isGranular() ) { | 195 | if ( !FileWatcherFSEvents::isGranular() ) { |
diff --git a/src/3rdParty/efsw/WatcherFSEvents.hpp b/src/3rdParty/efsw/WatcherFSEvents.hpp index 4dbb231..f05b094 100755..100644 --- a/src/3rdParty/efsw/WatcherFSEvents.hpp +++ b/src/3rdParty/efsw/WatcherFSEvents.hpp | |||
| @@ -9,51 +9,72 @@ | |||
| 9 | #include <CoreServices/CoreServices.h> | 9 | #include <CoreServices/CoreServices.h> |
| 10 | #include <efsw/FileInfo.hpp> | 10 | #include <efsw/FileInfo.hpp> |
| 11 | #include <efsw/WatcherGeneric.hpp> | 11 | #include <efsw/WatcherGeneric.hpp> |
| 12 | #include <set> | 12 | #include <unordered_set> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | 14 | ||
| 15 | namespace efsw { | 15 | namespace efsw { |
| 16 | 16 | ||
| 17 | /* OSX < 10.7 has no file events */ | ||
| 18 | /* So i declare the events constants */ | ||
| 19 | enum FSEventEvents { | ||
| 20 | efswFSEventStreamCreateFlagUseCFTypes = 0x00000001, | ||
| 21 | efswFSEventStreamCreateFlagNoDefer = 0x00000002, | ||
| 22 | efswFSEventStreamCreateFlagFileEvents = 0x00000010, | ||
| 23 | efswFSEventStreamCreateFlagUseExtendedData = 0x00000040, | ||
| 24 | efswFSEventStreamEventFlagItemCreated = 0x00000100, | ||
| 25 | efswFSEventStreamEventFlagItemRemoved = 0x00000200, | ||
| 26 | efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, | ||
| 27 | efswFSEventStreamEventFlagItemRenamed = 0x00000800, | ||
| 28 | efswFSEventStreamEventFlagItemModified = 0x00001000, | ||
| 29 | efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, | ||
| 30 | efswFSEventStreamEventFlagItemChangeOwner = 0x00004000, | ||
| 31 | efswFSEventStreamEventFlagItemXattrMod = 0x00008000, | ||
| 32 | efswFSEventStreamEventFlagItemIsFile = 0x00010000, | ||
| 33 | efswFSEventStreamEventFlagItemIsDir = 0x00020000, | ||
| 34 | efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, | ||
| 35 | efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | | ||
| 36 | efswFSEventStreamEventFlagItemModified | | ||
| 37 | efswFSEventStreamEventFlagItemInodeMetaMod | ||
| 38 | }; | ||
| 39 | |||
| 17 | class FileWatcherFSEvents; | 40 | class FileWatcherFSEvents; |
| 18 | 41 | ||
| 19 | class FSEvent { | 42 | class FSEvent { |
| 20 | public: | 43 | public: |
| 21 | FSEvent( std::string path, long flags, Uint64 id ) : Path( path ), Flags( flags ), Id( id ) {} | 44 | FSEvent( std::string path, long flags, Uint64 id, Uint64 inode = 0 ) : |
| 45 | Path( path ), Flags( flags ), Id( id ), inode( inode ) {} | ||
| 22 | 46 | ||
| 23 | std::string Path; | 47 | std::string Path; |
| 24 | long Flags; | 48 | long Flags{ 0 }; |
| 25 | Uint64 Id; | 49 | Uint64 Id{ 0 }; |
| 50 | Uint64 inode{ 0 }; | ||
| 26 | }; | 51 | }; |
| 27 | 52 | ||
| 28 | class WatcherFSEvents : public Watcher { | 53 | class WatcherFSEvents : public Watcher { |
| 29 | public: | 54 | public: |
| 30 | WatcherFSEvents(); | 55 | WatcherFSEvents(); |
| 31 | 56 | ||
| 32 | WatcherFSEvents( WatchID id, std::string directory, FileWatchListener* listener, bool recursive, | ||
| 33 | WatcherFSEvents* parent = NULL ); | ||
| 34 | |||
| 35 | ~WatcherFSEvents(); | 57 | ~WatcherFSEvents(); |
| 36 | 58 | ||
| 37 | void init(); | 59 | void init(); |
| 38 | 60 | ||
| 39 | void initAsync(); | ||
| 40 | |||
| 41 | void handleActions( std::vector<FSEvent>& events ); | 61 | void handleActions( std::vector<FSEvent>& events ); |
| 42 | 62 | ||
| 43 | void process(); | 63 | void process(); |
| 44 | 64 | ||
| 45 | Atomic<FileWatcherFSEvents*> FWatcher; | 65 | Atomic<FileWatcherFSEvents*> FWatcher; |
| 46 | FSEventStreamRef FSStream; | 66 | FSEventStreamRef FSStream; |
| 67 | Uint64 ModifiedFlags{ efswFSEventsModified }; | ||
| 68 | bool SanitizeEvents{ false }; | ||
| 47 | 69 | ||
| 48 | protected: | 70 | protected: |
| 49 | void handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, | 71 | void handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, |
| 50 | std::string& filePath ); | 72 | std::string& filePath, Uint64 inode ); |
| 51 | 73 | ||
| 52 | WatcherGeneric* WatcherGen; | 74 | WatcherGeneric* WatcherGen; |
| 53 | 75 | ||
| 54 | Atomic<bool> initializedAsync; | 76 | std::unordered_set<std::string> DirsChanged; |
| 55 | 77 | std::unordered_set<Uint64> FilesAdded; | |
| 56 | std::set<std::string> DirsChanged; | ||
| 57 | 78 | ||
| 58 | void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, | 79 | void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, |
| 59 | Action action, std::string oldFilename = "" ); | 80 | Action action, std::string oldFilename = "" ); |
diff --git a/src/3rdParty/efsw/WatcherGeneric.cpp b/src/3rdParty/efsw/WatcherGeneric.cpp index a6bb106..a6bb106 100755..100644 --- a/src/3rdParty/efsw/WatcherGeneric.cpp +++ b/src/3rdParty/efsw/WatcherGeneric.cpp | |||
diff --git a/src/3rdParty/efsw/WatcherGeneric.hpp b/src/3rdParty/efsw/WatcherGeneric.hpp index 9cf8365..d11ec20 100755..100644 --- a/src/3rdParty/efsw/WatcherGeneric.hpp +++ b/src/3rdParty/efsw/WatcherGeneric.hpp | |||
| @@ -17,7 +17,7 @@ class WatcherGeneric : public Watcher { | |||
| 17 | 17 | ||
| 18 | ~WatcherGeneric(); | 18 | ~WatcherGeneric(); |
| 19 | 19 | ||
| 20 | void watch(); | 20 | void watch() override; |
| 21 | 21 | ||
| 22 | void watchDir( std::string dir ); | 22 | void watchDir( std::string dir ); |
| 23 | 23 | ||
diff --git a/src/3rdParty/efsw/WatcherInotify.cpp b/src/3rdParty/efsw/WatcherInotify.cpp index 7259bb1..812ddae 100755..100644 --- a/src/3rdParty/efsw/WatcherInotify.cpp +++ b/src/3rdParty/efsw/WatcherInotify.cpp | |||
| @@ -4,10 +4,6 @@ namespace efsw { | |||
| 4 | 4 | ||
| 5 | WatcherInotify::WatcherInotify() : Watcher(), Parent( NULL ) {} | 5 | WatcherInotify::WatcherInotify() : Watcher(), Parent( NULL ) {} |
| 6 | 6 | ||
| 7 | WatcherInotify::WatcherInotify( WatchID id, std::string directory, FileWatchListener* listener, | ||
| 8 | bool recursive, WatcherInotify* parent ) : | ||
| 9 | Watcher( id, directory, listener, recursive ), Parent( parent ), DirInfo( directory ) {} | ||
| 10 | |||
| 11 | bool WatcherInotify::inParentTree( WatcherInotify* parent ) { | 7 | bool WatcherInotify::inParentTree( WatcherInotify* parent ) { |
| 12 | WatcherInotify* tNext = Parent; | 8 | WatcherInotify* tNext = Parent; |
| 13 | 9 | ||
diff --git a/src/3rdParty/efsw/WatcherInotify.hpp b/src/3rdParty/efsw/WatcherInotify.hpp index bf2ff5e..ec55ed0 100755..100644 --- a/src/3rdParty/efsw/WatcherInotify.hpp +++ b/src/3rdParty/efsw/WatcherInotify.hpp | |||
| @@ -10,15 +10,13 @@ class WatcherInotify : public Watcher { | |||
| 10 | public: | 10 | public: |
| 11 | WatcherInotify(); | 11 | WatcherInotify(); |
| 12 | 12 | ||
| 13 | WatcherInotify( WatchID id, std::string directory, FileWatchListener* listener, bool recursive, | ||
| 14 | WatcherInotify* parent = NULL ); | ||
| 15 | |||
| 16 | bool inParentTree( WatcherInotify* parent ); | 13 | bool inParentTree( WatcherInotify* parent ); |
| 17 | 14 | ||
| 18 | WatcherInotify* Parent; | 15 | WatcherInotify* Parent; |
| 19 | WatchID InotifyID; | 16 | WatchID InotifyID; |
| 20 | 17 | ||
| 21 | FileInfo DirInfo; | 18 | FileInfo DirInfo; |
| 19 | bool syntheticEvents{ false }; | ||
| 22 | }; | 20 | }; |
| 23 | 21 | ||
| 24 | } // namespace efsw | 22 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/WatcherKqueue.cpp b/src/3rdParty/efsw/WatcherKqueue.cpp index 441948a..424b989 100755..100644 --- a/src/3rdParty/efsw/WatcherKqueue.cpp +++ b/src/3rdParty/efsw/WatcherKqueue.cpp | |||
| @@ -139,7 +139,7 @@ void WatcherKqueue::addAll() { | |||
| 139 | void WatcherKqueue::removeAll() { | 139 | void WatcherKqueue::removeAll() { |
| 140 | efDEBUG( "removeAll(): Removing all child watchers\n" ); | 140 | efDEBUG( "removeAll(): Removing all child watchers\n" ); |
| 141 | 141 | ||
| 142 | std::list<WatchID> erase; | 142 | std::vector<WatchID> erase; |
| 143 | 143 | ||
| 144 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) { | 144 | for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) { |
| 145 | efDEBUG( "removeAll(): Removed child watcher %s\n", it->second->Directory.c_str() ); | 145 | efDEBUG( "removeAll(): Removed child watcher %s\n", it->second->Directory.c_str() ); |
| @@ -147,7 +147,7 @@ void WatcherKqueue::removeAll() { | |||
| 147 | erase.push_back( it->second->ID ); | 147 | erase.push_back( it->second->ID ); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | for ( std::list<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ ) { | 150 | for ( std::vector<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ ) { |
| 151 | removeWatch( *eit ); | 151 | removeWatch( *eit ); |
| 152 | } | 152 | } |
| 153 | } | 153 | } |
| @@ -354,7 +354,8 @@ void WatcherKqueue::watch() { | |||
| 354 | bool needScan = false; | 354 | bool needScan = false; |
| 355 | 355 | ||
| 356 | // Then we get the the events of the current folder | 356 | // Then we get the the events of the current folder |
| 357 | while ( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1, | 357 | while ( !mChangeList.empty() && |
| 358 | ( nev = kevent( mKqueue, mChangeList.data(), mChangeListCount + 1, &event, 1, | ||
| 358 | &mWatcher->mTimeOut ) ) != 0 ) { | 359 | &mWatcher->mTimeOut ) ) != 0 ) { |
| 359 | // An error ocurred? | 360 | // An error ocurred? |
| 360 | if ( nev == -1 ) { | 361 | if ( nev == -1 ) { |
| @@ -436,7 +437,6 @@ void WatcherKqueue::moveDirectory( std::string oldPath, std::string newPath, boo | |||
| 436 | 437 | ||
| 437 | WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, | 438 | WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 438 | bool recursive, WatcherKqueue* parent ) { | 439 | bool recursive, WatcherKqueue* parent ) { |
| 439 | static long s_fc = 0; | ||
| 440 | static bool s_ug = false; | 440 | static bool s_ug = false; |
| 441 | 441 | ||
| 442 | std::string dir( directory ); | 442 | std::string dir( directory ); |
| @@ -478,8 +478,6 @@ WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener | |||
| 478 | 478 | ||
| 479 | watch->addAll(); | 479 | watch->addAll(); |
| 480 | 480 | ||
| 481 | s_fc++; | ||
| 482 | |||
| 483 | // if failed to open the directory... erase the watcher | 481 | // if failed to open the directory... erase the watcher |
| 484 | if ( !watch->initOK() ) { | 482 | if ( !watch->initOK() ) { |
| 485 | int le = watch->lastErrno(); | 483 | int le = watch->lastErrno(); |
| @@ -502,9 +500,8 @@ WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener | |||
| 502 | } | 500 | } |
| 503 | } else { | 501 | } else { |
| 504 | if ( !s_ug ) { | 502 | if ( !s_ug ) { |
| 505 | efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld. Folders " | 503 | efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld.\n", |
| 506 | "added: %ld\n", | 504 | mWatcher->mFileDescriptorCount ); |
| 507 | mWatcher->mFileDescriptorCount, s_fc ); | ||
| 508 | s_ug = true; | 505 | s_ug = true; |
| 509 | } | 506 | } |
| 510 | 507 | ||
diff --git a/src/3rdParty/efsw/WatcherKqueue.hpp b/src/3rdParty/efsw/WatcherKqueue.hpp index 87d898c..75c0f62 100755..100644 --- a/src/3rdParty/efsw/WatcherKqueue.hpp +++ b/src/3rdParty/efsw/WatcherKqueue.hpp | |||
| @@ -49,7 +49,7 @@ class WatcherKqueue : public Watcher { | |||
| 49 | 49 | ||
| 50 | WatchID watchingDirectory( std::string dir ); | 50 | WatchID watchingDirectory( std::string dir ); |
| 51 | 51 | ||
| 52 | void watch(); | 52 | void watch() override; |
| 53 | 53 | ||
| 54 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, | 54 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 55 | WatcherKqueue* parent ); | 55 | WatcherKqueue* parent ); |
diff --git a/src/3rdParty/efsw/WatcherWin32.cpp b/src/3rdParty/efsw/WatcherWin32.cpp index 3e8bcc7..712419e 100755..100644 --- a/src/3rdParty/efsw/WatcherWin32.cpp +++ b/src/3rdParty/efsw/WatcherWin32.cpp | |||
| @@ -1,34 +1,114 @@ | |||
| 1 | #include <efsw/Debug.hpp> | ||
| 1 | #include <efsw/String.hpp> | 2 | #include <efsw/String.hpp> |
| 2 | #include <efsw/WatcherWin32.hpp> | 3 | #include <efsw/WatcherWin32.hpp> |
| 3 | 4 | ||
| 4 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 | 5 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 |
| 5 | 6 | ||
| 7 | #include <algorithm> | ||
| 8 | |||
| 6 | namespace efsw { | 9 | namespace efsw { |
| 7 | 10 | ||
| 8 | /// Unpacks events and passes them to a user defined callback. | 11 | struct EFSW_FILE_NOTIFY_EXTENDED_INFORMATION_EX { |
| 9 | void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) { | 12 | DWORD NextEntryOffset; |
| 10 | if ( dwNumberOfBytesTransfered == 0 || NULL == lpOverlapped ) { | 13 | DWORD Action; |
| 11 | return; | 14 | LARGE_INTEGER CreationTime; |
| 15 | LARGE_INTEGER LastModificationTime; | ||
| 16 | LARGE_INTEGER LastChangeTime; | ||
| 17 | LARGE_INTEGER LastAccessTime; | ||
| 18 | LARGE_INTEGER AllocatedLength; | ||
| 19 | LARGE_INTEGER FileSize; | ||
| 20 | DWORD FileAttributes; | ||
| 21 | DWORD ReparsePointTag; | ||
| 22 | LARGE_INTEGER FileId; | ||
| 23 | LARGE_INTEGER ParentFileId; | ||
| 24 | DWORD FileNameLength; | ||
| 25 | WCHAR FileName[1]; | ||
| 26 | }; | ||
| 27 | |||
| 28 | typedef EFSW_FILE_NOTIFY_EXTENDED_INFORMATION_EX* EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX; | ||
| 29 | |||
| 30 | typedef BOOL( WINAPI* EFSW_LPREADDIRECTORYCHANGESEXW )( HANDLE hDirectory, LPVOID lpBuffer, | ||
| 31 | DWORD nBufferLength, BOOL bWatchSubtree, | ||
| 32 | DWORD dwNotifyFilter, LPDWORD lpBytesReturned, | ||
| 33 | LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, | ||
| 34 | DWORD ReadDirectoryNotifyInformationClass ); | ||
| 35 | |||
| 36 | static EFSW_LPREADDIRECTORYCHANGESEXW pReadDirectoryChangesExW = NULL; | ||
| 37 | |||
| 38 | #define EFSW_ReadDirectoryNotifyExtendedInformation 2 | ||
| 39 | |||
| 40 | static void initReadDirectoryChangesEx() { | ||
| 41 | static bool hasInit = false; | ||
| 42 | if ( !hasInit ) { | ||
| 43 | hasInit = true; | ||
| 44 | |||
| 45 | HMODULE hModule = GetModuleHandleW( L"Kernel32.dll" ); | ||
| 46 | if ( !hModule ) | ||
| 47 | return; | ||
| 48 | |||
| 49 | pReadDirectoryChangesExW = | ||
| 50 | (EFSW_LPREADDIRECTORYCHANGESEXW)GetProcAddress( hModule, "ReadDirectoryChangesExW" ); | ||
| 12 | } | 51 | } |
| 52 | } | ||
| 13 | 53 | ||
| 14 | char szFile[MAX_PATH]; | 54 | void WatchCallbackOld( WatcherWin32* pWatch ) { |
| 15 | PFILE_NOTIFY_INFORMATION pNotify; | 55 | PFILE_NOTIFY_INFORMATION pNotify; |
| 16 | WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped; | ||
| 17 | WatcherWin32* pWatch = tWatch->Watch; | ||
| 18 | size_t offset = 0; | 56 | size_t offset = 0; |
| 19 | |||
| 20 | do { | 57 | do { |
| 21 | bool skip = false; | 58 | bool skip = false; |
| 22 | 59 | ||
| 23 | pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset]; | 60 | pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset]; |
| 24 | offset += pNotify->NextEntryOffset; | 61 | offset += pNotify->NextEntryOffset; |
| 62 | int count = | ||
| 63 | WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, | ||
| 64 | pNotify->FileNameLength / sizeof( WCHAR ), NULL, 0, NULL, NULL ); | ||
| 65 | if ( count == 0 ) | ||
| 66 | continue; | ||
| 67 | |||
| 68 | std::string nfile( count, '\0' ); | ||
| 69 | |||
| 70 | count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, | ||
| 71 | pNotify->FileNameLength / sizeof( WCHAR ), &nfile[0], count, | ||
| 72 | NULL, NULL ); | ||
| 73 | |||
| 74 | if ( FILE_ACTION_MODIFIED == pNotify->Action ) { | ||
| 75 | FileInfo fifile( std::string( pWatch->DirName ) + nfile ); | ||
| 76 | |||
| 77 | if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && | ||
| 78 | pWatch->LastModifiedEvent.file.Size == fifile.Size && | ||
| 79 | pWatch->LastModifiedEvent.fileName == nfile ) { | ||
| 80 | skip = true; | ||
| 81 | } | ||
| 82 | |||
| 83 | pWatch->LastModifiedEvent.fileName = nfile; | ||
| 84 | pWatch->LastModifiedEvent.file = fifile; | ||
| 85 | } | ||
| 86 | |||
| 87 | if ( !skip ) { | ||
| 88 | pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action ); | ||
| 89 | } | ||
| 90 | } while ( pNotify->NextEntryOffset != 0 ); | ||
| 91 | } | ||
| 92 | |||
| 93 | void WatchCallbackEx( WatcherWin32* pWatch ) { | ||
| 94 | EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX pNotify; | ||
| 95 | size_t offset = 0; | ||
| 96 | do { | ||
| 97 | bool skip = false; | ||
| 98 | |||
| 99 | pNotify = (EFSW_PFILE_NOTIFY_EXTENDED_INFORMATION_EX)&pWatch->Buffer[offset]; | ||
| 100 | offset += pNotify->NextEntryOffset; | ||
| 101 | int count = | ||
| 102 | WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, | ||
| 103 | pNotify->FileNameLength / sizeof( WCHAR ), NULL, 0, NULL, NULL ); | ||
| 104 | if ( count == 0 ) | ||
| 105 | continue; | ||
| 25 | 106 | ||
| 26 | int count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, | 107 | std::string nfile( count, '\0' ); |
| 27 | pNotify->FileNameLength / sizeof( WCHAR ), szFile, | ||
| 28 | MAX_PATH - 1, NULL, NULL ); | ||
| 29 | szFile[count] = TEXT( '\0' ); | ||
| 30 | 108 | ||
| 31 | std::string nfile( szFile ); | 109 | count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, |
| 110 | pNotify->FileNameLength / sizeof( WCHAR ), &nfile[0], count, | ||
| 111 | NULL, NULL ); | ||
| 32 | 112 | ||
| 33 | if ( FILE_ACTION_MODIFIED == pNotify->Action ) { | 113 | if ( FILE_ACTION_MODIFIED == pNotify->Action ) { |
| 34 | FileInfo fifile( std::string( pWatch->DirName ) + nfile ); | 114 | FileInfo fifile( std::string( pWatch->DirName ) + nfile ); |
| @@ -41,12 +121,59 @@ void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOve | |||
| 41 | 121 | ||
| 42 | pWatch->LastModifiedEvent.fileName = nfile; | 122 | pWatch->LastModifiedEvent.fileName = nfile; |
| 43 | pWatch->LastModifiedEvent.file = fifile; | 123 | pWatch->LastModifiedEvent.file = fifile; |
| 124 | } else if ( FILE_ACTION_RENAMED_OLD_NAME == pNotify->Action ) { | ||
| 125 | pWatch->OldFiles.emplace_back( nfile, pNotify->FileId ); | ||
| 126 | skip = true; | ||
| 127 | } else if ( FILE_ACTION_RENAMED_NEW_NAME == pNotify->Action ) { | ||
| 128 | std::string oldFile; | ||
| 129 | LARGE_INTEGER oldFileId{}; | ||
| 130 | |||
| 131 | for ( auto it = pWatch->OldFiles.begin(); it != pWatch->OldFiles.end(); ++it ) { | ||
| 132 | if ( it->second.QuadPart == pNotify->FileId.QuadPart ) { | ||
| 133 | oldFile = it->first; | ||
| 134 | oldFileId = it->second; | ||
| 135 | it = pWatch->OldFiles.erase( it ); | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | if ( oldFile.empty() ) { | ||
| 141 | pWatch->Watch->handleAction( pWatch, nfile, FILE_ACTION_ADDED ); | ||
| 142 | skip = true; | ||
| 143 | } else { | ||
| 144 | pWatch->Watch->handleAction( pWatch, oldFile, FILE_ACTION_RENAMED_OLD_NAME ); | ||
| 145 | } | ||
| 44 | } | 146 | } |
| 45 | 147 | ||
| 46 | if ( !skip ) { | 148 | if ( !skip ) { |
| 47 | pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action ); | 149 | pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action ); |
| 48 | } | 150 | } |
| 49 | } while ( pNotify->NextEntryOffset != 0 ); | 151 | } while ( pNotify->NextEntryOffset != 0 ); |
| 152 | } | ||
| 153 | |||
| 154 | /// Unpacks events and passes them to a user defined callback. | ||
| 155 | void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) { | ||
| 156 | if ( NULL == lpOverlapped ) { | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | |||
| 160 | WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped; | ||
| 161 | WatcherWin32* pWatch = tWatch->Watch; | ||
| 162 | |||
| 163 | if ( dwNumberOfBytesTransfered == 0 ) { | ||
| 164 | if ( nullptr != pWatch && !pWatch->StopNow ) { | ||
| 165 | RefreshWatch( tWatch ); | ||
| 166 | } else { | ||
| 167 | return; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | // Fork watch depending on the Windows API supported | ||
| 172 | if ( pWatch->Extended ) { | ||
| 173 | WatchCallbackEx( pWatch ); | ||
| 174 | } else { | ||
| 175 | WatchCallbackOld( pWatch ); | ||
| 176 | } | ||
| 50 | 177 | ||
| 51 | if ( !pWatch->StopNow ) { | 178 | if ( !pWatch->StopNow ) { |
| 52 | RefreshWatch( tWatch ); | 179 | RefreshWatch( tWatch ); |
| @@ -54,11 +181,40 @@ void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOve | |||
| 54 | } | 181 | } |
| 55 | 182 | ||
| 56 | /// Refreshes the directory monitoring. | 183 | /// Refreshes the directory monitoring. |
| 57 | bool RefreshWatch( WatcherStructWin32* pWatch ) { | 184 | RefreshResult RefreshWatch( WatcherStructWin32* pWatch ) { |
| 58 | return ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer, | 185 | initReadDirectoryChangesEx(); |
| 59 | sizeof( pWatch->Watch->Buffer ), pWatch->Watch->Recursive, | 186 | |
| 60 | pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, | 187 | bool bRet = false; |
| 61 | NULL ) != 0; | 188 | RefreshResult ret = RefreshResult::Failed; |
| 189 | pWatch->Watch->Extended = false; | ||
| 190 | |||
| 191 | if ( pReadDirectoryChangesExW ) { | ||
| 192 | bRet = pReadDirectoryChangesExW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(), | ||
| 193 | (DWORD)pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive, | ||
| 194 | pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, | ||
| 195 | NULL, EFSW_ReadDirectoryNotifyExtendedInformation ) != 0; | ||
| 196 | if ( bRet ) { | ||
| 197 | ret = RefreshResult::SucessEx; | ||
| 198 | pWatch->Watch->Extended = true; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | if ( !bRet ) { | ||
| 203 | bRet = ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer.data(), | ||
| 204 | (DWORD)pWatch->Watch->Buffer.size(), pWatch->Watch->Recursive, | ||
| 205 | pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, | ||
| 206 | NULL ) != 0; | ||
| 207 | |||
| 208 | if ( bRet ) | ||
| 209 | ret = RefreshResult::Success; | ||
| 210 | } | ||
| 211 | |||
| 212 | if ( !bRet ) { | ||
| 213 | std::string error = std::to_string( GetLastError() ); | ||
| 214 | Errors::Log::createLastError( Errors::WatcherFailed, error ); | ||
| 215 | } | ||
| 216 | |||
| 217 | return ret; | ||
| 62 | } | 218 | } |
| 63 | 219 | ||
| 64 | /// Stops monitoring a directory. | 220 | /// Stops monitoring a directory. |
| @@ -70,19 +226,17 @@ void DestroyWatch( WatcherStructWin32* pWatch ) { | |||
| 70 | CloseHandle( pWatch->Watch->DirHandle ); | 226 | CloseHandle( pWatch->Watch->DirHandle ); |
| 71 | efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); | 227 | efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); |
| 72 | efSAFE_DELETE( pWatch->Watch ); | 228 | efSAFE_DELETE( pWatch->Watch ); |
| 229 | efSAFE_DELETE( pWatch ); | ||
| 73 | } | 230 | } |
| 74 | } | 231 | } |
| 75 | 232 | ||
| 76 | /// Starts monitoring a directory. | 233 | /// Starts monitoring a directory. |
| 77 | WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter, | 234 | WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, |
| 78 | HANDLE iocp ) { | 235 | DWORD bufferSize, DWORD notifyFilter, HANDLE iocp ) { |
| 79 | WatcherStructWin32* tWatch; | 236 | WatcherStructWin32* tWatch = new WatcherStructWin32(); |
| 80 | size_t ptrsize = sizeof( *tWatch ); | 237 | WatcherWin32* pWatch = new WatcherWin32(bufferSize); |
| 81 | tWatch = static_cast<WatcherStructWin32*>( | 238 | if (tWatch) |
| 82 | HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize ) ); | 239 | tWatch->Watch = pWatch; |
| 83 | |||
| 84 | WatcherWin32* pWatch = new WatcherWin32(); | ||
| 85 | tWatch->Watch = pWatch; | ||
| 86 | 240 | ||
| 87 | pWatch->DirHandle = CreateFileW( | 241 | pWatch->DirHandle = CreateFileW( |
| 88 | szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, | 242 | szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
| @@ -90,17 +244,17 @@ WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, DWORD Noti | |||
| 90 | 244 | ||
| 91 | if ( pWatch->DirHandle != INVALID_HANDLE_VALUE && | 245 | if ( pWatch->DirHandle != INVALID_HANDLE_VALUE && |
| 92 | CreateIoCompletionPort( pWatch->DirHandle, iocp, 0, 1 ) ) { | 246 | CreateIoCompletionPort( pWatch->DirHandle, iocp, 0, 1 ) ) { |
| 93 | pWatch->NotifyFilter = NotifyFilter; | 247 | pWatch->NotifyFilter = notifyFilter; |
| 94 | pWatch->Recursive = recursive; | 248 | pWatch->Recursive = recursive; |
| 95 | 249 | ||
| 96 | if ( RefreshWatch( tWatch ) ) { | 250 | if ( RefreshResult::Failed != RefreshWatch( tWatch ) ) { |
| 97 | return tWatch; | 251 | return tWatch; |
| 98 | } | 252 | } |
| 99 | } | 253 | } |
| 100 | 254 | ||
| 101 | CloseHandle( pWatch->DirHandle ); | 255 | CloseHandle( pWatch->DirHandle ); |
| 102 | efSAFE_DELETE( pWatch->Watch ); | 256 | efSAFE_DELETE( pWatch->Watch ); |
| 103 | HeapFree( GetProcessHeap(), 0, tWatch ); | 257 | efSAFE_DELETE( tWatch ); |
| 104 | return NULL; | 258 | return NULL; |
| 105 | } | 259 | } |
| 106 | 260 | ||
diff --git a/src/3rdParty/efsw/WatcherWin32.hpp b/src/3rdParty/efsw/WatcherWin32.hpp index 71e13be..ea1e8e4 100755..100644 --- a/src/3rdParty/efsw/WatcherWin32.hpp +++ b/src/3rdParty/efsw/WatcherWin32.hpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <efsw/FileInfo.hpp> | 4 | #include <efsw/FileInfo.hpp> |
| 5 | #include <efsw/FileWatcherImpl.hpp> | 5 | #include <efsw/FileWatcherImpl.hpp> |
| 6 | #include <vector> | ||
| 6 | 7 | ||
| 7 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 | 8 | #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 |
| 8 | 9 | ||
| @@ -21,6 +22,8 @@ namespace efsw { | |||
| 21 | 22 | ||
| 22 | class WatcherWin32; | 23 | class WatcherWin32; |
| 23 | 24 | ||
| 25 | enum RefreshResult { Failed, Success, SucessEx }; | ||
| 26 | |||
| 24 | /// Internal watch data | 27 | /// Internal watch data |
| 25 | struct WatcherStructWin32 { | 28 | struct WatcherStructWin32 { |
| 26 | OVERLAPPED Overlapped; | 29 | OVERLAPPED Overlapped; |
| @@ -32,39 +35,41 @@ struct sLastModifiedEvent { | |||
| 32 | std::string fileName; | 35 | std::string fileName; |
| 33 | }; | 36 | }; |
| 34 | 37 | ||
| 35 | bool RefreshWatch( WatcherStructWin32* pWatch ); | 38 | RefreshResult RefreshWatch( WatcherStructWin32* pWatch ); |
| 36 | 39 | ||
| 37 | void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ); | 40 | void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ); |
| 38 | 41 | ||
| 39 | void DestroyWatch( WatcherStructWin32* pWatch ); | 42 | void DestroyWatch( WatcherStructWin32* pWatch ); |
| 40 | 43 | ||
| 41 | WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter, | 44 | WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, |
| 42 | HANDLE iocp ); | 45 | DWORD bufferSize, DWORD notifyFilter, HANDLE iocp ); |
| 43 | 46 | ||
| 44 | class WatcherWin32 : public Watcher { | 47 | class WatcherWin32 : public Watcher { |
| 45 | public: | 48 | public: |
| 46 | WatcherWin32() : | 49 | WatcherWin32(DWORD dwBufferSize) : |
| 47 | Struct( NULL ), | 50 | Struct( NULL ), |
| 48 | DirHandle( NULL ), | 51 | DirHandle( NULL ), |
| 52 | Buffer(), | ||
| 49 | lParam( 0 ), | 53 | lParam( 0 ), |
| 50 | NotifyFilter( 0 ), | 54 | NotifyFilter( 0 ), |
| 51 | StopNow( false ), | 55 | StopNow( false ), |
| 56 | Extended( false ), | ||
| 52 | Watch( NULL ), | 57 | Watch( NULL ), |
| 53 | DirName( NULL ) {} | 58 | DirName( NULL ) { |
| 59 | Buffer.resize(dwBufferSize); | ||
| 60 | } | ||
| 54 | 61 | ||
| 55 | WatcherStructWin32* Struct; | 62 | WatcherStructWin32* Struct; |
| 56 | HANDLE DirHandle; | 63 | HANDLE DirHandle; |
| 57 | BYTE Buffer | 64 | std::vector<BYTE> Buffer; |
| 58 | [63 * | ||
| 59 | 1024]; // do NOT make this bigger than 64K because it will fail if the folder being watched | ||
| 60 | // is on the network! (see | ||
| 61 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) | ||
| 62 | LPARAM lParam; | 65 | LPARAM lParam; |
| 63 | DWORD NotifyFilter; | 66 | DWORD NotifyFilter; |
| 64 | bool StopNow; | 67 | bool StopNow; |
| 68 | bool Extended; | ||
| 65 | FileWatcherImpl* Watch; | 69 | FileWatcherImpl* Watch; |
| 66 | char* DirName; | 70 | char* DirName; |
| 67 | sLastModifiedEvent LastModifiedEvent; | 71 | sLastModifiedEvent LastModifiedEvent; |
| 72 | std::vector<std::pair<std::string, LARGE_INTEGER>> OldFiles; | ||
| 68 | }; | 73 | }; |
| 69 | 74 | ||
| 70 | } // namespace efsw | 75 | } // namespace efsw |
diff --git a/src/3rdParty/efsw/base.hpp b/src/3rdParty/efsw/base.hpp index 43abc4f..43abc4f 100755..100644 --- a/src/3rdParty/efsw/base.hpp +++ b/src/3rdParty/efsw/base.hpp | |||
diff --git a/src/3rdParty/efsw/efsw.h b/src/3rdParty/efsw/efsw.h index 28e63e2..30cf595 100755..100644 --- a/src/3rdParty/efsw/efsw.h +++ b/src/3rdParty/efsw/efsw.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /** | 1 | /** |
| 2 | @author Sepul Sepehr Taghdisian | 2 | @author Sepul Sepehr Taghdisian |
| 3 | 3 | ||
| 4 | Copyright (c) 2013 Martin Lucas Golini | 4 | Copyright (c) 2024 MartÃn Lucas Golini |
| 5 | 5 | ||
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | of this software and associated documentation files (the "Software"), to deal | 7 | of this software and associated documentation files (the "Software"), to deal |
| @@ -32,31 +32,31 @@ | |||
| 32 | extern "C" { | 32 | extern "C" { |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | #if defined(_WIN32) | 35 | #if defined( _WIN32 ) |
| 36 | #ifdef EFSW_DYNAMIC | 36 | #ifdef EFSW_DYNAMIC |
| 37 | // Windows platforms | 37 | // Windows platforms |
| 38 | #ifdef EFSW_EXPORTS | 38 | #ifdef EFSW_EXPORTS |
| 39 | // From DLL side, we must export | 39 | // From DLL side, we must export |
| 40 | #define EFSW_API __declspec(dllexport) | 40 | #define EFSW_API __declspec( dllexport ) |
| 41 | #else | ||
| 42 | // From client application side, we must import | ||
| 43 | #define EFSW_API __declspec(dllimport) | ||
| 44 | #endif | ||
| 45 | #else | ||
| 46 | // No specific directive needed for static build | ||
| 47 | #ifndef EFSW_API | ||
| 48 | #define EFSW_API | ||
| 49 | #endif | ||
| 50 | #endif | ||
| 51 | #else | 41 | #else |
| 52 | #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) | 42 | // From client application side, we must import |
| 53 | #define EFSW_API __attribute__ ((visibility("default"))) | 43 | #define EFSW_API __declspec( dllimport ) |
| 54 | #endif | 44 | #endif |
| 55 | 45 | #else | |
| 56 | // Other platforms don't need to define anything | 46 | // No specific directive needed for static build |
| 57 | #ifndef EFSW_API | 47 | #ifndef EFSW_API |
| 58 | #define EFSW_API | 48 | #define EFSW_API |
| 59 | #endif | 49 | #endif |
| 50 | #endif | ||
| 51 | #else | ||
| 52 | #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) | ||
| 53 | #define EFSW_API __attribute__( ( visibility( "default" ) ) ) | ||
| 54 | #endif | ||
| 55 | |||
| 56 | // Other platforms don't need to define anything | ||
| 57 | #ifndef EFSW_API | ||
| 58 | #define EFSW_API | ||
| 59 | #endif | ||
| 60 | #endif | 60 | #endif |
| 61 | 61 | ||
| 62 | /// Type for a watch id | 62 | /// Type for a watch id |
| @@ -65,84 +65,127 @@ typedef long efsw_watchid; | |||
| 65 | /// Type for watcher | 65 | /// Type for watcher |
| 66 | typedef void* efsw_watcher; | 66 | typedef void* efsw_watcher; |
| 67 | 67 | ||
| 68 | enum efsw_action | 68 | enum efsw_action { |
| 69 | { | 69 | EFSW_ADD = 1, /// Sent when a file is created or renamed |
| 70 | EFSW_ADD = 1, /// Sent when a file is created or renamed | 70 | EFSW_DELETE = 2, /// Sent when a file is deleted or renamed |
| 71 | EFSW_DELETE = 2, /// Sent when a file is deleted or renamed | 71 | EFSW_MODIFIED = 3, /// Sent when a file is modified |
| 72 | EFSW_MODIFIED = 3, /// Sent when a file is modified | 72 | EFSW_MOVED = 4 /// Sent when a file is moved |
| 73 | EFSW_MOVED = 4 /// Sent when a file is moved | 73 | }; |
| 74 | |||
| 75 | enum efsw_error { | ||
| 76 | EFSW_NOTFOUND = -1, | ||
| 77 | EFSW_REPEATED = -2, | ||
| 78 | EFSW_OUTOFSCOPE = -3, | ||
| 79 | EFSW_NOTREADABLE = -4, | ||
| 80 | EFSW_REMOTE = -5, | ||
| 81 | EFSW_WATCHER_FAILED = -6, | ||
| 82 | EFSW_UNSPECIFIED = -7 | ||
| 74 | }; | 83 | }; |
| 75 | 84 | ||
| 76 | enum efsw_error | 85 | enum efsw_option { |
| 77 | { | 86 | /// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and |
| 78 | EFSW_NOTFOUND = -1, | 87 | /// file system events may be dropped. For that, using a different (bigger) buffer size |
| 79 | EFSW_REPEATED = -2, | 88 | /// can be defined here, but note that this does not work for network drives, |
| 80 | EFSW_OUTOFSCOPE = -3, | 89 | /// because a buffer larger than 64K will fail the folder being watched, see |
| 81 | EFSW_NOTREADABLE = -4, | 90 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) |
| 82 | EFSW_REMOTE = -5, | 91 | EFSW_OPT_WIN_BUFFER_SIZE = 1, |
| 83 | EFSW_UNSPECIFIED = -6 | 92 | /// For Windows, per default all events are captured but we might only be interested |
| 93 | /// in a subset; the value of the option should be set to a bitwise or'ed set of | ||
| 94 | /// FILE_NOTIFY_CHANGE_* flags. | ||
| 95 | EFSW_OPT_WIN_NOTIFY_FILTER = 2, | ||
| 96 | /// For macOS (FSEvents backend), per default all modified event types are capture but we might | ||
| 97 | // only be interested in a subset; the value of the option should be set to a set of bitwise | ||
| 98 | // from: | ||
| 99 | // kFSEventStreamEventFlagItemFinderInfoMod | ||
| 100 | // kFSEventStreamEventFlagItemModified | ||
| 101 | // kFSEventStreamEventFlagItemInodeMetaMod | ||
| 102 | // Default configuration will set the 3 flags | ||
| 103 | EFSW_OPT_MAC_MODIFIED_FILTER = 3, | ||
| 104 | /// macOS sometimes informs incorrect or old file states that may confuse the consumer | ||
| 105 | /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing | ||
| 106 | /// the number of events reported. This will have an small performance and memory impact as a | ||
| 107 | /// consequence. | ||
| 108 | EFSW_OPT_MAC_SANITIZE_EVENTS = 4, | ||
| 109 | /// Linux does not support natively recursive watchers. This means that when using recursive | ||
| 110 | /// watches efsw registers new watchers for each directory. If new file are created between | ||
| 111 | /// the time efsw takes to register the new directory those events might be missed. To avoid | ||
| 112 | /// missing new file notifications efsw will trigger synthetic new file events for existing | ||
| 113 | /// files in the new directroy watched. This might have the unintended consequence of sending | ||
| 114 | /// duplicated created events due to the system also emitting this event. | ||
| 115 | LINUX_PRODUCE_SYNTHETIC_EVENTS = 5, | ||
| 84 | }; | 116 | }; |
| 85 | 117 | ||
| 86 | /// Basic interface for listening for file events. | 118 | /// Basic interface for listening for file events. |
| 87 | typedef void (*efsw_pfn_fileaction_callback) ( | 119 | typedef void ( *efsw_pfn_fileaction_callback )( efsw_watcher watcher, efsw_watchid watchid, |
| 88 | efsw_watcher watcher, | 120 | const char* dir, const char* filename, |
| 89 | efsw_watchid watchid, | 121 | enum efsw_action action, const char* old_filename, |
| 90 | const char* dir, | 122 | void* param ); |
| 91 | const char* filename, | 123 | |
| 92 | enum efsw_action action, | 124 | typedef struct { |
| 93 | const char* old_filename, | 125 | enum efsw_option option; |
| 94 | void* param | 126 | int value; |
| 95 | ); | 127 | } efsw_watcher_option; |
| 96 | 128 | ||
| 97 | /** | 129 | /** |
| 98 | * Creates a new file-watcher | 130 | * Creates a new file-watcher |
| 99 | * @param generic_mode Force the use of the Generic file watcher | 131 | * @param generic_mode Force the use of the Generic file watcher |
| 100 | */ | 132 | */ |
| 101 | efsw_watcher EFSW_API efsw_create(int generic_mode); | 133 | efsw_watcher EFSW_API efsw_create( int generic_mode ); |
| 102 | 134 | ||
| 103 | /// Release the file-watcher and unwatch any directories | 135 | /// Release the file-watcher and unwatch any directories |
| 104 | void EFSW_API efsw_release(efsw_watcher watcher); | 136 | void EFSW_API efsw_release( efsw_watcher watcher ); |
| 105 | 137 | ||
| 106 | /// Retreive last error occured by file-watcher | 138 | /// Retrieve last error occured by file-watcher |
| 107 | EFSW_API const char* efsw_getlasterror(); | 139 | EFSW_API const char* efsw_getlasterror(); |
| 108 | 140 | ||
| 109 | /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. | 141 | /// Reset file-watcher last error |
| 110 | /// For backwards compatibility. | 142 | EFSW_API void efsw_clearlasterror(); |
| 143 | |||
| 144 | /// Add a directory watch | ||
| 111 | /// On error returns WatchID with Error type. | 145 | /// On error returns WatchID with Error type. |
| 112 | efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory, | 146 | efsw_watchid EFSW_API efsw_addwatch( efsw_watcher watcher, const char* directory, |
| 113 | efsw_pfn_fileaction_callback callback_fn, int recursive, void* param); | 147 | efsw_pfn_fileaction_callback callback_fn, int recursive, |
| 148 | void* param ); | ||
| 149 | |||
| 150 | /// Add a directory watch, specifying options | ||
| 151 | /// @param options Pointer to an array of watcher options | ||
| 152 | /// @param nr_options Number of options referenced by \p options | ||
| 153 | efsw_watchid EFSW_API efsw_addwatch_withoptions( efsw_watcher watcher, const char* directory, | ||
| 154 | efsw_pfn_fileaction_callback callback_fn, | ||
| 155 | int recursive, efsw_watcher_option* options, | ||
| 156 | int options_number, void* param ); | ||
| 114 | 157 | ||
| 115 | /// Remove a directory watch. This is a brute force search O(nlogn). | 158 | /// Remove a directory watch. This is a brute force search O(nlogn). |
| 116 | void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory); | 159 | void EFSW_API efsw_removewatch( efsw_watcher watcher, const char* directory ); |
| 117 | 160 | ||
| 118 | /// Remove a directory watch. This is a map lookup O(logn). | 161 | /// Remove a directory watch. This is a map lookup O(logn). |
| 119 | void EFSW_API efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid); | 162 | void EFSW_API efsw_removewatch_byid( efsw_watcher watcher, efsw_watchid watchid ); |
| 120 | 163 | ||
| 121 | /// Starts watching ( in other thread ) | 164 | /// Starts watching ( in other thread ) |
| 122 | void EFSW_API efsw_watch(efsw_watcher watcher); | 165 | void EFSW_API efsw_watch( efsw_watcher watcher ); |
| 123 | 166 | ||
| 124 | /** | 167 | /** |
| 125 | * Allow recursive watchers to follow symbolic links to other directories | 168 | * Allow recursive watchers to follow symbolic links to other directories |
| 126 | * followSymlinks is disabled by default | 169 | * followSymlinks is disabled by default |
| 127 | */ | 170 | */ |
| 128 | void EFSW_API efsw_follow_symlinks(efsw_watcher watcher, int enable); | 171 | void EFSW_API efsw_follow_symlinks( efsw_watcher watcher, int enable ); |
| 129 | 172 | ||
| 130 | /** @return If can follow symbolic links to directorioes */ | 173 | /** @return If can follow symbolic links to directorioes */ |
| 131 | int EFSW_API efsw_follow_symlinks_isenabled(efsw_watcher watcher); | 174 | int EFSW_API efsw_follow_symlinks_isenabled( efsw_watcher watcher ); |
| 132 | 175 | ||
| 133 | /** | 176 | /** |
| 134 | * When enable this it will allow symlinks to watch recursively out of the pointed directory. | 177 | * When enable this it will allow symlinks to watch recursively out of the pointed directory. |
| 135 | * follorSymlinks must be enabled to this work. | 178 | * follorSymlinks must be enabled to this work. |
| 136 | * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed, | 179 | * For example, added symlink to /home/folder, and the symlink points to /, this by default is not |
| 137 | * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion. | 180 | * allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid great |
| 138 | * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ). | 181 | * levels of recursion. Enabling this could lead in infinite recursion, and crash the watcher ( it |
| 139 | * Buy enabling out of scope links, it will allow this behavior. | 182 | * will try not to avoid this ). Buy enabling out of scope links, it will allow this behavior. |
| 140 | * allowOutOfScopeLinks are disabled by default. | 183 | * allowOutOfScopeLinks are disabled by default. |
| 141 | */ | 184 | */ |
| 142 | void EFSW_API efsw_allow_outofscopelinks(efsw_watcher watcher, int allow); | 185 | void EFSW_API efsw_allow_outofscopelinks( efsw_watcher watcher, int allow ); |
| 143 | 186 | ||
| 144 | /// @return Returns if out of scope links are allowed | 187 | /// @return Returns if out of scope links are allowed |
| 145 | int EFSW_API efsw_outofscopelinks_isallowed(efsw_watcher watcher); | 188 | int EFSW_API efsw_outofscopelinks_isallowed( efsw_watcher watcher ); |
| 146 | 189 | ||
| 147 | #ifdef __cplusplus | 190 | #ifdef __cplusplus |
| 148 | } | 191 | } |
diff --git a/src/3rdParty/efsw/efsw.hpp b/src/3rdParty/efsw/efsw.hpp index 12af116..11a5dec 100755..100644 --- a/src/3rdParty/efsw/efsw.hpp +++ b/src/3rdParty/efsw/efsw.hpp | |||
| @@ -1,195 +1,261 @@ | |||
| 1 | /** | 1 | /** |
| 2 | @author MartÃn Lucas Golini | 2 | @author MartÃn Lucas Golini |
| 3 | 3 | ||
| 4 | Copyright (c) 2013 MartÃn Lucas Golini | 4 | Copyright (c) 2024 MartÃn Lucas Golini |
| 5 | 5 | ||
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | of this software and associated documentation files (the "Software"), to deal | 7 | of this software and associated documentation files (the "Software"), to deal |
| 8 | in the Software without restriction, including without limitation the rights | 8 | in the Software without restriction, including without limitation the rights |
| 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | copies of the Software, and to permit persons to whom the Software is | 10 | copies of the Software, and to permit persons to whom the Software is |
| 11 | furnished to do so, subject to the following conditions: | 11 | furnished to do so, subject to the following conditions: |
| 12 | 12 | ||
| 13 | The above copyright notice and this permission notice shall be included in | 13 | The above copyright notice and this permission notice shall be included in |
| 14 | all copies or substantial portions of the Software. | 14 | all copies or substantial portions of the Software. |
| 15 | 15 | ||
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 22 | THE SOFTWARE. | 22 | THE SOFTWARE. |
| 23 | 23 | ||
| 24 | This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) | 24 | This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com) |
| 25 | http://code.google.com/p/simplefilewatcher/ also MIT licensed. | 25 | http://code.google.com/p/simplefilewatcher/ also MIT licensed. |
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | #ifndef ESFW_HPP | 28 | #ifndef ESFW_HPP |
| 29 | #define ESFW_HPP | 29 | #define ESFW_HPP |
| 30 | 30 | ||
| 31 | #include <list> | 31 | #include <string> |
| 32 | #include <string> | 32 | #include <vector> |
| 33 | 33 | ||
| 34 | #if defined( _WIN32 ) | 34 | #if defined( _WIN32 ) |
| 35 | #ifdef EFSW_DYNAMIC | 35 | #ifdef EFSW_DYNAMIC |
| 36 | // Windows platforms | 36 | // Windows platforms |
| 37 | #ifdef EFSW_EXPORTS | 37 | #ifdef EFSW_EXPORTS |
| 38 | // From DLL side, we must export | 38 | // From DLL side, we must export |
| 39 | #define EFSW_API __declspec( dllexport ) | 39 | #define EFSW_API __declspec( dllexport ) |
| 40 | #else | 40 | #else |
| 41 | // From client application side, we must import | 41 | // From client application side, we must import |
| 42 | #define EFSW_API __declspec( dllimport ) | 42 | #define EFSW_API __declspec( dllimport ) |
| 43 | #endif | 43 | #endif |
| 44 | #else | 44 | #else |
| 45 | // No specific directive needed for static build | 45 | // No specific directive needed for static build |
| 46 | #ifndef EFSW_API | 46 | #ifndef EFSW_API |
| 47 | #define EFSW_API | 47 | #define EFSW_API |
| 48 | #endif | 48 | #endif |
| 49 | #endif | 49 | #endif |
| 50 | #else | 50 | #else |
| 51 | #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) | 51 | #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS ) |
| 52 | #ifndef EFSW_API | 52 | #ifndef EFSW_API |
| 53 | #define EFSW_API __attribute__( ( visibility( "default" ) ) ) | 53 | #define EFSW_API __attribute__( ( visibility( "default" ) ) ) |
| 54 | #endif | 54 | #endif |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | // Other platforms don't need to define anything | 57 | // Other platforms don't need to define anything |
| 58 | #ifndef EFSW_API | 58 | #ifndef EFSW_API |
| 59 | #define EFSW_API | 59 | #define EFSW_API |
| 60 | #endif | 60 | #endif |
| 61 | #endif | 61 | #endif |
| 62 | 62 | ||
| 63 | namespace efsw { | 63 | namespace efsw { |
| 64 | 64 | ||
| 65 | /// Type for a watch id | 65 | /// Type for a watch id |
| 66 | typedef long WatchID; | 66 | typedef long WatchID; |
| 67 | 67 | ||
| 68 | // forward declarations | 68 | // forward declarations |
| 69 | class FileWatcherImpl; | 69 | class FileWatcherImpl; |
| 70 | class FileWatchListener; | 70 | class FileWatchListener; |
| 71 | 71 | class WatcherOption; | |
| 72 | /// Actions to listen for. Rename will send two events, one for | 72 | |
| 73 | /// the deletion of the old file, and one for the creation of the | 73 | /// Actions to listen for. Rename will send two events, one for |
| 74 | /// new file. | 74 | /// the deletion of the old file, and one for the creation of the |
| 75 | namespace Actions { | 75 | /// new file. |
| 76 | enum Action { | 76 | namespace Actions { |
| 77 | /// Sent when a file is created or renamed | 77 | enum Action { |
| 78 | Add = 1, | 78 | /// Sent when a file is created or renamed |
| 79 | /// Sent when a file is deleted or renamed | 79 | Add = 1, |
| 80 | Delete = 2, | 80 | /// Sent when a file is deleted or renamed |
| 81 | /// Sent when a file is modified | 81 | Delete = 2, |
| 82 | Modified = 3, | 82 | /// Sent when a file is modified |
| 83 | /// Sent when a file is moved | 83 | Modified = 3, |
| 84 | Moved = 4 | 84 | /// Sent when a file is moved |
| 85 | }; | 85 | Moved = 4 |
| 86 | } | 86 | }; |
| 87 | typedef Actions::Action Action; | 87 | } |
| 88 | 88 | typedef Actions::Action Action; | |
| 89 | /// Errors log namespace | 89 | |
| 90 | namespace Errors { | 90 | /// Errors log namespace |
| 91 | 91 | namespace Errors { | |
| 92 | enum Error { | 92 | |
| 93 | FileNotFound = -1, | 93 | enum Error { |
| 94 | FileRepeated = -2, | 94 | NoError = 0, |
| 95 | FileOutOfScope = -3, | 95 | FileNotFound = -1, |
| 96 | FileNotReadable = -4, | 96 | FileRepeated = -2, |
| 97 | FileRemote = -5, /** Directory in remote file system ( create a generic FileWatcher instance to | 97 | FileOutOfScope = -3, |
| 98 | watch this directory ). */ | 98 | FileNotReadable = -4, |
| 99 | Unspecified = -6 | 99 | /// Directory in remote file system |
| 100 | }; | 100 | /// ( create a generic FileWatcher instance to watch this directory ). |
| 101 | 101 | FileRemote = -5, | |
| 102 | class EFSW_API Log { | 102 | /// File system watcher failed to watch for changes. |
| 103 | public: | 103 | WatcherFailed = -6, |
| 104 | /// @return The last error logged | 104 | Unspecified = -7 |
| 105 | static std::string getLastErrorLog(); | 105 | }; |
| 106 | 106 | ||
| 107 | /// Creates an error of the type specified | 107 | class EFSW_API Log { |
| 108 | static Error createLastError( Error err, std::string log ); | 108 | public: |
| 109 | }; | 109 | /// @return The last error logged |
| 110 | 110 | static std::string getLastErrorLog(); | |
| 111 | } // namespace Errors | 111 | |
| 112 | typedef Errors::Error Error; | 112 | /// @return The code of the last error logged |
| 113 | 113 | static Error getLastErrorCode(); | |
| 114 | /// Listens to files and directories and dispatches events | 114 | |
| 115 | /// to notify the listener of files and directories changes. | 115 | /// Reset last error |
| 116 | /// @class FileWatcher | 116 | static void clearLastError(); |
| 117 | class EFSW_API FileWatcher { | 117 | |
| 118 | public: | 118 | /// Creates an error of the type specified |
| 119 | /// Default constructor, will use the default platform file watcher | 119 | static Error createLastError( Error err, std::string log ); |
| 120 | FileWatcher(); | 120 | }; |
| 121 | 121 | ||
| 122 | /// Constructor that lets you force the use of the Generic File Watcher | 122 | } // namespace Errors |
| 123 | explicit FileWatcher( bool useGenericFileWatcher ); | 123 | typedef Errors::Error Error; |
| 124 | 124 | ||
| 125 | virtual ~FileWatcher(); | 125 | /// Optional file watcher settings. |
| 126 | 126 | namespace Options { | |
| 127 | /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. | 127 | enum Option { |
| 128 | /// For backwards compatibility. | 128 | /// For Windows, the default buffer size of 63*1024 bytes sometimes is not enough and |
| 129 | /// On error returns WatchID with Error type. | 129 | /// file system events may be dropped. For that, using a different (bigger) buffer size |
| 130 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher ); | 130 | /// can be defined here, but note that this does not work for network drives, |
| 131 | 131 | /// because a buffer larger than 64K will fail the folder being watched, see | |
| 132 | /// Add a directory watch | 132 | /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx) |
| 133 | /// On error returns WatchID with Error type. | 133 | WinBufferSize = 1, |
| 134 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); | 134 | /// For Windows, per default all events are captured but we might only be interested |
| 135 | 135 | /// in a subset; the value of the option should be set to a bitwise or'ed set of | |
| 136 | /// Remove a directory watch. This is a brute force search O(nlogn). | 136 | /// FILE_NOTIFY_CHANGE_* flags. |
| 137 | void removeWatch( const std::string& directory ); | 137 | WinNotifyFilter = 2, |
| 138 | 138 | /// For macOS (FSEvents backend), per default all modified event types are capture but we might | |
| 139 | /// Remove a directory watch. This is a map lookup O(logn). | 139 | /// only be interested in a subset; the value of the option should be set to a set of bitwise |
| 140 | void removeWatch( WatchID watchid ); | 140 | /// from: |
| 141 | 141 | /// kFSEventStreamEventFlagItemFinderInfoMod | |
| 142 | /// Starts watching ( in other thread ) | 142 | /// kFSEventStreamEventFlagItemModified |
| 143 | void watch(); | 143 | /// kFSEventStreamEventFlagItemInodeMetaMod |
| 144 | 144 | /// Default configuration will set the 3 flags | |
| 145 | /// @return Returns a list of the directories that are being watched | 145 | MacModifiedFilter = 3, |
| 146 | std::list<std::string> directories(); | 146 | /// macOS sometimes informs incorrect or old file states that may confuse the consumer |
| 147 | 147 | /// The events sanitizer will try to sanitize incorrectly reported events in favor of reducing | |
| 148 | /** Allow recursive watchers to follow symbolic links to other directories | 148 | /// the number of events reported. This will have an small performance and memory impact as a |
| 149 | * followSymlinks is disabled by default | 149 | /// consequence. |
| 150 | */ | 150 | MacSanitizeEvents = 4, |
| 151 | void followSymlinks( bool follow ); | 151 | /// Linux does not support natively recursive watchers. This means that when using recursive |
| 152 | 152 | /// watches efsw registers new watchers for each directory. If new file are created between | |
| 153 | /** @return If can follow symbolic links to directorioes */ | 153 | /// the time efsw takes to register the new directory those events might be missed. To avoid |
| 154 | const bool& followSymlinks() const; | 154 | /// missing new file notifications efsw will trigger synthetic created file events for existing |
| 155 | 155 | /// files in the new directroy watched. This might have the unintended consequence of sending | |
| 156 | /** When enable this it will allow symlinks to watch recursively out of the pointed directory. | 156 | /// duplicated created events due to the system also emitting this event. |
| 157 | * follorSymlinks must be enabled to this work. | 157 | LinuxProduceSyntheticEvents = 5, |
| 158 | * For example, added symlink to /home/folder, and the symlink points to /, this by default is | 158 | }; |
| 159 | * not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid | 159 | } |
| 160 | * great levels of recursion. Enabling this could lead in infinite recursion, and crash the | 160 | typedef Options::Option Option; |
| 161 | * watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow | 161 | |
| 162 | * this behavior. allowOutOfScopeLinks are disabled by default. | 162 | /// Listens to files and directories and dispatches events |
| 163 | */ | 163 | /// to notify the listener of files and directories changes. |
| 164 | void allowOutOfScopeLinks( bool allow ); | 164 | /// @class FileWatcher |
| 165 | 165 | class EFSW_API FileWatcher { | |
| 166 | /// @return Returns if out of scope links are allowed | 166 | public: |
| 167 | const bool& allowOutOfScopeLinks() const; | 167 | /// Default constructor, will use the default platform file watcher |
| 168 | 168 | FileWatcher(); | |
| 169 | private: | 169 | |
| 170 | /// The implementation | 170 | /// Constructor that lets you force the use of the Generic File Watcher |
| 171 | FileWatcherImpl* mImpl; | 171 | explicit FileWatcher( bool useGenericFileWatcher ); |
| 172 | bool mFollowSymlinks; | 172 | |
| 173 | bool mOutOfScopeLinks; | 173 | virtual ~FileWatcher(); |
| 174 | }; | 174 | |
| 175 | 175 | /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option. | |
| 176 | /// Basic interface for listening for file events. | 176 | /// For backwards compatibility. |
| 177 | /// @class FileWatchListener | 177 | /// On error returns WatchID with Error type. |
| 178 | class FileWatchListener { | 178 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher ); |
| 179 | public: | 179 | |
| 180 | virtual ~FileWatchListener() {} | 180 | /// Add a directory watch |
| 181 | 181 | /// On error returns WatchID with Error type. | |
| 182 | /// Handles the action file action | 182 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ); |
| 183 | /// @param watchid The watch id for the directory | 183 | |
| 184 | /// @param dir The directory | 184 | /// Add a directory watch, allowing customization with options |
| 185 | /// @param filename The filename that was accessed (not full path) | 185 | /// @param directory The folder to be watched |
| 186 | /// @param action Action that was performed | 186 | /// @param watcher The listener to receive events |
| 187 | /// @param oldFilename The name of the file or directory moved | 187 | /// @param recursive Set this to true to include subdirectories |
| 188 | virtual void handleFileAction( WatchID watchid, const std::string& dir, | 188 | /// @param options Allows customization of a watcher |
| 189 | const std::string& filename, Action action, | 189 | /// @return Returns the watch id for the directory or, on error, a WatchID with Error type. |
| 190 | std::string oldFilename = "" ) = 0; | 190 | WatchID addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, |
| 191 | }; | 191 | const std::vector<WatcherOption>& options ); |
| 192 | 192 | ||
| 193 | } // namespace efsw | 193 | /// Remove a directory watch. This is a brute force search O(nlogn). |
| 194 | 194 | void removeWatch( const std::string& directory ); | |
| 195 | #endif | 195 | |
| 196 | /// Remove a directory watch. This is a map lookup O(logn). | ||
| 197 | void removeWatch( WatchID watchid ); | ||
| 198 | |||
| 199 | /// Starts watching ( in other thread ) | ||
| 200 | void watch(); | ||
| 201 | |||
| 202 | /// @return Returns a list of the directories that are being watched | ||
| 203 | std::vector<std::string> directories(); | ||
| 204 | |||
| 205 | /** Allow recursive watchers to follow symbolic links to other directories | ||
| 206 | * followSymlinks is disabled by default | ||
| 207 | */ | ||
| 208 | void followSymlinks( bool follow ); | ||
| 209 | |||
| 210 | /** @return If can follow symbolic links to directorioes */ | ||
| 211 | const bool& followSymlinks() const; | ||
| 212 | |||
| 213 | /** When enable this it will allow symlinks to watch recursively out of the pointed directory. | ||
| 214 | * follorSymlinks must be enabled to this work. | ||
| 215 | * For example, added symlink to /home/folder, and the symlink points to /, this by default is | ||
| 216 | * not allowed, it's only allowed to symlink anything from /home/ and deeper. This is to avoid | ||
| 217 | * great levels of recursion. Enabling this could lead in infinite recursion, and crash the | ||
| 218 | * watcher ( it will try not to avoid this ). Buy enabling out of scope links, it will allow | ||
| 219 | * this behavior. allowOutOfScopeLinks are disabled by default. | ||
| 220 | */ | ||
| 221 | void allowOutOfScopeLinks( bool allow ); | ||
| 222 | |||
| 223 | /// @return Returns if out of scope links are allowed | ||
| 224 | const bool& allowOutOfScopeLinks() const; | ||
| 225 | |||
| 226 | private: | ||
| 227 | /// The implementation | ||
| 228 | FileWatcherImpl* mImpl; | ||
| 229 | bool mFollowSymlinks; | ||
| 230 | bool mOutOfScopeLinks; | ||
| 231 | }; | ||
| 232 | |||
| 233 | /// Basic interface for listening for file events. | ||
| 234 | /// @class FileWatchListener | ||
| 235 | class FileWatchListener { | ||
| 236 | public: | ||
| 237 | virtual ~FileWatchListener() {} | ||
| 238 | |||
| 239 | /// Handles the action file action | ||
| 240 | /// @param watchid The watch id for the directory | ||
| 241 | /// @param dir The directory | ||
| 242 | /// @param filename The filename that was accessed (not full path) | ||
| 243 | /// @param action Action that was performed | ||
| 244 | /// @param oldFilename The name of the file or directory moved | ||
| 245 | virtual void handleFileAction( WatchID watchid, const std::string& dir, | ||
| 246 | const std::string& filename, Action action, | ||
| 247 | std::string oldFilename = "" ) = 0; | ||
| 248 | }; | ||
| 249 | |||
| 250 | /// Optional, typically platform specific parameter for customization of a watcher. | ||
| 251 | /// @class WatcherOption | ||
| 252 | class WatcherOption { | ||
| 253 | public: | ||
| 254 | WatcherOption( Option option, int value ) : mOption( option ), mValue( value ){}; | ||
| 255 | Option mOption; | ||
| 256 | int mValue; | ||
| 257 | }; | ||
| 258 | |||
| 259 | } // namespace efsw | ||
| 260 | |||
| 261 | #endif | ||
diff --git a/src/3rdParty/efsw/inotify-nosys.h b/src/3rdParty/efsw/inotify-nosys.h index be1e627..be1e627 100755..100644 --- a/src/3rdParty/efsw/inotify-nosys.h +++ b/src/3rdParty/efsw/inotify-nosys.h | |||
diff --git a/src/3rdParty/efsw/platform/platformimpl.hpp b/src/3rdParty/efsw/platform/platformimpl.hpp index 5442580..5442580 100755..100644 --- a/src/3rdParty/efsw/platform/platformimpl.hpp +++ b/src/3rdParty/efsw/platform/platformimpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp b/src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp index 92eeb47..92eeb47 100755..100644 --- a/src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp +++ b/src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/FileSystemImpl.hpp b/src/3rdParty/efsw/platform/posix/FileSystemImpl.hpp index 0bfba76..0bfba76 100755..100644 --- a/src/3rdParty/efsw/platform/posix/FileSystemImpl.hpp +++ b/src/3rdParty/efsw/platform/posix/FileSystemImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/MutexImpl.cpp b/src/3rdParty/efsw/platform/posix/MutexImpl.cpp index 2233798..2233798 100755..100644 --- a/src/3rdParty/efsw/platform/posix/MutexImpl.cpp +++ b/src/3rdParty/efsw/platform/posix/MutexImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/MutexImpl.hpp b/src/3rdParty/efsw/platform/posix/MutexImpl.hpp index a33d827..a33d827 100755..100644 --- a/src/3rdParty/efsw/platform/posix/MutexImpl.hpp +++ b/src/3rdParty/efsw/platform/posix/MutexImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/SystemImpl.cpp b/src/3rdParty/efsw/platform/posix/SystemImpl.cpp index 37d4120..37d4120 100755..100644 --- a/src/3rdParty/efsw/platform/posix/SystemImpl.cpp +++ b/src/3rdParty/efsw/platform/posix/SystemImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/SystemImpl.hpp b/src/3rdParty/efsw/platform/posix/SystemImpl.hpp index 9322b06..9322b06 100755..100644 --- a/src/3rdParty/efsw/platform/posix/SystemImpl.hpp +++ b/src/3rdParty/efsw/platform/posix/SystemImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/posix/ThreadImpl.cpp b/src/3rdParty/efsw/platform/posix/ThreadImpl.cpp index e0ae84f..772fbc9 100755..100644 --- a/src/3rdParty/efsw/platform/posix/ThreadImpl.cpp +++ b/src/3rdParty/efsw/platform/posix/ThreadImpl.cpp | |||
| @@ -5,11 +5,10 @@ | |||
| 5 | 5 | ||
| 6 | #include <cassert> | 6 | #include <cassert> |
| 7 | #include <efsw/Debug.hpp> | 7 | #include <efsw/Debug.hpp> |
| 8 | #include <iostream> | ||
| 9 | 8 | ||
| 10 | namespace efsw { namespace Platform { | 9 | namespace efsw { namespace Platform { |
| 11 | 10 | ||
| 12 | ThreadImpl::ThreadImpl( Thread* owner ) : mIsActive( false ) { | 11 | ThreadImpl::ThreadImpl( efsw::Thread* owner ) : mIsActive( false ) { |
| 13 | mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0; | 12 | mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0; |
| 14 | 13 | ||
| 15 | if ( !mIsActive ) { | 14 | if ( !mIsActive ) { |
| @@ -17,14 +16,16 @@ ThreadImpl::ThreadImpl( Thread* owner ) : mIsActive( false ) { | |||
| 17 | } | 16 | } |
| 18 | } | 17 | } |
| 19 | 18 | ||
| 19 | ThreadImpl::~ThreadImpl() { | ||
| 20 | terminate(); | ||
| 21 | } | ||
| 22 | |||
| 20 | void ThreadImpl::wait() { | 23 | void ThreadImpl::wait() { |
| 21 | // Wait for the thread to finish, no timeout | 24 | // Wait for the thread to finish, no timeout |
| 22 | if ( mIsActive ) { | 25 | if ( mIsActive ) { |
| 23 | assert( pthread_equal( pthread_self(), mThread ) == 0 ); | 26 | assert( pthread_equal( pthread_self(), mThread ) == 0 ); |
| 24 | 27 | ||
| 25 | pthread_join( mThread, NULL ); | 28 | mIsActive = pthread_join( mThread, NULL ) != 0; |
| 26 | |||
| 27 | mIsActive = false; // Reset the thread state | ||
| 28 | } | 29 | } |
| 29 | } | 30 | } |
| 30 | 31 | ||
| @@ -41,14 +42,14 @@ void ThreadImpl::terminate() { | |||
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | void* ThreadImpl::entryPoint( void* userData ) { | 44 | void* ThreadImpl::entryPoint( void* userData ) { |
| 44 | // The Thread instance is stored in the user data | ||
| 45 | Thread* owner = static_cast<Thread*>( userData ); | ||
| 46 | |||
| 47 | // Tell the thread to handle cancel requests immediatly | 45 | // Tell the thread to handle cancel requests immediatly |
| 48 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | 46 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS |
| 49 | pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); | 47 | pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL ); |
| 50 | #endif | 48 | #endif |
| 51 | 49 | ||
| 50 | // The Thread instance is stored in the user data | ||
| 51 | Thread* owner = static_cast<Thread*>( userData ); | ||
| 52 | |||
| 52 | // Forward to the owner | 53 | // Forward to the owner |
| 53 | owner->run(); | 54 | owner->run(); |
| 54 | 55 | ||
diff --git a/src/3rdParty/efsw/platform/posix/ThreadImpl.hpp b/src/3rdParty/efsw/platform/posix/ThreadImpl.hpp index ffc6da0..2e02f9a 100755..100644 --- a/src/3rdParty/efsw/platform/posix/ThreadImpl.hpp +++ b/src/3rdParty/efsw/platform/posix/ThreadImpl.hpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #if defined( EFSW_PLATFORM_POSIX ) | 6 | #if defined( EFSW_PLATFORM_POSIX ) |
| 7 | 7 | ||
| 8 | #include <efsw/Atomic.hpp> | ||
| 8 | #include <pthread.h> | 9 | #include <pthread.h> |
| 9 | 10 | ||
| 10 | namespace efsw { | 11 | namespace efsw { |
| @@ -15,7 +16,9 @@ namespace Platform { | |||
| 15 | 16 | ||
| 16 | class ThreadImpl { | 17 | class ThreadImpl { |
| 17 | public: | 18 | public: |
| 18 | ThreadImpl( Thread* owner ); | 19 | explicit ThreadImpl( efsw::Thread* owner ); |
| 20 | |||
| 21 | ~ThreadImpl(); | ||
| 19 | 22 | ||
| 20 | void wait(); | 23 | void wait(); |
| 21 | 24 | ||
| @@ -25,7 +28,7 @@ class ThreadImpl { | |||
| 25 | static void* entryPoint( void* userData ); | 28 | static void* entryPoint( void* userData ); |
| 26 | 29 | ||
| 27 | pthread_t mThread; | 30 | pthread_t mThread; |
| 28 | bool mIsActive; | 31 | Atomic<bool> mIsActive; |
| 29 | }; | 32 | }; |
| 30 | 33 | ||
| 31 | } // namespace Platform | 34 | } // namespace Platform |
diff --git a/src/3rdParty/efsw/platform/win/FileSystemImpl.cpp b/src/3rdParty/efsw/platform/win/FileSystemImpl.cpp index 2b87513..2b87513 100755..100644 --- a/src/3rdParty/efsw/platform/win/FileSystemImpl.cpp +++ b/src/3rdParty/efsw/platform/win/FileSystemImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/win/FileSystemImpl.hpp b/src/3rdParty/efsw/platform/win/FileSystemImpl.hpp index e952efc..e952efc 100755..100644 --- a/src/3rdParty/efsw/platform/win/FileSystemImpl.hpp +++ b/src/3rdParty/efsw/platform/win/FileSystemImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/win/MutexImpl.cpp b/src/3rdParty/efsw/platform/win/MutexImpl.cpp index 62b7f83..62b7f83 100755..100644 --- a/src/3rdParty/efsw/platform/win/MutexImpl.cpp +++ b/src/3rdParty/efsw/platform/win/MutexImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/win/MutexImpl.hpp b/src/3rdParty/efsw/platform/win/MutexImpl.hpp index 7b06492..7b06492 100755..100644 --- a/src/3rdParty/efsw/platform/win/MutexImpl.hpp +++ b/src/3rdParty/efsw/platform/win/MutexImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/win/SystemImpl.cpp b/src/3rdParty/efsw/platform/win/SystemImpl.cpp index d1f2b21..d1f2b21 100755..100644 --- a/src/3rdParty/efsw/platform/win/SystemImpl.cpp +++ b/src/3rdParty/efsw/platform/win/SystemImpl.cpp | |||
diff --git a/src/3rdParty/efsw/platform/win/SystemImpl.hpp b/src/3rdParty/efsw/platform/win/SystemImpl.hpp index 99b4867..99b4867 100755..100644 --- a/src/3rdParty/efsw/platform/win/SystemImpl.hpp +++ b/src/3rdParty/efsw/platform/win/SystemImpl.hpp | |||
diff --git a/src/3rdParty/efsw/platform/win/ThreadImpl.cpp b/src/3rdParty/efsw/platform/win/ThreadImpl.cpp index d0fde8b..463934c 100755..100644 --- a/src/3rdParty/efsw/platform/win/ThreadImpl.cpp +++ b/src/3rdParty/efsw/platform/win/ThreadImpl.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace efsw { namespace Platform { | 9 | namespace efsw { namespace Platform { |
| 10 | 10 | ||
| 11 | ThreadImpl::ThreadImpl( Thread* owner ) { | 11 | ThreadImpl::ThreadImpl( efsw::Thread* owner ) { |
| 12 | mThread = reinterpret_cast<HANDLE>( | 12 | mThread = reinterpret_cast<HANDLE>( |
| 13 | _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) ); | 13 | _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) ); |
| 14 | 14 | ||
diff --git a/src/3rdParty/efsw/platform/win/ThreadImpl.hpp b/src/3rdParty/efsw/platform/win/ThreadImpl.hpp index 1afb593..455f24c 100755..100644 --- a/src/3rdParty/efsw/platform/win/ThreadImpl.hpp +++ b/src/3rdParty/efsw/platform/win/ThreadImpl.hpp | |||
| @@ -19,7 +19,7 @@ namespace Platform { | |||
| 19 | 19 | ||
| 20 | class ThreadImpl { | 20 | class ThreadImpl { |
| 21 | public: | 21 | public: |
| 22 | ThreadImpl( Thread* owner ); | 22 | explicit ThreadImpl( efsw::Thread* owner ); |
| 23 | 23 | ||
| 24 | ~ThreadImpl(); | 24 | ~ThreadImpl(); |
| 25 | 25 | ||
diff --git a/src/3rdParty/efsw/sophist.h b/src/3rdParty/efsw/sophist.h index 3a64504..82e5c36 100755..100644 --- a/src/3rdParty/efsw/sophist.h +++ b/src/3rdParty/efsw/sophist.h | |||
| @@ -1,147 +1,147 @@ | |||
| 1 | /* sophist.h - 0.3 - public domain - Sean Barrett 2010 | 1 | /* sophist.h - 0.3 - public domain - Sean Barrett 2010 |
| 2 | ** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net | 2 | ** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net |
| 3 | ** Sophist provides portable types; you typedef/#define them to your own names | 3 | ** Sophist provides portable types; you typedef/#define them to your own names |
| 4 | ** | 4 | ** |
| 5 | ** defines: | 5 | ** defines: |
| 6 | ** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian | 6 | ** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian |
| 7 | ** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined | 7 | ** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined |
| 8 | ** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit | 8 | ** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit |
| 9 | ** | 9 | ** |
| 10 | ** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer | 10 | ** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer |
| 11 | ** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16 | 11 | ** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16 |
| 12 | ** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64 | 12 | ** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64 |
| 13 | ** - SOPHIST_int64_constant(number) - macros for creating 64-bit | 13 | ** - SOPHIST_int64_constant(number) - macros for creating 64-bit |
| 14 | ** - SOPHIST_uint64_constant(number) integer constants | 14 | ** - SOPHIST_uint64_constant(number) integer constants |
| 15 | ** - SOPHIST_printf_format64 - string for printf format for int64 | 15 | ** - SOPHIST_printf_format64 - string for printf format for int64 |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #ifndef __INCLUDE_SOPHIST_H__ | 18 | #ifndef __INCLUDE_SOPHIST_H__ |
| 19 | #define __INCLUDE_SOPHIST_H__ | 19 | #define __INCLUDE_SOPHIST_H__ |
| 20 | 20 | ||
| 21 | #define SOPHIST_compiletime_assert(name,val) \ | 21 | #define SOPHIST_compiletime_assert(name,val) \ |
| 22 | typedef int SOPHIST__assert##name[(val) ? 1 : -1] | 22 | typedef int SOPHIST__assert##name[(val) ? 1 : -1] |
| 23 | 23 | ||
| 24 | /* define a couple synthetic rules to make code more readable */ | 24 | /* define a couple synthetic rules to make code more readable */ |
| 25 | #if (defined(__sparc__) || defined(__sparc)) && \ | 25 | #if (defined(__sparc__) || defined(__sparc)) && \ |
| 26 | (defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)) | 26 | (defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__)) |
| 27 | #define SOPHIST_sparc64 | 27 | #define SOPHIST_sparc64 |
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | #if (defined(linux) || defined(__linux__)) && \ | 30 | #if (defined(linux) || defined(__linux__)) && \ |
| 31 | (defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64)) | 31 | (defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64)) |
| 32 | #define SOPHIST_linux64 | 32 | #define SOPHIST_linux64 |
| 33 | #endif | 33 | #endif |
| 34 | 34 | ||
| 35 | /* basic types */ | 35 | /* basic types */ |
| 36 | typedef signed char SOPHIST_int8; | 36 | typedef signed char SOPHIST_int8; |
| 37 | typedef unsigned char SOPHIST_uint8; | 37 | typedef unsigned char SOPHIST_uint8; |
| 38 | 38 | ||
| 39 | typedef signed short SOPHIST_int16; | 39 | typedef signed short SOPHIST_int16; |
| 40 | typedef unsigned short SOPHIST_uint16; | 40 | typedef unsigned short SOPHIST_uint16; |
| 41 | 41 | ||
| 42 | #ifdef __palmos__ | 42 | #ifdef __palmos__ |
| 43 | typedef signed long SOPHIST_int32; | 43 | typedef signed long SOPHIST_int32; |
| 44 | typedef unsigned long SOPHIST_uint32; | 44 | typedef unsigned long SOPHIST_uint32; |
| 45 | #else | 45 | #else |
| 46 | typedef signed int SOPHIST_int32; | 46 | typedef signed int SOPHIST_int32; |
| 47 | typedef unsigned int SOPHIST_uint32; | 47 | typedef unsigned int SOPHIST_uint32; |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | #ifndef SOPHIST_NO_64 | 50 | #ifndef SOPHIST_NO_64 |
| 51 | #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ | 51 | #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ |
| 52 | || (defined(__alpha) && defined(__DECC)) | 52 | || (defined(__alpha) && defined(__DECC)) |
| 53 | 53 | ||
| 54 | typedef signed __int64 SOPHIST_int64; | 54 | typedef signed __int64 SOPHIST_int64; |
| 55 | typedef unsigned __int64 SOPHIST_uint64; | 55 | typedef unsigned __int64 SOPHIST_uint64; |
| 56 | #define SOPHIST_has_64 1 | 56 | #define SOPHIST_has_64 1 |
| 57 | #define SOPHIST_int64_constant(x) (x##i64) | 57 | #define SOPHIST_int64_constant(x) (x##i64) |
| 58 | #define SOPHIST_uint64_constant(x) (x##ui64) | 58 | #define SOPHIST_uint64_constant(x) (x##ui64) |
| 59 | #define SOPHIST_printf_format64 "I64" | 59 | #define SOPHIST_printf_format64 "I64" |
| 60 | 60 | ||
| 61 | #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) | 61 | #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) |
| 62 | 62 | ||
| 63 | typedef signed long SOPHIST_int64; | 63 | typedef signed long SOPHIST_int64; |
| 64 | typedef unsigned long SOPHIST_uint64; | 64 | typedef unsigned long SOPHIST_uint64; |
| 65 | 65 | ||
| 66 | #define SOPHIST_has_64 1 | 66 | #define SOPHIST_has_64 1 |
| 67 | #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) | 67 | #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) |
| 68 | #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) | 68 | #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) |
| 69 | #define SOPHIST_printf_format64 "l" | 69 | #define SOPHIST_printf_format64 "l" |
| 70 | 70 | ||
| 71 | #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ | 71 | #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ |
| 72 | || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ | 72 | || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ |
| 73 | || defined(sgi) || defined (__sgi) || defined(__sgi__) \ | 73 | || defined(sgi) || defined (__sgi) || defined(__sgi__) \ |
| 74 | || defined(_CRAYC) | 74 | || defined(_CRAYC) |
| 75 | 75 | ||
| 76 | typedef signed long long SOPHIST_int64; | 76 | typedef signed long long SOPHIST_int64; |
| 77 | typedef unsigned long long SOPHIST_uint64; | 77 | typedef unsigned long long SOPHIST_uint64; |
| 78 | 78 | ||
| 79 | #define SOPHIST_has_64 1 | 79 | #define SOPHIST_has_64 1 |
| 80 | #define SOPHIST_int64_constant(x) (x##LL) | 80 | #define SOPHIST_int64_constant(x) (x##LL) |
| 81 | #define SOPHIST_uint64_constant(x) (x##ULL) | 81 | #define SOPHIST_uint64_constant(x) (x##ULL) |
| 82 | #define SOPHIST_printf_format64 "ll" | 82 | #define SOPHIST_printf_format64 "ll" |
| 83 | #endif | 83 | #endif |
| 84 | #endif | 84 | #endif |
| 85 | 85 | ||
| 86 | #ifndef SOPHIST_has_64 | 86 | #ifndef SOPHIST_has_64 |
| 87 | #define SOPHIST_has_64 0 | 87 | #define SOPHIST_has_64 0 |
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1); | 90 | SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1); |
| 91 | SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2); | 91 | SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2); |
| 92 | SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4); | 92 | SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4); |
| 93 | SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4); | 93 | SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4); |
| 94 | 94 | ||
| 95 | #if SOPHIST_has_64 | 95 | #if SOPHIST_has_64 |
| 96 | SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8); | 96 | SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8); |
| 97 | SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8); | 97 | SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8); |
| 98 | #endif | 98 | #endif |
| 99 | 99 | ||
| 100 | /* determine whether pointers are 64-bit */ | 100 | /* determine whether pointers are 64-bit */ |
| 101 | 101 | ||
| 102 | #if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \ | 102 | #if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \ |
| 103 | || defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \ | 103 | || defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \ |
| 104 | || defined(__64BIT__) \ | 104 | || defined(__64BIT__) \ |
| 105 | || defined(__LP64) || defined(__LP64__) || defined(_LP64) \ | 105 | || defined(__LP64) || defined(__LP64__) || defined(_LP64) \ |
| 106 | || defined(_ADDR64) || defined(_CRAYC) \ | 106 | || defined(_ADDR64) || defined(_CRAYC) \ |
| 107 | 107 | ||
| 108 | #define SOPHIST_pointer64 1 | 108 | #define SOPHIST_pointer64 1 |
| 109 | 109 | ||
| 110 | SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8); | 110 | SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8); |
| 111 | 111 | ||
| 112 | typedef SOPHIST_int64 SOPHIST_intptr; | 112 | typedef SOPHIST_int64 SOPHIST_intptr; |
| 113 | typedef SOPHIST_uint64 SOPHIST_uintptr; | 113 | typedef SOPHIST_uint64 SOPHIST_uintptr; |
| 114 | #else | 114 | #else |
| 115 | 115 | ||
| 116 | #define SOPHIST_pointer64 0 | 116 | #define SOPHIST_pointer64 0 |
| 117 | 117 | ||
| 118 | SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4); | 118 | SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4); |
| 119 | 119 | ||
| 120 | /* do we care about pointers that are only 16-bit? */ | 120 | /* do we care about pointers that are only 16-bit? */ |
| 121 | typedef SOPHIST_int32 SOPHIST_intptr; | 121 | typedef SOPHIST_int32 SOPHIST_intptr; |
| 122 | typedef SOPHIST_uint32 SOPHIST_uintptr; | 122 | typedef SOPHIST_uint32 SOPHIST_uintptr; |
| 123 | 123 | ||
| 124 | #endif | 124 | #endif |
| 125 | 125 | ||
| 126 | SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *)); | 126 | SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *)); |
| 127 | 127 | ||
| 128 | /* enumerate known little endian cases; fallback to big-endian */ | 128 | /* enumerate known little endian cases; fallback to big-endian */ |
| 129 | 129 | ||
| 130 | #define SOPHIST_little_endian 1 | 130 | #define SOPHIST_little_endian 1 |
| 131 | #define SOPHIST_big_endian 2 | 131 | #define SOPHIST_big_endian 2 |
| 132 | 132 | ||
| 133 | #if defined(__386__) || defined(i386) || defined(__i386__) \ | 133 | #if defined(__386__) || defined(i386) || defined(__i386__) \ |
| 134 | || defined(__X86) || defined(_M_IX86) \ | 134 | || defined(__X86) || defined(_M_IX86) \ |
| 135 | || defined(_M_X64) || defined(__x86_64__) \ | 135 | || defined(_M_X64) || defined(__x86_64__) \ |
| 136 | || defined(alpha) || defined(__alpha) || defined(__alpha__) \ | 136 | || defined(alpha) || defined(__alpha) || defined(__alpha__) \ |
| 137 | || defined(_M_ALPHA) \ | 137 | || defined(_M_ALPHA) \ |
| 138 | || defined(ARM) || defined(_ARM) || defined(__arm__) \ | 138 | || defined(ARM) || defined(_ARM) || defined(__arm__) \ |
| 139 | || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ | 139 | || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ |
| 140 | || defined(_WIN32_WCE) || defined(__NT__) \ | 140 | || defined(_WIN32_WCE) || defined(__NT__) \ |
| 141 | || defined(__MIPSEL__) | 141 | || defined(__MIPSEL__) |
| 142 | #define SOPHIST_endian SOPHIST_little_endian | 142 | #define SOPHIST_endian SOPHIST_little_endian |
| 143 | #else | 143 | #else |
| 144 | #define SOPHIST_endian SOPHIST_big_endian | 144 | #define SOPHIST_endian SOPHIST_big_endian |
| 145 | #endif | 145 | #endif |
| 146 | 146 | ||
| 147 | #endif /* __INCLUDE_SOPHIST_H__ */ | 147 | #endif /* __INCLUDE_SOPHIST_H__ */ |
