+ trim_right(result);
+ while (result.endsWith(QLatin1Char('.')))
+ {
+ result.chop(1);
+ 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;
+}
+
+static QPair<QString,QString> clean_file_path_get_prefix(const QString path)
+{
+ static const char *const PREFIXES[] =
+ {
+ "//?/", "//", "/", NULL
+ };
+ const QString posixPath = QDir::fromNativeSeparators(path.trimmed());
+ for (int i = 0; PREFIXES[i]; i++)
+ {
+ const QString prefix = QString::fromLatin1(PREFIXES[i]);
+ if (posixPath.startsWith(prefix))
+ {
+ return qMakePair(prefix, posixPath.mid(prefix.length()));
+ }
+ }
+ return qMakePair(QString(), posixPath);
+}
+
+QString MUtils::clean_file_path(const QString &path, const bool &pretty)
+{
+ const QPair<QString, QString> prefix = clean_file_path_get_prefix(path);
+
+ QStringList parts = prefix.second.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ for(int i = 0; i < parts.count(); i++)
+ {
+ if((i == 0) && (parts[i].length() == 2) && parts[i][0].isLetter() && (parts[i][1] == QLatin1Char(':')))
+ {
+ continue; //handle case "c:\"
+ }
+ parts[i] = MUtils::clean_file_name(parts[i], pretty);
+ }
+
+ const QString cleanPath = parts.join(QLatin1String("/"));
+ return prefix.first.isEmpty() ? cleanPath : prefix.first + cleanPath;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PARENT PATH
+///////////////////////////////////////////////////////////////////////////////
+
+static void remove_trailing_separators(QString &pathStr)
+{
+ while (pathStr.endsWith('/'))
+ {
+ pathStr.chop(1);
+ }
+}
+
+MUTILS_API QString MUtils::parent_path(const QString &path)
+{
+ QString parentPath(QDir::fromNativeSeparators(path));
+ remove_trailing_separators(parentPath);
+ const int pos = parentPath.lastIndexOf(QLatin1Char('/'));
+ if (pos >= 0)
+ {
+ parentPath.truncate(pos);
+ remove_trailing_separators(parentPath);
+ if (parentPath.isEmpty())
+ {
+ return QLatin1String("/");
+ }
+ if ((parentPath.length() == 2) && parentPath.at(0).isLetter() && (parentPath.at(1) == QLatin1Char(':')))
+ {
+ parentPath += QLatin1Char('/');
+ }
+ return parentPath;
+ }
+ return QString();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// REGULAR EXPESSION HELPER
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::regexp_parse_uint32(const QRegExp ®exp, quint32 &value)
+{
+ return regexp_parse_uint32(regexp, &value, 1U, 1U);
+}
+
+bool MUtils::regexp_parse_int32(const QRegExp ®exp, qint32 &value)
+{
+ return regexp_parse_int32(regexp, &value, 1U, 1U);
+}
+
+bool MUtils::regexp_parse_uint32(const QRegExp ®exp, quint32 &value, const size_t &offset)
+{
+ return regexp_parse_uint32(regexp, &value, offset, 1U);
+}
+
+bool MUtils::regexp_parse_int32(const QRegExp ®exp, qint32 &value, const size_t &offset)
+{
+ return regexp_parse_int32(regexp, &value, offset, 1U);
+}
+
+bool MUtils::regexp_parse_uint32(const QRegExp ®exp, quint32 *values, const size_t &count)
+{
+ return regexp_parse_uint32(regexp, values, 1U, count);
+}
+
+bool MUtils::regexp_parse_int32(const QRegExp ®exp, qint32 *values, const size_t &count)
+{
+ return regexp_parse_int32(regexp, values, 1U, count);
+}
+
+bool MUtils::regexp_parse_uint32(const QRegExp ®exp, quint32 *values, const size_t &offset, const size_t &count)
+{
+ const QStringList caps = regexp.capturedTexts();
+
+ if (caps.isEmpty() || (quint32(caps.count()) <= count))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < count; i++)
+ {
+ bool ok = false;
+ values[i] = caps[offset+i].toUInt(&ok);
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool MUtils::regexp_parse_int32(const QRegExp ®exp, qint32 *values, const size_t &offset, const size_t &count)
+{
+ const QStringList caps = regexp.capturedTexts();
+
+ if (caps.isEmpty() || (quint32(caps.count()) <= count))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < count; i++)
+ {
+ bool ok = false;
+ values[i] = caps[offset+i].toInt(&ok);
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AVAILABLE CODEPAGES
+///////////////////////////////////////////////////////////////////////////////
+
+QStringList MUtils::available_codepages(const bool &noAliases)
+{
+ QStringList codecList;
+ QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
+
+ while(!availableCodecs.isEmpty())
+ {
+ const QByteArray current = availableCodecs.takeFirst();
+ if(!current.toLower().startsWith("system"))
+ {
+ codecList << QString::fromLatin1(current.constData(), current.size());
+ if(noAliases)
+ {
+ if(QTextCodec *const currentCodec = QTextCodec::codecForName(current.constData()))
+ {
+ const QList<QByteArray> aliases = currentCodec->aliases();
+ for(QList<QByteArray>::ConstIterator iter = aliases.constBegin(); iter != aliases.constEnd(); iter++)
+ {
+ availableCodecs.removeAll(*iter);
+ }
+ }
+ }
+ }
+ }
+
+ return codecList;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// FP MATH SUPPORT
+///////////////////////////////////////////////////////////////////////////////
+
+MUtils::fp_parts_t MUtils::break_fp(const double value)
+{
+ fp_parts_t result = { };
+ if (_finite(value))
+ {
+ result.parts[1] = modf(value, &result.parts[0]);
+ }
+ else
+ {
+ result.parts[0] = std::numeric_limits<double>::quiet_NaN();
+ result.parts[1] = std::numeric_limits<double>::quiet_NaN();
+ }
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// INITIALIZER
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned int MUtils::Internal::MUTILS_INITIALIZER(const unsigned int interfaceId)
+{
+ if(interfaceId != ((unsigned int)MUTILS_INTERFACE))
+ {
+ OS::system_message_err(L"MUtils", L"ERROR: MUtils library initialization has failed!");
+ for(;;) _exit((int)0xC0000142);
+ }
+
+ volatile unsigned int _result = MUTILS_INTERFACE;
+ return _result;