OSDN Git Service

Overhaul of the temp_folder() function + use scoped pointers for global objects.
authorLoRd_MuldeR <mulder2@gmx.de>
Mon, 24 Nov 2014 21:29:00 +0000 (22:29 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Mon, 24 Nov 2014 21:29:00 +0000 (22:29 +0100)
MUtilities_VS2013.vcxproj
include/MUtils/Global.h
include/MUtils/OSSupport.h
src/Global.cpp
src/OSSupport_Win32.cpp

index 130c12a..3ab810e 100644 (file)
       <Optimization>Full</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;MUTILS_DLL_EXPORT;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_NODLL;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;MUTILS_STATIC_LIB;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_NODLL;QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
       <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
index 07a33f2..797604d 100644 (file)
@@ -33,10 +33,14 @@ class QProcess;
 #      ifdef MUTILS_DLL_EXPORT
 #              define MUTILS_API __declspec(dllexport)
 #      else
-#              define MUTILS_API __declspec(dllimport)
+#              ifndef MUTILS_STATIC_LIB
+#                      define MUTILS_API __declspec(dllimport)
+#              else
+#                      define MUTILS_API /*static lib*/
+#              endif
 #      endif
 #else
-#              define MUTILS_API
+#      define MUTILS_API
 #endif
 
 //Helper Macros
@@ -44,6 +48,19 @@ class QProcess;
 #define MUTILS_MAKE_STRING(X) MUTILS_MAKE_STRING_HELPER(X)
 #define MUTILS_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" MUTILS_MAKE_STRING(__LINE__) ") : warning: " TXT))
 
+//Check Debug Flags
+#if defined(_DEBUG) || defined(DEBUG) || (!defined(NDEBUG))
+#      define MUTILS_DEBUG 1
+#      if defined(NDEBUG) || defined(QT_NO_DEBUG) || (!defined(QT_DEBUG))
+#              error Inconsistent DEBUG flags have been detected!
+#      endif
+#else
+#      define MUTILS_DEBUG 0
+#      if (!defined(NDEBUG)) || (!defined(QT_NO_DEBUG)) || defined(QT_DEBUG)
+#              error Inconsistent DEBUG flags have been detected!
+#      endif
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace MUtils
@@ -61,7 +78,14 @@ namespace MUtils
        MUTILS_API quint64 next_rand64(void);
 
        //Version
-       MUTILS_API const char* buildDate(void);
+       MUTILS_API const char* mutils_build_date(void);
+       MUTILS_API const char* mutils_build_time(void);
+       //Internal
+       namespace Internal
+       {
+               MUTILS_API int selfTest(const char *const date, const bool debug);
+               static const int g_selfTestRet = selfTest(__DATE__, MUTILS_DEBUG);
+       }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -86,6 +110,6 @@ while(0)
 } \
 while(0)
 
-#define MUTILS_QUTF8(STR) ((STR).toUtf8().constData())
 #define MUTILS_QSTR2WCHAR(STR) (reinterpret_cast<const wchar_t*>((STR).utf16()))
+#define MUTILS_QSTR2QUTF8(STR) ((STR).toUtf8().constData())
 #define MUTILS_WCHAR2QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
index 0d8ed5e..1a0f9f0 100644 (file)
@@ -53,6 +53,11 @@ namespace MUtils
                }
                network_type_t;
                
+               //System message
+               MUTILS_API void system_message_nfo(const wchar_t *const title, const wchar_t *const text);
+               MUTILS_API void system_message_wrn(const wchar_t *const title, const wchar_t *const text);
+               MUTILS_API void system_message_err(const wchar_t *const title, const wchar_t *const text);
+
                //Get known Folder
                MUTILS_API const QString &known_folder(known_folder_t folder_id);
 
index 81614d2..b560432 100644 (file)
@@ -102,70 +102,47 @@ QString MUtils::rand_str(const bool &bLong)
 // TEMP FOLDER
 ///////////////////////////////////////////////////////////////////////////////
 
