OSDN Git Service

Some improvements to connectivity check: Start with small timeout and increase the...
[mutilities/MUtilities.git] / src / Global.cpp
index 2116f72..dc48e84 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // MuldeR's Utilities for Qt
-// Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2017 LoRd_MuldeR <MuldeR2@GMX.de>
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,7 @@
 //MUtils
 #include <MUtils/Global.h>
 #include <MUtils/OSSupport.h>
+#include <MUtils/Version.h>
 
 //Internal
 #include "DirLocker.h"
@@ -39,6 +40,7 @@
 #include <QPair>
 #include <QListIterator>
 #include <QMutex>
+#include <QThreadStorage>
 
 //CRT
 #include <cstdlib>
 // Random Support
 ///////////////////////////////////////////////////////////////////////////////
 
+#ifndef _CRT_RAND_S
+#define rand_s(X) (true)
+#endif
+
+//Per-thread init flag
+static QThreadStorage<bool> g_srand_flag;
+
 //Robert Jenkins' 96 bit Mix Function
-static unsigned int mix_function(const unsigned int x, const unsigned int y, const unsigned int z)
+static quint32 mix_function(const quint32 x, const quint32 y, const quint32 z)
 {
-       unsigned int a = x;
-       unsigned int b = y;
-       unsigned int c = z;
+       quint32 a = x;
+       quint32 b = y;
+       quint32 c = z;
        
        a=a-b;  a=a-c;  a=a^(c >> 13);
-       b=b-c;  b=b-a;  b=b^(a << ); 
+       b=b-c;  b=b-a;  b=b^(a <<  8); 
        c=c-a;  c=c-b;  c=c^(b >> 13);
        a=a-b;  a=a-c;  a=a^(c >> 12);
        b=b-c;  b=b-a;  b=b^(a << 16);
-       c=c-a;  c=c-b;  c=c^(b >> );
-       a=a-b;  a=a-c;  a=a^(c >> );
+       c=c-a;  c=c-b;  c=c^(b >>  5);
+       a=a-b;  a=a-c;  a=a^(c >>  3);
        b=b-c;  b=b-a;  b=b^(a << 10);
        c=c-a;  c=c-b;  c=c^(b >> 15);
 
        return a ^ b ^ c;
 }
 
-void MUtils::seed_rand(void)
+static void seed_rand(void)
 {
-       qsrand(mix_function(clock(), time(NULL), _getpid()));
+       QDateTime build(MUtils::Version::lib_build_date(), MUtils::Version::lib_build_time());
+       const quint32 seed = mix_function(MUtils::OS::process_id(), MUtils::OS::thread_id(), build.toMSecsSinceEpoch());
+       qsrand(mix_function(clock(), time(NULL), seed));
 }
 
-quint32 MUtils::next_rand32(void)
+static quint32 rand_fallback(void)
 {
-       quint32 rnd = 0xDEADBEEF;
-
-#ifdef _CRT_RAND_S
-       if(rand_s(&rnd) == 0)
+       Q_ASSERT(RAND_MAX >= 0xFFF);
+       if (!(g_srand_flag.hasLocalData() && g_srand_flag.localData()))
        {
-               return rnd;
+               seed_rand();
+               g_srand_flag.setLocalData(true);
        }
-#endif //_CRT_RAND_S
-
-       for(size_t i = 0; i < sizeof(quint32); i++)
+       quint32 rnd = 0x32288EA3;
+       for (size_t i = 0; i < 3; i++)
        {
-               rnd = (rnd << 8) ^ qrand();
+               rnd = (rnd << 12) ^ qrand();
        }
+       return rnd;
+}
 
+quint32 MUtils::next_rand_u32(void)
+{
+       quint32 rnd;
+       if (rand_s(&rnd))
+       {
+               return rand_fallback();
+       }
        return rnd;
 }
 
-quint64 MUtils::next_rand64(void)
+quint64 MUtils::next_rand_u64(void)
 {
-       return (quint64(next_rand32()) << 32) | quint64(next_rand32());
+       return (quint64(next_rand_u32()) << 32) | quint64(next_rand_u32());
 }
 
