aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp872
1 files changed, 872 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp b/Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp
new file mode 100644
index 00000000..d41a5494
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/common/mptPathString.cpp
@@ -0,0 +1,872 @@
+/*
+ * mptPathString.cpp
+ * -----------------
+ * Purpose: Wrapper class around the platform-native representation of path names. Should be the only type that is used to store path names.
+ * Notes : Currently none.
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+#include "stdafx.h"
+#include "mptPathString.h"
+
+#include "mpt/uuid/uuid.hpp"
+
+#include "misc_util.h"
+
+#include "mptRandom.h"
+
+#if MPT_OS_WINDOWS
+#include <windows.h>
+#if defined(MODPLUG_TRACKER)
+#include <shlwapi.h>
+#endif
+#include <tchar.h>
+#endif
+
+OPENMPT_NAMESPACE_BEGIN
+
+#if MPT_OS_WINDOWS
+
+namespace mpt
+{
+
+
+RawPathString PathString::AsNativePrefixed() const
+{
+#if MPT_OS_WINDOWS_WINRT && (_WIN32_WINNT < 0x0a00)
+ // For WinRT on Windows 8, there is no official wy to determine an absolute path.
+ return path;
+#else
+ if(path.length() < MAX_PATH || path.substr(0, 4) == PL_("\\\\?\\"))
+ {
+ // Path is short enough or already in prefixed form
+ return path;
+ }
+ const RawPathString absPath = mpt::GetAbsolutePath(*this).AsNative();
+ if(absPath.substr(0, 2) == PL_("\\\\"))
+ {
+ // Path is a network share: \\server\foo.bar -> \\?\UNC\server\foo.bar
+ return PL_("\\\\?\\UNC") + absPath.substr(1);
+ } else
+ {
+ // Regular file: C:\foo.bar -> \\?\C:\foo.bar
+ return PL_("\\\\?\\") + absPath;
+ }
+#endif
+}
+
+
+#if !MPT_OS_WINDOWS_WINRT
+
+int PathString::CompareNoCase(const PathString & a, const PathString & b)
+{
+ return lstrcmpi(a.path.c_str(), b.path.c_str());
+}
+
+#endif // !MPT_OS_WINDOWS_WINRT
+
+
+// Convert a path to its simplified form, i.e. remove ".\" and "..\" entries
+// Note: We use our own implementation as PathCanonicalize is limited to MAX_PATH
+// and unlimited versions are only available on Windows 8 and later.
+// Furthermore, we also convert forward-slashes to backslashes and always remove trailing slashes.
+PathString PathString::Simplify() const
+{
+ if(path.empty())
+ return PathString();
+
+ std::vector<RawPathString> components;
+ RawPathString root;
+ RawPathString::size_type startPos = 0;
+ if(path.size() >= 2 && path[1] == PC_(':'))
+ {
+ // Drive letter
+ root = path.substr(0, 2) + PC_('\\');
+ startPos = 2;
+ } else if(path.substr(0, 2) == PL_("\\\\"))
+ {
+ // Network share
+ root = PL_("\\\\");
+ startPos = 2;
+ } else if(path.substr(0, 2) == PL_(".\\") || path.substr(0, 2) == PL_("./"))
+ {
+ // Special case for relative paths
+ root = PL_(".\\");
+ startPos = 2;
+ } else if(path.size() >= 1 && (path[0] == PC_('\\') || path[0] == PC_('/')))
+ {
+ // Special case for relative paths
+ root = PL_("\\");
+ startPos = 1;
+ }
+
+ while(startPos < path.size())
+ {
+ auto pos = path.find_first_of(PL_("\\/"), startPos);
+ if(pos == RawPathString::npos)
+ pos = path.size();
+ mpt::RawPathString dir = path.substr(startPos, pos - startPos);
+ if(dir == PL_(".."))
+ {
+ // Go back one directory
+ if(!components.empty())
+ {
+ components.pop_back();
+ }
+ } else if(dir == PL_("."))
+ {
+ // nop
+ } else if(!dir.empty())
+ {
+ components.push_back(std::move(dir));
+ }
+ startPos = pos + 1;
+ }
+
+ RawPathString result = root;
+ result.reserve(path.size());
+ for(const auto &component : components)
+ {
+ result += component + PL_("\\");
+ }
+ if(!components.empty())
+ result.pop_back();
+ return mpt::PathString(result);
+}
+
+} // namespace mpt
+
+#endif // MPT_OS_WINDOWS
+
+
+namespace mpt
+{
+
+
+#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+
+void PathString::SplitPath(PathString *drive, PathString *dir, PathString *fname, PathString *ext) const
+{
+ // We cannot use CRT splitpath here, because:
+ // * limited to _MAX_PATH or similar
+ // * no support for UNC paths
+ // * no support for \\?\ prefixed paths
+
+ if(drive) *drive = mpt::PathString();
+ if(dir) *dir = mpt::PathString();
+ if(fname) *fname = mpt::PathString();
+ if(ext) *ext = mpt::PathString();
+
+ mpt::RawPathString p = path;
+
+ // remove \\?\\ prefix
+ if(p.substr(0, 8) == PL_("\\\\?\\UNC\\"))
+ {
+ p = PL_("\\\\") + p.substr(8);
+ } else if(p.substr(0, 4) == PL_("\\\\?\\"))
+ {
+ p = p.substr(4);
+ }
+
+ if (p.length() >= 2 && (
+ p.substr(0, 2) == PL_("\\\\")
+ || p.substr(0, 2) == PL_("\\/")
+ || p.substr(0, 2) == PL_("/\\")
+ || p.substr(0, 2) == PL_("//")
+ ))
+ { // UNC
+ mpt::RawPathString::size_type first_slash = p.substr(2).find_first_of(PL_("\\/"));
+ if(first_slash != mpt::RawPathString::npos)
+ {
+ mpt::RawPathString::size_type second_slash = p.substr(2 + first_slash + 1).find_first_of(PL_("\\/"));
+ if(second_slash != mpt::RawPathString::npos)
+ {
+ if(drive) *drive = mpt::PathString::FromNative(p.substr(0, 2 + first_slash + 1 + second_slash));
+ p = p.substr(2 + first_slash + 1 + second_slash);
+ } else
+ {
+ if(drive) *drive = mpt::PathString::FromNative(p);
+ p = mpt::RawPathString();
+ }
+ } else
+ {
+ if(drive) *drive = mpt::PathString::FromNative(p);
+ p = mpt::RawPathString();
+ }
+ } else
+ { // local
+ if(p.length() >= 2 && (p[1] == PC_(':')))
+ {
+ if(drive) *drive = mpt::PathString::FromNative(p.substr(0, 2));
+ p = p.substr(2);
+ } else
+ {
+ if(drive) *drive = mpt::PathString();
+ }
+ }
+ mpt::RawPathString::size_type last_slash = p.find_last_of(PL_("\\/"));
+ if(last_slash != mpt::RawPathString::npos)
+ {
+ if(dir) *dir = mpt::PathString::FromNative(p.substr(0, last_slash + 1));
+ p = p.substr(last_slash + 1);
+ } else
+ {
+ if(dir) *dir = mpt::PathString();
+ }
+ mpt::RawPathString::size_type last_dot = p.find_last_of(PL_("."));
+ if(last_dot == mpt::RawPathString::npos)
+ {
+ if(fname) *fname = mpt::PathString::FromNative(p);
+ if(ext) *ext = mpt::PathString();
+ } else if(last_dot == 0)
+ {
+ if(fname) *fname = mpt::PathString::FromNative(p);
+ if(ext) *ext = mpt::PathString();
+ } else if(p == PL_(".") || p == PL_(".."))
+ {
+ if(fname) *fname = mpt::PathString::FromNative(p);
+ if(ext) *ext = mpt::PathString();
+ } else
+ {
+ if(fname) *fname = mpt::PathString::FromNative(p.substr(0, last_dot));
+ if(ext) *ext = mpt::PathString::FromNative(p.substr(last_dot));
+ }
+
+}
+
+PathString PathString::GetDrive() const
+{
+ PathString drive;
+ SplitPath(&drive, nullptr, nullptr, nullptr);
+ return drive;
+}
+PathString PathString::GetDir() const
+{
+ PathString dir;
+ SplitPath(nullptr, &dir, nullptr, nullptr);
+ return dir;
+}
+PathString PathString::GetPath() const
+{
+ PathString drive, dir;
+ SplitPath(&drive, &dir, nullptr, nullptr);
+ return drive + dir;
+}
+PathString PathString::GetFileName() const
+{
+ PathString fname;
+ SplitPath(nullptr, nullptr, &fname, nullptr);
+ return fname;
+}
+PathString PathString::GetFileExt() const
+{
+ PathString ext;
+ SplitPath(nullptr, nullptr, nullptr, &ext);
+ return ext;
+}
+PathString PathString::GetFullFileName() const
+{
+ PathString name, ext;
+ SplitPath(nullptr, nullptr, &name, &ext);
+ return name + ext;
+}
+
+
+bool PathString::IsDirectory() const
+{
+ // Using PathIsDirectoryW here instead would increase libopenmpt dependencies by shlwapi.dll.
+ // GetFileAttributesW also does the job just fine.
+ #if MPT_OS_WINDOWS_WINRT
+ WIN32_FILE_ATTRIBUTE_DATA data = {};
+ if(::GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &data) == 0)
+ {
+ return false;
+ }
+ DWORD dwAttrib = data.dwFileAttributes;
+ #else // !MPT_OS_WINDOWS_WINRT
+ DWORD dwAttrib = ::GetFileAttributes(path.c_str());
+ #endif // MPT_OS_WINDOWS_WINRT
+ return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
+}
+
+bool PathString::IsFile() const
+{
+ #if MPT_OS_WINDOWS_WINRT
+ WIN32_FILE_ATTRIBUTE_DATA data = {};
+ if (::GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &data) == 0)
+ {
+ return false;
+ }
+ DWORD dwAttrib = data.dwFileAttributes;
+ #else // !MPT_OS_WINDOWS_WINRT
+ DWORD dwAttrib = ::GetFileAttributes(path.c_str());
+ #endif // MPT_OS_WINDOWS_WINRT
+ return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
+}
+
+#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+
+
+#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+
+bool PathString::FileOrDirectoryExists() const
+{
+ return ::PathFileExists(path.c_str()) != FALSE;
+}
+
+#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+
+
+#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+
+PathString PathString::ReplaceExt(const mpt::PathString &newExt) const
+{
+ return GetDrive() + GetDir() + GetFileName() + newExt;
+}
+
+
+PathString PathString::SanitizeComponent() const
+{
+ PathString result = *this;
+ SanitizeFilename(result);
+ return result;
+}
+
+
+// Convert an absolute path to a path that's relative to "&relativeTo".
+PathString PathString::AbsolutePathToRelative(const PathString &relativeTo) const
+{
+ mpt::PathString result = *this;
+ if(path.empty())
+ {
+ return result;
+ }
+ if(!_tcsncicmp(relativeTo.AsNative().c_str(), AsNative().c_str(), relativeTo.AsNative().length()))
+ {
+ // Path is OpenMPT's directory or a sub directory ("C:\OpenMPT\Somepath" => ".\Somepath")
+ result = P_(".\\"); // ".\"
+ result += mpt::PathString::FromNative(AsNative().substr(relativeTo.AsNative().length()));
+ } else if(!_tcsncicmp(relativeTo.AsNative().c_str(), AsNative().c_str(), 2))
+ {
+ // Path is on the same drive as OpenMPT ("C:\Somepath" => "\Somepath")
+ result = mpt::PathString::FromNative(AsNative().substr(2));
+ }
+ return result;
+}
+
+
+// Convert a path that is relative to "&relativeTo" to an absolute path.
+PathString PathString::RelativePathToAbsolute(const PathString &relativeTo) const
+{
+ mpt::PathString result = *this;
+ if(path.empty())
+ {
+ return result;
+ }
+ if(path.length() >= 2 && path[0] == PC_('\\') && path[1] != PC_('\\'))
+ {
+ // Path is on the same drive as OpenMPT ("\Somepath\" => "C:\Somepath\"), but ignore network paths starting with "\\"
+ result = mpt::PathString::FromNative(relativeTo.AsNative().substr(0, 2));
+ result += mpt::PathString(path);
+ } else if(path.length() >= 2 && path.substr(0, 2) == PL_(".\\"))
+ {
+ // Path is OpenMPT's directory or a sub directory (".\Somepath\" => "C:\OpenMPT\Somepath\")
+ result = relativeTo; // "C:\OpenMPT\"
+ result += mpt::PathString::FromNative(AsNative().substr(2));
+ }
+ return result;
+}
+
+
+#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+
+
+bool PathString::IsPathSeparator(RawPathString::value_type c)
+{
+#if MPT_OS_WINDOWS
+ return (c == PC_('\\')) || (c == PC_('/'));
+#else
+ return c == PC_('/');
+#endif
+}
+
+RawPathString::value_type PathString::GetDefaultPathSeparator()
+{
+#if MPT_OS_WINDOWS
+ return PC_('\\');
+#else
+ return PC_('/');
+#endif
+}
+
+
+} // namespace mpt
+
+
+namespace mpt
+{
+
+bool PathIsAbsolute(const mpt::PathString &path) {
+ mpt::RawPathString rawpath = path.AsNative();
+#if MPT_OS_WINDOWS
+ if(rawpath.substr(0, 8) == PL_("\\\\?\\UNC\\"))
+ {
+ return true;
+ }
+ if(rawpath.substr(0, 4) == PL_("\\\\?\\"))
+ {
+ return true;
+ }
+ if(rawpath.substr(0, 2) == PL_("\\\\"))
+ {
+ return true; // UNC
+ }
+ if(rawpath.substr(0, 2) == PL_("//"))
+ {
+ return true; // UNC
+ }
+ return (rawpath.length()) >= 3 && (rawpath[1] == ':') && mpt::PathString::IsPathSeparator(rawpath[2]);
+#else
+ return (rawpath.length() >= 1) && mpt::PathString::IsPathSeparator(rawpath[0]);
+#endif
+}
+
+
+#if MPT_OS_WINDOWS
+
+#if !(MPT_OS_WINDOWS_WINRT && (_WIN32_WINNT < 0x0a00))
+
+mpt::PathString GetAbsolutePath(const mpt::PathString &path)
+{
+ DWORD size = GetFullPathName(path.AsNative().c_str(), 0, nullptr, nullptr);
+ if(size == 0)
+ {
+ return path;
+ }
+ std::vector<TCHAR> fullPathName(size, TEXT('\0'));
+ if(GetFullPathName(path.AsNative().c_str(), size, fullPathName.data(), nullptr) == 0)
+ {
+ return path;
+ }
+ return mpt::PathString::FromNative(fullPathName.data());
+}
+
+#endif
+
+#ifdef MODPLUG_TRACKER
+
+bool DeleteWholeDirectoryTree(mpt::PathString path)
+{
+ if(path.AsNative().empty())
+ {
+ return false;
+ }
+ if(PathIsRelative(path.AsNative().c_str()) == TRUE)
+ {
+ return false;
+ }
+ if(!path.FileOrDirectoryExists())
+ {
+ return true;
+ }
+ if(!path.IsDirectory())
+ {
+ return false;
+ }
+ path.EnsureTrailingSlash();
+ HANDLE hFind = NULL;
+ WIN32_FIND_DATA wfd = {};
+ hFind = FindFirstFile((path + P_("*.*")).AsNative().c_str(), &wfd);
+ if(hFind != NULL && hFind != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ mpt::PathString filename = mpt::PathString::FromNative(wfd.cFileName);
+ if(filename != P_(".") && filename != P_(".."))
+ {
+ filename = path + filename;
+ if(filename.IsDirectory())
+ {
+ if(!DeleteWholeDirectoryTree(filename))
+ {
+ return false;
+ }
+ } else if(filename.IsFile())
+ {
+ if(DeleteFile(filename.AsNative().c_str()) == 0)
+ {
+ return false;
+ }
+ }
+ }
+ } while(FindNextFile(hFind, &wfd));
+ FindClose(hFind);
+ }
+ if(RemoveDirectory(path.AsNative().c_str()) == 0)
+ {
+ return false;
+ }
+ return true;
+}
+
+#endif // MODPLUG_TRACKER
+
+#endif // MPT_OS_WINDOWS
+
+
+
+#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+
+mpt::PathString GetExecutablePath()
+{
+ std::vector<TCHAR> exeFileName(MAX_PATH);
+ while(GetModuleFileName(0, exeFileName.data(), mpt::saturate_cast<DWORD>(exeFileName.size())) >= exeFileName.size())
+ {
+ if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ return mpt::PathString();
+ }
+ exeFileName.resize(exeFileName.size() * 2);
+ }
+ return mpt::GetAbsolutePath(mpt::PathString::FromNative(exeFileName.data()).GetPath());
+}
+
+
+#if !MPT_OS_WINDOWS_WINRT
+
+mpt::PathString GetSystemPath()
+{
+ DWORD size = GetSystemDirectory(nullptr, 0);
+ std::vector<TCHAR> path(size + 1);
+ if(!GetSystemDirectory(path.data(), size + 1))
+ {
+ return mpt::PathString();
+ }
+ return mpt::PathString::FromNative(path.data()) + P_("\\");
+}
+
+#endif // !MPT_OS_WINDOWS_WINRT
+
+#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+
+
+
+#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
+
+mpt::PathString GetTempDirectory()
+{
+ DWORD size = GetTempPath(0, nullptr);
+ if(size)
+ {
+ std::vector<TCHAR> tempPath(size + 1);
+ if(GetTempPath(size + 1, tempPath.data()))
+ {
+ return mpt::PathString::FromNative(tempPath.data());
+ }
+ }
+ // use exe directory as fallback
+ return mpt::GetExecutablePath();
+}
+
+mpt::PathString CreateTempFileName(const mpt::PathString &fileNamePrefix, const mpt::PathString &fileNameExtension)
+{
+ mpt::PathString filename = mpt::GetTempDirectory();
+ filename += (!fileNamePrefix.empty() ? fileNamePrefix + P_("_") : mpt::PathString());
+ filename += mpt::PathString::FromUnicode(mpt::UUID::GenerateLocalUseOnly(mpt::global_prng()).ToUString());
+ filename += (!fileNameExtension.empty() ? P_(".") + fileNameExtension : mpt::PathString());
+ return filename;
+}
+
+TempFileGuard::TempFileGuard(const mpt::PathString &filename)
+ : filename(filename)
+{
+ return;
+}
+
+mpt::PathString TempFileGuard::GetFilename() const
+{
+ return filename;
+}
+
+TempFileGuard::~TempFileGuard()
+{
+ if(!filename.empty())
+ {
+ DeleteFile(filename.AsNative().c_str());
+ }
+}
+
+
+TempDirGuard::TempDirGuard(const mpt::PathString &dirname_)
+ : dirname(dirname_.WithTrailingSlash())
+{
+ if(dirname.empty())
+ {
+ return;
+ }
+ if(::CreateDirectory(dirname.AsNative().c_str(), NULL) == 0)
+ { // fail
+ dirname = mpt::PathString();
+ }
+}
+
+mpt::PathString TempDirGuard::GetDirname() const
+{
+ return dirname;
+}
+
+TempDirGuard::~TempDirGuard()
+{
+ if(!dirname.empty())
+ {
+ DeleteWholeDirectoryTree(dirname);
+ }
+}
+
+#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
+
+} // namespace mpt
+
+
+
+#if defined(MODPLUG_TRACKER)
+
+static inline char SanitizeFilenameChar(char c)
+{
+ if( c == '\\' ||
+ c == '\"' ||
+ c == '/' ||
+ c == ':' ||
+ c == '?' ||
+ c == '<' ||
+ c == '>' ||
+ c == '|' ||
+ c == '*')
+ {
+ c = '_';
+ }
+ return c;
+}
+
+static inline wchar_t SanitizeFilenameChar(wchar_t c)
+{
+ if( c == L'\\' ||
+ c == L'\"' ||
+ c == L'/' ||
+ c == L':' ||
+ c == L'?' ||
+ c == L'<' ||
+ c == L'>' ||
+ c == L'|' ||
+ c == L'*')
+ {
+ c = L'_';
+ }
+ return c;
+}
+
+#if MPT_CXX_AT_LEAST(20)
+static inline char8_t SanitizeFilenameChar(char8_t c)
+{
+ if( c == u8'\\' ||
+ c == u8'\"' ||
+ c == u8'/' ||
+ c == u8':' ||
+ c == u8'?' ||
+ c == u8'<' ||
+ c == u8'>' ||
+ c == u8'|' ||
+ c == u8'*')
+ {
+ c = u8'_';
+ }
+ return c;
+}
+#endif
+
+void SanitizeFilename(mpt::PathString &filename)
+{
+ mpt::RawPathString tmp = filename.AsNative();
+ for(auto &c : tmp)
+ {
+ c = SanitizeFilenameChar(c);
+ }
+ filename = mpt::PathString::FromNative(tmp);
+}
+
+void SanitizeFilename(char *beg, char *end)
+{
+ for(char *it = beg; it != end; ++it)
+ {
+ *it = SanitizeFilenameChar(*it);
+ }
+}
+
+void SanitizeFilename(wchar_t *beg, wchar_t *end)
+{
+ for(wchar_t *it = beg; it != end; ++it)
+ {
+ *it = SanitizeFilenameChar(*it);
+ }
+}
+
+void SanitizeFilename(std::string &str)
+{
+ for(size_t i = 0; i < str.length(); i++)
+ {
+ str[i] = SanitizeFilenameChar(str[i]);
+ }
+}
+
+void SanitizeFilename(std::wstring &str)
+{
+ for(size_t i = 0; i < str.length(); i++)
+ {
+ str[i] = SanitizeFilenameChar(str[i]);
+ }
+}
+
+#if MPT_USTRING_MODE_UTF8
+void SanitizeFilename(mpt::u8string &str)
+{
+ for(size_t i = 0; i < str.length(); i++)
+ {
+ str[i] = SanitizeFilenameChar(str[i]);
+ }
+}
+#endif // MPT_USTRING_MODE_UTF8
+
+#if defined(MPT_WITH_MFC)
+void SanitizeFilename(CString &str)
+{
+ for(int i = 0; i < str.GetLength(); i++)
+ {
+ str.SetAt(i, SanitizeFilenameChar(str.GetAt(i)));
+ }
+}
+#endif // MPT_WITH_MFC
+
+#endif // MODPLUG_TRACKER
+
+
+#if defined(MODPLUG_TRACKER)
+
+
+mpt::PathString FileType::AsFilterString(FlagSet<FileTypeFormat> format) const
+{
+ mpt::PathString filter;
+ if(GetShortName().empty() || GetExtensions().empty())
+ {
+ return filter;
+ }
+ if(!GetDescription().empty())
+ {
+ filter += mpt::PathString::FromUnicode(GetDescription());
+ } else
+ {
+ filter += mpt::PathString::FromUnicode(GetShortName());
+ }
+ const auto extensions = GetExtensions();
+ if(format[FileTypeFormatShowExtensions])
+ {
+ filter += P_(" (");
+ bool first = true;
+ for(const auto &ext : extensions)
+ {
+ if(first)
+ {
+ first = false;
+ } else
+ {
+ filter += P_(",");
+ }
+ filter += P_("*.");
+ filter += ext;
+ }
+ filter += P_(")");
+ }
+ filter += P_("|");
+ {
+ bool first = true;
+ for(const auto &ext : extensions)
+ {
+ if(first)
+ {
+ first = false;
+ } else
+ {
+ filter += P_(";");
+ }
+ filter += P_("*.");
+ filter += ext;
+ }
+ }
+ filter += P_("|");
+ return filter;
+}
+
+
+mpt::PathString FileType::AsFilterOnlyString() const
+{
+ mpt::PathString filter;
+ const auto extensions = GetExtensions();
+ {
+ bool first = true;
+ for(const auto &ext : extensions)
+ {
+ if(first)
+ {
+ first = false;
+ } else
+ {
+ filter += P_(";");
+ }
+ filter += P_("*.");
+ filter += ext;
+ }
+ }
+ return filter;
+}
+
+
+mpt::PathString ToFilterString(const FileType &fileType, FlagSet<FileTypeFormat> format)
+{
+ return fileType.AsFilterString(format);
+}
+
+
+mpt::PathString ToFilterString(const std::vector<FileType> &fileTypes, FlagSet<FileTypeFormat> format)
+{
+ mpt::PathString filter;
+ for(const auto &type : fileTypes)
+ {
+ filter += type.AsFilterString(format);
+ }
+ return filter;
+}
+
+
+mpt::PathString ToFilterOnlyString(const FileType &fileType, bool prependSemicolonWhenNotEmpty)
+{
+ mpt::PathString filter = fileType.AsFilterOnlyString();
+ return filter.empty() ? filter : (prependSemicolonWhenNotEmpty ? P_(";") : P_("")) + filter;
+}
+
+
+mpt::PathString ToFilterOnlyString(const std::vector<FileType> &fileTypes, bool prependSemicolonWhenNotEmpty)
+{
+ mpt::PathString filter;
+ for(const auto &type : fileTypes)
+ {
+ filter += type.AsFilterOnlyString();
+ }
+ return filter.empty() ? filter : (prependSemicolonWhenNotEmpty ? P_(";") : P_("")) + filter;
+}
+
+
+#endif // MODPLUG_TRACKER
+
+
+
+OPENMPT_NAMESPACE_END