-static QReadWriteLock g_temp_folder_lock;
-static QFile*         g_temp_folder_file = NULL;
-static QString*       g_temp_folder_path = NULL;
-
-#define INIT_TEMP_FOLDER_RAND(OUT_PTR, FILE_PTR, BASE_DIR) do \
-{ \
-       for(int _i = 0; _i < 128; _i++) \
-       { \
-               const QString _randDir = QString("%1/%2").arg((BASE_DIR), rand_str()); \
-               if(!QDir(_randDir).exists()) \
-               { \
-                       *(OUT_PTR) = try_init_folder(_randDir, (FILE_PTR)); \
-                       if(!(OUT_PTR)->isEmpty()) break; \
-               } \
-       } \
-} \
-while(0)
-
-static QString try_init_folder(const QString &folderPath, QFile *&lockFile)
-{
-       static const char *TEST_DATA = "Lorem ipsum dolor sit amet, consectetur, adipisci velit!";
-       
-       bool success = false;
-
-       const QFileInfo folderInfo(folderPath);
-       const QDir folderDir(folderInfo.absoluteFilePath());
-
-       //Remove existing lock file
-       if(lockFile)
-       {
-               lockFile->remove();
-               MUTILS_DELETE(lockFile);
-       }
+static QScopedPointer<QFile>   g_temp_folder_file;
+static QScopedPointer<QString> g_temp_folder_path;
+static QReadWriteLock          g_temp_folder_lock;
 
-       //Create folder, if it does *not* exist yet
-       if(!folderDir.exists())
+static QString try_create_subfolder(const QString &baseDir, const QString &postfix)
+{
+       const QString baseDirPath = QDir(baseDir).absolutePath();
+       for(int i = 0; i < 32; i++)
        {
-               for(int i = 0; i < 16; i++)
+               QDir directory(baseDirPath);
+               if(directory.mkpath(postfix) && directory.cd(postfix))
                {
-                       if(folderDir.mkpath(".")) break;
+                       return directory.canonicalPath();
                }
        }
+       return QString();
+}
 
-       //Make sure folder exists now *and* is writable
-       if(folderDir.exists())
+static QString try_init_temp_folder(const QString &baseDir)
+{
+       static const char *TEST_DATA = "Lorem ipsum dolor sit amet, consectetur, adipisci velit!";
+       
+       QString tempPath = try_create_subfolder(baseDir, MUtils::rand_str());
+       if(!tempPath.isEmpty())
        {
                const QByteArray testData = QByteArray(TEST_DATA);
                for(int i = 0; i < 32; i++)
                {
-                       lockFile = new QFile(folderDir.absoluteFilePath(QString("~%1.tmp").arg(MUtils::rand_str())));
-                       if(lockFile->open(QIODevice::ReadWrite | QIODevice::Truncate))
+                       g_temp_folder_file.reset(new QFile(QString("%1/~%2.lck").arg(tempPath, MUtils::rand_str())));
+                       if(g_temp_folder_file->open(QIODevice::ReadWrite | QIODevice::Truncate))
                        {
-                               if(lockFile->write(testData) >= testData.size())
+                               if(g_temp_folder_file->write(testData) >= testData.size())
                                {
-                                       success = true;
-                                       break;
+                                       return tempPath;
                                }
-                               lockFile->remove();
-                               MUTILS_DELETE(lockFile);
+                               g_temp_folder_file->remove();
                        }
                }
        }
 
-       return (success ? folderDir.canonicalPath() : QString());
+       return QString();
 }
 
 const QString &MUtils::temp_folder(void)
@@ -173,9 +150,9 @@ const QString &MUtils::temp_folder(void)
        QReadLocker readLock(&g_temp_folder_lock);
 
        //Already initialized?
-       if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
+       if((!g_temp_folder_path.isNull()) && (!g_temp_folder_path->isEmpty()))
        {
-               return (*g_temp_folder_path);
+               return (*g_temp_folder_path.data());
        }
 
        //Obtain the write lock to initilaize
@@ -183,52 +160,41 @@ const QString &MUtils::temp_folder(void)
        QWriteLocker writeLock(&g_temp_folder_lock);
        
        //Still uninitilaized?
-       if(g_temp_folder_path && (!g_temp_folder_path->isEmpty()))
+       if((!g_temp_folder_path.isNull()) && (!g_temp_folder_path->isEmpty()))
        {
-               return (*g_temp_folder_path);
+               return (*g_temp_folder_path.data());
        }
 
-       //Create the string, if not done yet
-       if(!g_temp_folder_path)
-       {
-               g_temp_folder_path = new QString();
-       }
-       
-       g_temp_folder_path->clear();
-
        //Try the %TMP% or %TEMP% directory first
-       QString tempPath = try_init_folder(QDir::temp().absolutePath(), g_temp_folder_file);
+       QString tempPath = try_init_temp_folder(QDir::tempPath());
        if(!tempPath.isEmpty())
        {
-               INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
+               g_temp_folder_path.reset(new QString(tempPath));
+               return (*g_temp_folder_path.data());
        }
 
-       //Otherwise create TEMP folder in %LOCALAPPDATA% or %SYSTEMROOT%
-       if(g_temp_folder_path->isEmpty())
+       qWarning("%%TEMP%% directory not found -> trying fallback mode now!");
+       static const OS::known_folder_t FOLDER_ID[2] = { OS::FOLDER_LOCALAPPDATA, OS::FOLDER_SYSTROOT_DIR };
+       for(size_t id = 0; id < 2; id++)
        {
-               qWarning("%%TEMP%% directory not found -> trying fallback mode now!");
-               static const OS::known_folder_t folderId[2] = { OS::FOLDER_LOCALAPPDATA, OS::FOLDER_SYSTROOT_DIR };
-               for(size_t id = 0; (g_temp_folder_path->isEmpty() && (id < 2)); id++)
+               const QString &knownFolder = OS::known_folder(FOLDER_ID[id]);
+               if(!knownFolder.isEmpty())
                {
-                       const QString &knownFolder = OS::known_folder(folderId[id]);
-                       if(!knownFolder.isEmpty())
+                       const QString tempRoot = try_create_subfolder(knownFolder, QLatin1String("TEMP"));
+                       if(!tempRoot.isEmpty())
                        {
-                               tempPath = try_init_folder(QString("%1/Temp").arg(knownFolder), g_temp_folder_file);
+                               tempPath = try_init_temp_folder(tempRoot);
                                if(!tempPath.isEmpty())
                                {
-                                       INIT_TEMP_FOLDER_RAND(g_temp_folder_path, g_temp_folder_file, tempPath);
+                                       g_temp_folder_path.reset(new QString(tempPath));
+                                       return (*g_temp_folder_path.data());
                                }
                        }
                }
        }
 
-       //Failed to create TEMP folder?
-       if(g_temp_folder_path->isEmpty())
-       {
-               qFatal("Temporary directory could not be initialized !!!");
-       }
-       
-       return (*g_temp_folder_path);
+       qFatal("Temporary directory could not be initialized !!!");
+       return (*((QString*)NULL));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -279,3 +245,33 @@ void MUtils::init_process(QProcess &process, const QString &wokringDir, const bo
        process.setReadChannel(QProcess::StandardOutput);
        process.setProcessEnvironment(env);
 }
+
+///////////////////////////////////////////////////////////////////////////////
+// LIB VERSION
+///////////////////////////////////////////////////////////////////////////////
+
+const char* MUtils::mutils_build_date(void)
+{
+       static const char *const BUILD_DATE = __DATE__;
+       return BUILD_DATE;
+}
+
+const char* MUtils::mutils_build_time(void)
+{
+       static const char *const BUILD_TIME = __TIME__;
+       return BUILD_TIME;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SELF-TEST
+///////////////////////////////////////////////////////////////////////////////
+
+int MUtils::Internal::selfTest(const char *const date, const bool debug)
+{
+       if(strcmp(date, __DATE__) || (MUTILS_DEBUG != debug))
+       {
+               MUtils::OS::system_message_err(L"MUtils", L"FATAL ERROR: MUtils library version mismatch detected!");
+               abort();
+       }
+       return 0;
+}
index 37b2fbd..c8145d5 100644 (file)
 static const DWORD g_main_thread_id = GetCurrentThreadId();
 
 ///////////////////////////////////////////////////////////////////////////////
+// SYSTEM MESSAGE
+///////////////////////////////////////////////////////////////////////////////
+
+void MUtils::OS::system_message_nfo(const wchar_t *const title, const wchar_t *const text)
+{
+       MessageBoxW(NULL, text, title, MB_TOPMOST | MB_TASKMODAL | MB_ICONINFORMATION);
+}
+
+void MUtils::OS::system_message_wrn(const wchar_t *const title, const wchar_t *const text)
+{
+       MessageBoxW(NULL, text, title, MB_TOPMOST | MB_TASKMODAL | MB_ICONWARNING);
+}
+
+void MUtils::OS::system_message_err(const wchar_t *const title, const wchar_t *const text)
+{
+       MessageBoxW(NULL, text, title, MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // KNWON FOLDERS
 ///////////////////////////////////////////////////////////////////////////////
 
+typedef QMap<size_t, QString> KFMap;
 typedef HRESULT (WINAPI *SHGetKnownFolderPath_t)(const GUID &rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
 typedef HRESULT (WINAPI *SHGetFolderPath_t)(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath);
 
-static QMap<size_t, QString>* g_known_folders_map;
+static QScopedPointer<KFMap>  g_known_folders_map;
 static SHGetKnownFolderPath_t g_known_folders_fpGetKnownFolderPath;
 static SHGetFolderPath_t      g_known_folders_fpGetFolderPath;
 static QReadWriteLock         g_known_folders_lock;
@@ -91,7 +111,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id)
        QReadLocker readLock(&g_known_folders_lock);
 
        //Already in cache?
-       if(g_known_folders_map)
+       if(!g_known_folders_map.isNull())
        {
                if(g_known_folders_map->contains(folderId))
                {
@@ -104,7 +124,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id)
        QWriteLocker writeLock(&g_known_folders_lock);
 
        //Still not in cache?
-       if(g_known_folders_map)
+       if(!g_known_folders_map.isNull())
        {
                if(g_known_folders_map->contains(folderId))
                {
@@ -113,7 +133,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id)
        }
 
        //Initialize on first call
-       if(!g_known_folders_map)
+       if(g_known_folders_map.isNull())
        {
                QLibrary shell32("shell32.dll");
                if(shell32.load())
@@ -121,7 +141,7 @@ const QString &MUtils::OS::known_folder(known_folder_t folder_id)
                        g_known_folders_fpGetFolderPath =      (SHGetFolderPath_t)      shell32.resolve("SHGetFolderPathW");
                        g_known_folders_fpGetKnownFolderPath = (SHGetKnownFolderPath_t) shell32.resolve("SHGetKnownFolderPath");
                }
-               g_known_folders_map = new QMap<size_t, QString>();
+               g_known_folders_map.reset(new QMap<size_t, QString>());
        }
 
        QString folderPath;
@@ -244,7 +264,7 @@ static volatile bool   g_fatal_exit_flag = true;
 
 static DWORD WINAPI fatal_exit_helper(LPVOID lpParameter)
 {
-       MessageBoxA(NULL, ((LPCSTR) lpParameter), "Guru Meditation", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST | MB_SETFOREGROUND);
+       MessageBoxA(NULL, ((LPCSTR) lpParameter), "GURU MEDITATION", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST | MB_SETFOREGROUND);
        return 0;
 }