OSDN Git Service

Added support for Visual Studio 2019.2 (v16.2).
[mutilities/MUtilities.git] / include / MUtils / Global.h
index 4a577c8..ca7fe75 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // MuldeR's Utilities for Qt
-// Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2019 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
@@ -20,9 +20,9 @@
 //////////////////////////////////////////////////////////////////////////////////
 
 /**
-* @file
-* @brief This file contains miscellaneous functions that are generally useful for Qt-based applications
-*/
+ * @file
+ * @brief This file contains miscellaneous functions that are generally useful for Qt-based applications
+ */
 
 #pragma once
 
 
 //Forward Declarations
 class QProcess;
+class QDir;
+template<typename K, typename V> class QHash;
 
 ///////////////////////////////////////////////////////////////////////////////
 
+/** \cond INTERNAL
+ */
+
+ //Interface version
+#define MUTILS_INTERFACE 3
+
 //MUtils API
 #ifdef _MSC_VER
 #      ifdef MUTILS_DLL_EXPORT
@@ -48,11 +56,6 @@ class QProcess;
 #      define MUTILS_API
 #endif
 
-//Helper Macros
-#define MUTILS_MAKE_STRING_HELPER(X) #X
-#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)
@@ -73,11 +76,36 @@ class QProcess;
        #endif
 #endif
 
+//Library initializer
+#define MUTILS_GLUE_NAME_HELPER(X,Y) X##Y
+#define MUTILS_GLUE_NAME(X,Y) MUTILS_GLUE_NAME_HELPER(X,Y)
+#if MUTILS_DEBUG
+#define MUTILS_INITIALIZER MUTILS_GLUE_NAME(initialize_d, MUTILS_INTERFACE)
+#else
+#define MUTILS_INITIALIZER MUTILS_GLUE_NAME(initialize_r, MUTILS_INTERFACE)
+#endif
+
+//Compiler warnings
+#define MUTILS_MAKE_STRING_HELPER(X) #X
+#define MUTILS_MAKE_STRING(X) MUTILS_MAKE_STRING_HELPER(X)
+#define MUTILS_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" MUTILS_MAKE_STRING(__LINE__) ") : warning: " TXT))
+
+/** \endcond INTERNAL
+ */
+
 ///////////////////////////////////////////////////////////////////////////////
 