-QString MUtils::rand_str(const bool &bLong)
+QString MUtils::next_rand_str(const bool &bLong)
 {
-       if(!bLong)
+       if (bLong)
        {
-               return QString::number(next_rand64(), 16).rightJustified(16, QLatin1Char('0'));
+               return next_rand_str(false) + next_rand_str(false);
+       }
+       else
+       {
+               return QString::number(next_rand_u64(), 16).rightJustified(16, QLatin1Char('0'));
        }
-       return QString("%1%2").arg(rand_str(false), rand_str(false));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -163,7 +184,7 @@ QString MUtils::make_temp_file(const QString &basePath, const QString &extension
 {
        for(int i = 0; i < 4096; i++)
        {
-               const QString tempFileName = QString("%1/%2.%3").arg(basePath, rand_str(), extension);
+               const QString tempFileName = QString("%1/%2.%3").arg(basePath, next_rand_str(), extension);
                if(!QFileInfo(tempFileName).exists())
                {
                        if(placeholder)
@@ -252,7 +273,7 @@ static QString try_create_subfolder(const QString &baseDir, const QString &postf
 
 static MUtils::Internal::DirLock *try_init_temp_folder(const QString &baseDir)
 {
-       const QString tempPath = try_create_subfolder(baseDir, MUtils::rand_str());
+       const QString tempPath = try_create_subfolder(baseDir, MUtils::next_rand_str());
        if(!tempPath.isEmpty())
        {
                for(int i = 0; i < 32; i++)
@@ -385,6 +406,7 @@ bool MUtils::remove_file(const QString &fileName)
                {
                        return true;
                }
+               MUtils::OS::sleep_ms(1);
                fileInfo.refresh();
        }
 
@@ -444,6 +466,7 @@ bool MUtils::remove_directory(const QString &folderPath, const bool &recursive)
                {
                        return true;
                }
+               MUtils::OS::sleep_ms(1);
                folder.refresh();
        }
        
@@ -540,7 +563,14 @@ void MUtils::natural_string_sort(QStringList &list, const bool bIgnoreCase)
 
 QString MUtils::clean_file_name(const QString &name)
 {
-       static const char FILENAME_ILLEGAL_CHARS[] = "\\/:*?<>\"";
+       static const QLatin1Char REPLACEMENT_CHAR('_');
+       static const char FILENAME_ILLEGAL_CHARS[] = "<>:\"/\\|?*";
+       static const char *const FILENAME_RESERVED_NAMES[] =
+       {
+               "CON", "PRN", "AUX", "NUL",
+               "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
+               "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", NULL
+       };
 
        QString result(name);
        if (result.contains(QLatin1Char('"')))
@@ -554,13 +584,13 @@ QString MUtils::clean_file_name(const QString &name)
        {
                if (iter->category() == QChar::Other_Control)
                {
-                       *iter = QLatin1Char('_');
+                       *iter = REPLACEMENT_CHAR;
                }
        }
                
        for(size_t i = 0; FILENAME_ILLEGAL_CHARS[i]; i++)
        {
-               result.replace(QLatin1Char(FILENAME_ILLEGAL_CHARS[i]), QLatin1Char('_'));
+               result.replace(QLatin1Char(FILENAME_ILLEGAL_CHARS[i]), REPLACEMENT_CHAR);
        }
        
        trim_right(result);
@@ -570,6 +600,15 @@ QString MUtils::clean_file_name(const QString &name)
                trim_right(result);
        }
 
+       for (size_t i = 0; FILENAME_RESERVED_NAMES[i]; i++)
+       {
+               const QString reserved = QString::fromLatin1(FILENAME_RESERVED_NAMES[i]);
+               if ((!result.compare(reserved, Qt::CaseInsensitive)) || result.startsWith(reserved + QLatin1Char('.'), Qt::CaseInsensitive))
+               {
+                       result.replace(0, reserved.length(), QString().leftJustified(reserved.length(), REPLACEMENT_CHAR));
+               }
+       }
+
        return result;
 }