+/**
+* \brief Global MUtils namespace
+*/
 namespace MUtils
 {
        /**
+       * \brief This struct containes the parts (integral and fractional part) of a floating-point number
+       */
+       typedef struct _fp_parts_t { double parts[2]; } fp_parts_t;
+
+       /**
        * \brief Rerieves the full path of the application's *Temp* folder.
        *
        * The application's *Temp* folder is a unique application-specific folder, intended to store any temporary files that the application may need. It will be created when this function is called for the first time (lazy initialization); subsequent calls are guaranteed to return the same path. Usually the application's *Temp* folder will be created as a sub-folder of the system's global *Temp* folder, as indicated by the `TMP` or `TEMP` environment variables. However, it may be created at a different place (e.g. in the users *Profile* directory), if those environment variables don't point to a usable directory. In any case, this function makes sure that the application's *Temp* folder exists for the whole lifetime of the application and that it is writable. When the application terminates normally, the application's *Temp* folder and all files or sub-directories thereof will be *removed* automatically!
@@ -86,8 +114,20 @@ namespace MUtils
        */
        MUTILS_API const QString& temp_folder(void);
 
-       //Process Utils
-       MUTILS_API void init_process(QProcess &process, const QString &wokringDir, const bool bReplaceTempDir = true, const QStringList *const extraPaths = NULL);
+       /**
+       * \brief Initialize a given [QProcess](http://doc.qt.io/qt-4.8/qprocess.html) object.
+       *
+       * This function prepares a given [QProcess](http://doc.qt.io/qt-4.8/qprocess.html) object for sub-process creation. It does so by setting up combined *stdout* and *stderr* redirection for the sub-process, cleaning up the sub-process' environment variables, as well as setting up the sub-process' working directory. Optionally, the *Temp* directory for the sub-process can be set to the application-specific *Temp* directory, which is achieved by overwriting the corresponding environment variables (e.g. `TMP` and `TEMP`). Furthermore, additional paths can be added to the `PATH` environment variable of the sub-process.
+       *
+       * \param process A reference to the [QProcess](http://doc.qt.io/qt-4.8/qprocess.html) object to be initialized. The [QProcess](http://doc.qt.io/qt-4.8/qprocess.html) object must be initialized *before* calling the `QProcess::start()` method.
+       *
+       * \param process A read-only reference to a QString holding the path of the working directory for the sub-process.
+       *
+       * \param bReplaceTempDir If set to `true`, the *Temp* directory for the sub-process is set to the application-specific *Temp* directory; if set to `false`, the default *Temp* directory is retained.
+       *
+       * \param extraPaths A read-only pointer to a QStringList object containing additional paths that will be added (prepended) to the sub-process' `PATH` environment variable. This parameter can be `NULL`, in which case *no* additional paths are added.
+       */
+       MUTILS_API void init_process(QProcess &process, const QString &wokringDir, const bool bReplaceTempDir = true, const QStringList *const extraPaths = NULL, const QHash<QString, QString> *const extraEnv = NULL);
 
        /**
        * \brief Generates a *random* unsigned 32-Bit value.
@@ -97,7 +137,8 @@ namespace MUtils
        * \return The function returns a *random* unsigned 32-Bit value.
        */
        MUTILS_API quint32 next_rand_u32(void);
-       
+       MUTILS_API quint32 next_rand_u32(const quint32 max);
+
        /**
        * \brief Generates a *random* unsigned 64-Bit value.
        *
@@ -132,6 +173,7 @@ namespace MUtils
        * \return If the function succeeds, it returns a QString holding the full path of the temporary file; otherwise it returns a default-constructed QString.
        */
        MUTILS_API QString make_temp_file(const QString &basePath, const QString &extension, const bool placeholder = false);
+       MUTILS_API QString make_temp_file(const QDir    &basePath, const QString &extension, const bool placeholder = false);
 
        /**
        * \brief Generates a unique file name.
@@ -144,11 +186,12 @@ namespace MUtils
        *
        * \param extension Specifies the desired file extensions of the unique file. Do **not** include a leading dot (`.`) character.
        *
-       * \param fancy If set to `true`, the file name is generated according to the `"<basedir>/<basename> (N).<ext>"` pattern; if set to `false`, the file name is generated according to the `"<basedir>/<basename>.XXXX.<ext>"` pattern.
+       * \param fancy If set to `true`, the unique file name is generated according to the `"<basedir>/<basename> (N).<ext>"` pattern; if set to `false`, it is generated according to the `"<basedir>/<basename>.XXXX.<ext>"` pattern. Also, if set to `true`, a counter is only included in the file name, if the file name *without* counter already exists; if set to `false`, a counter is always included. Finally, if set to `true`, the counter starts at **2** and is printed in decimal format; if set to `false`, the counter starts at **0** and is printed in zero-padded hexadecimal format.
        *
        * \return If the function succeeds, it returns a QString holding the full path of the unique file; otherwise it returns a default-constructed QString.
        */
-       MUTILS_API QString make_unique_file(const QString &basePath, const QString &baseName, const QString &extension, const bool fancy = false);
+       MUTILS_API QString make_unique_file(const QString &basePath, const QString &baseName, const QString &extension, const bool fancy = false, const bool placeholder = false);
+       MUTILS_API QString make_unique_file(const QDir    &basePath, const QString &baseName, const QString &extension, const bool fancy = false, const bool placeholder = false);
 
        /**
        * \brief Computes the *parity* of the given unsigned 32-Bit value
@@ -238,8 +281,31 @@ namespace MUtils
        */
        MUTILS_API void natural_string_sort(QStringList &list, const bool bIgnoreCase);
 
-       MUTILS_API QString clean_file_name(const QString &name);
-       MUTILS_API QString clean_file_path(const QString &path);
+       /**
+       * \brief Clean up a file name string
+       *
+       * This function ensures that the given string is a valid file (or directory) name. It does so by replacing any illegal characters, i.e. any characters *not* allowed in file names (which explicitly *includes* directory separators). Furthermore, the function will trim/remove specific characters that are *not* allowed directly at the beginning or end of a file name. Finally, the function takes care of special "reserved" file names that are forbidden by the file system. You can use this function to convert user inputs into a valid file name.
+       *
+       * \param name A read-only reference to the QString holding the original, potentially invalid file name.
+       *
+       * \param pretty If set to `true`, the function tries to generate a "pretty" file name from the given file name. Otherwise, the function simply replaces each forbidden file name character by an underscore character.
+       *
+       * \return The function returns a QString holding a valid file name. If, however, the input string was empty or contained only white-space characters, the returned sting can be empty.
+       */
+       MUTILS_API QString clean_file_name(const QString &name, const bool &pretty);
+
+       /**
+       * \brief Clean up a file path string
+       *
+       * This function ensures that the given string is a valid file (or directory) path. It does so by replacing any illegal characters, i.e. any characters *not* allowed in file paths. Directory separators are preserved, but they will be "canonicalized". Furthermore, in each path component, the function will trim/remove specific characters that are *not* allowed directly at the beginning or end of a path component. Finally, the function takes care of special "reserved" file names that are forbidden by the file system. You can use this function to convert user inputs into a valid file path.
+       *
+       * \param path A read-only reference to the QString holding the original, potentially invalid file path.
+       *
+       * \param pretty If set to `true`, the function tries to generate "pretty" file names from the given file names. Otherwise, the function simply replaces each forbidden file name character by an underscore character.
+       *
+       * \return The function returns a QString holding a valid file path. If, however, the input string was empty or contained only white-space characters, the returned sting can be empty.
+       */
+       MUTILS_API QString clean_file_path(const QString &path, const bool &pretty);
 
        /**
        * \brief Parse regular expression results
@@ -253,6 +319,9 @@ namespace MUtils
        * \return The function returns `true`, if the regular expression's capture could be parsed successfully; it returns `false`, if the capture contains an invalid string or if there are insufficient captures in given the [QRegExp](http://doc.qt.io/qt-4.8/qregexp.html) object.
        */
        MUTILS_API bool regexp_parse_uint32(const QRegExp &regexp, quint32 &value);
+       MUTILS_API bool regexp_parse_int32(const QRegExp &regexp, qint32 &value);
+       MUTILS_API bool regexp_parse_uint32(const QRegExp &regexp, quint32 &value, const size_t &offset);
+       MUTILS_API bool regexp_parse_int32(const QRegExp &regexp, qint32 &value, const size_t &offset);
 
        /**
        * \brief Parse regular expression results
@@ -268,6 +337,9 @@ namespace MUtils
        * \return The function returns `true`, if all of the regular expression's captures could be parsed successfully; it returns `false`, if any of the captures contain an invalid string or if there are insufficient captures in given the [QRegExp](http://doc.qt.io/qt-4.8/qregexp.html) object.
        */
        MUTILS_API bool regexp_parse_uint32(const QRegExp &regexp, quint32 *values, const size_t &count);
+       MUTILS_API bool regexp_parse_int32(const QRegExp &regexp, qint32 *values, const size_t &count);
+       MUTILS_API bool regexp_parse_uint32(const QRegExp &regexp, quint32 *values, const size_t &offset, const size_t &count);
+       MUTILS_API bool regexp_parse_int32(const QRegExp &regexp, qint32 *values, const size_t &offset, const size_t &count);
 
        /**
        * \brief Retrieve a list of all available codepages
@@ -280,27 +352,69 @@ namespace MUtils
        */
        MUTILS_API QStringList available_codepages(const bool &noAliases = true);
 
-       //Internal
+       /**
+       * \brief Break floating-point number into fractional and integral parts
+       *
+       * The function returns a struct containing the fractional and the integral part of a given floating-point values as two separate values. This is a convenience warapper for the `modf()` function.
+       *
+       * \param value The original floating-point value
+       *
+       * \return Returns a struct containing the fractional and integral parts.
+       */
+       MUTILS_API fp_parts_t break_fp(const double value);
+
+       //Internal (do *not* call directly!)
        namespace Internal
        {
-               MUTILS_API int selfTest(const char *const buildKey, const bool debug);
-               static const int s_selfTest = selfTest(__DATE__ "@" __TIME__, MUTILS_DEBUG);
+               MUTILS_API unsigned int MUTILS_INITIALIZER(const unsigned int interfaceId);
+               static const unsigned int init_flag = MUTILS_INITIALIZER(MUTILS_INTERFACE);
        }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-//Delete helper
+/** \brief Deletes the object, if and only if the given pointer is *not* NULL. Also sets pointer to NULL after object has been deleted.
+*/
 #define MUTILS_DELETE(PTR) do { if((PTR)) { delete (PTR); (PTR) = NULL; } } while(0)
+
+/** \brief Deletes the array, if and only if the given pointer is *not* NULL. Also sets pointer to NULL after array has been deleted.
+*/
 #define MUTILS_DELETE_ARRAY(PTR) do { if((PTR)) { delete [] (PTR); (PTR) = NULL; } } while(0)
 
-//Zero memory
+/** \brief Clears the specified variable or struct by setting all of its bytes to *zero* (`0x00`). Do **not** use for arrays.
+*/
 #define MUTILS_ZERO_MEMORY(PTR) memset(&(PTR), 0, sizeof((PTR)))
 
-//String conversion macros
+/** \brief Converts a given QString object to a `wchar_t*` pointer. Does **not** copy the string data, so do **not** free the pointer! The returned pointer only remains valid until the underlying QString is modified or goes out of scope.
+*/
 #define MUTILS_WCHR(STR) (reinterpret_cast<const wchar_t*>((STR).utf16()))
+
+/** \brief Converts a given QString object to a `char*` pointer. The string is converted to UTF-8 encoding. The pointer is valid *only* while the expression is being evaluated, so do **not** free or store this pointer! Mainly useful for function calls that require a `char*` argument.
+*/
 #define MUTILS_UTF8(STR) ((STR).toUtf8().constData())
+
+/** \brief Converts a given QString object to a `char*` pointer. The string is converted to Latin-1 encoding. The pointer is valid *only* while the expression is being evaluated, so do **not** free or store this pointer! Mainly useful for function calls that require a `char*` argument.
+*/
+#define MUTILS_L1STR(STR) ((STR).toLatin1().constData())
+
+/** \brief Creates a QString object from a given `wchar_t*` buffer. The buffer is expected to conatin a NULL-terminated string in UTF-16 encoding. The string data is copied into the new QString object, however the original buffer will **not** be freed automatically!
+*/
 #define MUTILS_QSTR(STR) (QString::fromUtf16(reinterpret_cast<const unsigned short*>((STR))))
 
-//Boolean helper
+/** \brief Converts a boolean expression into a string. A *true* boolean expression is converted to the string `"1"`; a *false* boolean expression is converted to the string `"0"`.
+*/
 #define MUTILS_BOOL2STR(X) ((X) ? "1" : "0")
+
+/** \brief Converts a given expression into a boolean expression, by application of double negation operator.
+*/
+#define MUTILS_BOOLIFY(X) (!(!(X)))
+
+/** \brief Get length of an array, only works with local array variables!
+*/
+#define MUTILS_ARR2LEN(X) (sizeof((X)) / sizeof((X)[0]))
+
+/** \brief Disables copy constructor and assignment operator in the specified class. This macro should be used in the "private" section of the class' declaration.
+*/
+#define MUTILS_NO_COPY(CLASS) \
+       CLASS(const CLASS &) { throw "Copy constructor is disabled!"; } \
+       CLASS &operator=(const CLASS &) { throw "Assignment operator is disabled!"; }