Bundle libOpenMPT as a dynamic framework, which should be safe once again, now that there is only one version to bundle. Also, now it is using the versions of libvorbisfile and libmpg123 that are bundled with the player, instead of compiling minimp3 and stbvorbis. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
505 lines
16 KiB
C++
505 lines
16 KiB
C++
/*
|
|
* mptPathString.h
|
|
* ---------------
|
|
* 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.
|
|
*/
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "openmpt/all/BuildSettings.hpp"
|
|
|
|
#include "mptString.h"
|
|
|
|
#include "mpt/base/namespace.hpp"
|
|
|
|
#include <vector>
|
|
|
|
#include "openmpt/base/FlagSet.hpp"
|
|
|
|
#define MPT_DEPRECATED_PATH
|
|
//#define MPT_DEPRECATED_PATH [[deprecated]]
|
|
|
|
OPENMPT_NAMESPACE_BEGIN
|
|
|
|
namespace mpt
|
|
{
|
|
|
|
#if MPT_OS_WINDOWS
|
|
typedef mpt::winstring RawPathString;
|
|
#else // !MPT_OS_WINDOWS
|
|
typedef std::string RawPathString;
|
|
#endif // if MPT_OS_WINDOWS
|
|
|
|
|
|
|
|
class PathString
|
|
{
|
|
|
|
private:
|
|
|
|
RawPathString path;
|
|
|
|
private:
|
|
|
|
explicit PathString(const RawPathString & path_)
|
|
: path(path_)
|
|
{
|
|
return;
|
|
}
|
|
|
|
public:
|
|
|
|
PathString()
|
|
{
|
|
return;
|
|
}
|
|
PathString(const PathString & other)
|
|
: path(other.path)
|
|
{
|
|
return;
|
|
}
|
|
PathString(PathString && other) noexcept
|
|
: path(std::move(other.path))
|
|
{
|
|
return;
|
|
}
|
|
PathString & assign(const PathString & other)
|
|
{
|
|
path = other.path;
|
|
return *this;
|
|
}
|
|
PathString & assign(PathString && other) noexcept
|
|
{
|
|
path = std::move(other.path);
|
|
return *this;
|
|
}
|
|
PathString & operator = (const PathString & other)
|
|
{
|
|
return assign(other);
|
|
}
|
|
PathString &operator = (PathString && other) noexcept
|
|
{
|
|
return assign(std::move(other));
|
|
}
|
|
PathString & append(const PathString & other)
|
|
{
|
|
path.append(other.path);
|
|
return *this;
|
|
}
|
|
PathString & operator += (const PathString & other)
|
|
{
|
|
return append(other);
|
|
}
|
|
|
|
friend PathString operator + (const PathString & a, const PathString & b)
|
|
{
|
|
return PathString(a).append(b);
|
|
}
|
|
|
|
friend bool operator < (const PathString & a, const PathString & b)
|
|
{
|
|
return a.AsNative() < b.AsNative();
|
|
}
|
|
friend bool operator == (const PathString & a, const PathString & b)
|
|
{
|
|
return a.AsNative() == b.AsNative();
|
|
}
|
|
friend bool operator != (const PathString & a, const PathString & b)
|
|
{
|
|
return a.AsNative() != b.AsNative();
|
|
}
|
|
|
|
bool empty() const { return path.empty(); }
|
|
|
|
std::size_t Length() const { return path.size(); }
|
|
|
|
|
|
|
|
public:
|
|
|
|
#if MPT_OS_WINDOWS
|
|
#if !MPT_OS_WINDOWS_WINRT
|
|
static int CompareNoCase(const PathString & a, const PathString & b);
|
|
#endif // !MPT_OS_WINDOWS_WINRT
|
|
#endif
|
|
|
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
|
|
|
|
void SplitPath(PathString *drive, PathString *dir, PathString *fname, PathString *ext) const;
|
|
// \\?\ prefixes will be removed and \\?\\UNC prefixes converted to canonical \\ form.
|
|
PathString GetDrive() const; // Drive letter + colon, e.g. "C:" or \\server\\share
|
|
PathString GetDir() const; // Directory, e.g. "\OpenMPT\"
|
|
PathString GetPath() const; // Drive + Dir, e.g. "C:\OpenMPT\"
|
|
PathString GetFileName() const; // File name without extension, e.g. "OpenMPT"
|
|
PathString GetFileExt() const; // Extension including dot, e.g. ".exe"
|
|
PathString GetFullFileName() const; // File name + extension, e.g. "OpenMPT.exe"
|
|
|
|
// Verify if this path represents a valid directory on the file system.
|
|
bool IsDirectory() const;
|
|
// Verify if this path exists and is a file on the file system.
|
|
bool IsFile() const;
|
|
|
|
bool FileOrDirectoryExists() const;
|
|
|
|
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
|
|
|
|
static bool IsPathSeparator(RawPathString::value_type c);
|
|
static RawPathString::value_type GetDefaultPathSeparator();
|
|
|
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
|
|
|
|
// Return the same path string with a different (or appended) extension (including "."), e.g. "foo.bar",".txt" -> "foo.txt" or "C:\OpenMPT\foo",".txt" -> "C:\OpenMPT\foo.txt"
|
|
PathString ReplaceExt(const mpt::PathString &newExt) const;
|
|
|
|
// Removes special characters from a filename component and replaces them with a safe replacement character ("_" on windows).
|
|
// Returns the result.
|
|
// Note that this also removes path component separators, so this should only be used on single-component PathString objects.
|
|
PathString SanitizeComponent() const;
|
|
|
|
bool HasTrailingSlash() const
|
|
{
|
|
if(path.empty())
|
|
{
|
|
return false;
|
|
}
|
|
RawPathString::value_type c = path[path.length() - 1];
|
|
return IsPathSeparator(c);
|
|
}
|
|
mpt::PathString &EnsureTrailingSlash()
|
|
{
|
|
if(!path.empty() && !HasTrailingSlash())
|
|
{
|
|
path += GetDefaultPathSeparator();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
mpt::PathString WithoutTrailingSlash() const
|
|
{
|
|
mpt::PathString result = *this;
|
|
while(result.HasTrailingSlash())
|
|
{
|
|
if(result.Length() == 1)
|
|
{
|
|
return result;
|
|
}
|
|
result = mpt::PathString(result.AsNative().substr(0, result.AsNative().length() - 1));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
mpt::PathString WithTrailingSlash() const
|
|
{
|
|
mpt::PathString result = *this;
|
|
result.EnsureTrailingSlash();
|
|
return result;
|
|
}
|
|
|
|
// Relative / absolute paths conversion
|
|
mpt::PathString AbsolutePathToRelative(const mpt::PathString &relativeTo) const;
|
|
mpt::PathString RelativePathToAbsolute(const mpt::PathString &relativeTo) const;
|
|
|
|
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
|
|
|
|
public:
|
|
|
|
#if MPT_OS_WINDOWS
|
|
|
|
#if !(MPT_WSTRING_CONVERT)
|
|
#error "mpt::PathString on Windows depends on MPT_WSTRING_CONVERT)"
|
|
#endif
|
|
// conversions
|
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
MPT_DEPRECATED_PATH std::string ToLocale() const { return mpt::ToCharset(mpt::Charset::Locale, path); }
|
|
#endif
|
|
std::string ToUTF8() const { return mpt::ToCharset(mpt::Charset::UTF8, path); }
|
|
std::wstring ToWide() const { return mpt::ToWide(path); }
|
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(path); }
|
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
MPT_DEPRECATED_PATH static PathString FromLocale(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::Locale, path)); }
|
|
static PathString FromLocaleSilent(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::Locale, path)); }
|
|
#endif
|
|
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToWin(mpt::Charset::UTF8, path)); }
|
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToWin(path)); }
|
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToWin(path)); }
|
|
RawPathString AsNative() const { return path; }
|
|
// Return native string, with possible \\?\ prefix if it exceeds MAX_PATH characters.
|
|
RawPathString AsNativePrefixed() const;
|
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
|
#if defined(MPT_WITH_MFC)
|
|
// CString TCHAR, so this is CHAR or WCHAR, depending on UNICODE
|
|
CString ToCString() const { return mpt::ToCString(path); }
|
|
static PathString FromCString(const CString &path) { return PathString(mpt::ToWin(path)); }
|
|
#endif // MPT_WITH_MFC
|
|
|
|
// Convert a path to its simplified form, i.e. remove ".\" and "..\" entries
|
|
mpt::PathString Simplify() const;
|
|
|
|
#else // !MPT_OS_WINDOWS
|
|
|
|
// conversions
|
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
std::string ToLocale() const { return path; }
|
|
std::string ToUTF8() const { return mpt::ToCharset(mpt::Charset::UTF8, mpt::Charset::Locale, path); }
|
|
#if MPT_WSTRING_CONVERT
|
|
std::wstring ToWide() const { return mpt::ToWide(mpt::Charset::Locale, path); }
|
|
#endif
|
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::Charset::Locale, path); }
|
|
static PathString FromLocale(const std::string &path) { return PathString(path); }
|
|
static PathString FromLocaleSilent(const std::string &path) { return PathString(path); }
|
|
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, mpt::Charset::UTF8, path)); }
|
|
#if MPT_WSTRING_CONVERT
|
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, path)); }
|
|
#endif
|
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::Charset::Locale, path)); }
|
|
RawPathString AsNative() const { return path; }
|
|
RawPathString AsNativePrefixed() const { return path; }
|
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
|
#else // !MPT_ENABLE_CHARSET_LOCALE
|
|
std::string ToUTF8() const { return path; }
|
|
#if MPT_WSTRING_CONVERT
|
|
std::wstring ToWide() const { return mpt::ToWide(mpt::Charset::UTF8, path); }
|
|
#endif
|
|
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::Charset::UTF8, path); }
|
|
static PathString FromUTF8(const std::string &path) { return PathString(path); }
|
|
#if MPT_WSTRING_CONVERT
|
|
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::Charset::UTF8, path)); }
|
|
#endif
|
|
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::Charset::UTF8, path)); }
|
|
RawPathString AsNative() const { return path; }
|
|
RawPathString AsNativePrefixed() const { return path; }
|
|
static PathString FromNative(const RawPathString &path) { return PathString(path); }
|
|
#endif // MPT_ENABLE_CHARSET_LOCALE
|
|
|
|
// Convert a path to its simplified form (currently only implemented on Windows)
|
|
[[deprecated]] mpt::PathString Simplify() const { return PathString(path); }
|
|
|
|
#endif // MPT_OS_WINDOWS
|
|
|
|
};
|
|
|
|
|
|
|
|
#if defined(MPT_ENABLE_CHARSET_LOCALE)
|
|
#if MPT_OS_WINDOWS
|
|
#ifdef UNICODE
|
|
[[deprecated]] inline std::string ToAString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.ToUnicode()); }
|
|
#else
|
|
MPT_DEPRECATED_PATH inline std::string ToAString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.AsNative()); }
|
|
#endif
|
|
#else
|
|
MPT_DEPRECATED_PATH inline std::string ToAString(const mpt::PathString & x) { return mpt::ToCharset(mpt::Charset::Locale, x.ToUnicode()); }
|
|
#endif
|
|
#endif
|
|
inline mpt::ustring ToUString(const mpt::PathString & x) { return x.ToUnicode(); }
|
|
#if MPT_WSTRING_FORMAT
|
|
inline std::wstring ToWString(const mpt::PathString & x) { return x.ToWide(); }
|
|
#endif
|
|
|
|
} // namespace mpt
|
|
|
|
#if MPT_OS_WINDOWS
|
|
|
|
#ifdef UNICODE
|
|
#define MPT_PATHSTRING_LITERAL(x) ( L ## x )
|
|
#define MPT_PATHSTRING(x) mpt::PathString::FromNative( L ## x )
|
|
#else
|
|
#define MPT_PATHSTRING_LITERAL(x) ( x )
|
|
#define MPT_PATHSTRING(x) mpt::PathString::FromNative( x )
|
|
#endif
|
|
|
|
#else // !MPT_OS_WINDOWS
|
|
|
|
#define MPT_PATHSTRING_LITERAL(x) ( x )
|
|
#define MPT_PATHSTRING(x) mpt::PathString::FromNative( x )
|
|
|
|
#endif // MPT_OS_WINDOWS
|
|
|
|
#define PC_(x) MPT_PATHSTRING_LITERAL(x)
|
|
#define PL_(x) MPT_PATHSTRING_LITERAL(x)
|
|
#define P_(x) MPT_PATHSTRING(x)
|
|
|
|
namespace mpt
|
|
{
|
|
|
|
|
|
bool PathIsAbsolute(const mpt::PathString &path);
|
|
|
|
#if MPT_OS_WINDOWS
|
|
|
|
#if !(MPT_OS_WINDOWS_WINRT && (_WIN32_WINNT < 0x0a00))
|
|
|
|
// Returns the absolute path for a potentially relative path and removes ".." or "." components. (same as GetFullPathNameW)
|
|
mpt::PathString GetAbsolutePath(const mpt::PathString &path);
|
|
|
|
#endif
|
|
|
|
#ifdef MODPLUG_TRACKER
|
|
|
|
// Deletes a complete directory tree. Handle with EXTREME care.
|
|
// Returns false if any file could not be removed and aborts as soon as it
|
|
// encounters any error. path must be absolute.
|
|
bool DeleteWholeDirectoryTree(mpt::PathString path);
|
|
|
|
#endif // MODPLUG_TRACKER
|
|
|
|
#endif // MPT_OS_WINDOWS
|
|
|
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
|
|
|
|
// Returns the application executable path or an empty string (if unknown), e.g. "C:\mptrack\"
|
|
mpt::PathString GetExecutablePath();
|
|
|
|
#if !MPT_OS_WINDOWS_WINRT
|
|
// Returns the system directory path, e.g. "C:\Windows\System32\"
|
|
mpt::PathString GetSystemPath();
|
|
#endif // !MPT_OS_WINDOWS_WINRT
|
|
|
|
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
|
|
|
|
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
|
|
|
|
// Returns temporary directory (with trailing backslash added) (e.g. "C:\TEMP\")
|
|
mpt::PathString GetTempDirectory();
|
|
|
|
// Returns a new unique absolute path.
|
|
mpt::PathString CreateTempFileName(const mpt::PathString &fileNamePrefix = mpt::PathString(), const mpt::PathString &fileNameExtension = P_("tmp"));
|
|
|
|
|
|
|
|
// Scoped temporary file guard. Deletes the file when going out of scope.
|
|
// The file itself is not created automatically.
|
|
class TempFileGuard
|
|
{
|
|
private:
|
|
const mpt::PathString filename;
|
|
public:
|
|
TempFileGuard(const mpt::PathString &filename = CreateTempFileName());
|
|
mpt::PathString GetFilename() const;
|
|
~TempFileGuard();
|
|
};
|
|
|
|
|
|
// Scoped temporary directory guard. Deletes the directory when going out of scope.
|
|
// The directory itself is created automatically.
|
|
class TempDirGuard
|
|
{
|
|
private:
|
|
mpt::PathString dirname;
|
|
public:
|
|
TempDirGuard(const mpt::PathString &dirname_ = CreateTempFileName());
|
|
mpt::PathString GetDirname() const;
|
|
~TempDirGuard();
|
|
};
|
|
|
|
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
|
|
|
|
} // namespace mpt
|
|
|
|
|
|
|
|
#if defined(MODPLUG_TRACKER)
|
|
|
|
// Sanitize a filename (remove special chars)
|
|
void SanitizeFilename(mpt::PathString &filename);
|
|
|
|
void SanitizeFilename(char *beg, char *end);
|
|
void SanitizeFilename(wchar_t *beg, wchar_t *end);
|
|
|
|
void SanitizeFilename(std::string &str);
|
|
void SanitizeFilename(std::wstring &str);
|
|
#if MPT_USTRING_MODE_UTF8
|
|
void SanitizeFilename(mpt::u8string &str);
|
|
#endif // MPT_USTRING_MODE_UTF8
|
|
|
|
template <std::size_t size>
|
|
void SanitizeFilename(char (&buffer)[size])
|
|
{
|
|
static_assert(size > 0);
|
|
SanitizeFilename(buffer, buffer + size);
|
|
}
|
|
|
|
template <std::size_t size>
|
|
void SanitizeFilename(wchar_t (&buffer)[size])
|
|
{
|
|
static_assert(size > 0);
|
|
SanitizeFilename(buffer, buffer + size);
|
|
}
|
|
|
|
#if defined(MPT_WITH_MFC)
|
|
void SanitizeFilename(CString &str);
|
|
#endif // MPT_WITH_MFC
|
|
|
|
#endif // MODPLUG_TRACKER
|
|
|
|
|
|
#if defined(MODPLUG_TRACKER)
|
|
|
|
enum FileTypeFormat
|
|
{
|
|
FileTypeFormatNone = 0 , // do not show extensions after description, i.e. "Foo Files"
|
|
FileTypeFormatShowExtensions = 1<<0, // show extensions after descripten, i.e. "Foo Files (*.foo,*.bar)"
|
|
};
|
|
MPT_DECLARE_ENUM(FileTypeFormat)
|
|
|
|
class FileType
|
|
{
|
|
private:
|
|
mpt::ustring m_ShortName; // "flac", "mod" (lowercase)
|
|
mpt::ustring m_Description; // "FastTracker 2 Module"
|
|
std::vector<std::string> m_MimeTypes; // "audio/ogg" (in ASCII)
|
|
std::vector<mpt::PathString> m_Extensions; // "mod", "xm" (lowercase)
|
|
std::vector<mpt::PathString> m_Prefixes; // "mod" for "mod.*"
|
|
public:
|
|
FileType() { }
|
|
FileType(const std::vector<FileType> &group)
|
|
{
|
|
for(const auto &type : group)
|
|
{
|
|
mpt::append(m_MimeTypes, type.m_MimeTypes);
|
|
mpt::append(m_Extensions, type.m_Extensions);
|
|
mpt::append(m_Prefixes, type.m_Prefixes);
|
|
}
|
|
}
|
|
static FileType Any()
|
|
{
|
|
return FileType().ShortName(U_("*")).Description(U_("All Files")).AddExtension(P_("*"));
|
|
}
|
|
public:
|
|
FileType& ShortName(const mpt::ustring &shortName) { m_ShortName = shortName; return *this; }
|
|
FileType& Description(const mpt::ustring &description) { m_Description = description; return *this; }
|
|
FileType& MimeTypes(const std::vector<std::string> &mimeTypes) { m_MimeTypes = mimeTypes; return *this; }
|
|
FileType& Extensions(const std::vector<mpt::PathString> &extensions) { m_Extensions = extensions; return *this; }
|
|
FileType& Prefixes(const std::vector<mpt::PathString> &prefixes) { m_Prefixes = prefixes; return *this; }
|
|
FileType& AddMimeType(const std::string &mimeType) { m_MimeTypes.push_back(mimeType); return *this; }
|
|
FileType& AddExtension(const mpt::PathString &extension) { m_Extensions.push_back(extension); return *this; }
|
|
FileType& AddPrefix(const mpt::PathString &prefix) { m_Prefixes.push_back(prefix); return *this; }
|
|
public:
|
|
mpt::ustring GetShortName() const { return m_ShortName; }
|
|
mpt::ustring GetDescription() const { return m_Description; }
|
|
std::vector<std::string> GetMimeTypes() const { return m_MimeTypes; }
|
|
std::vector<mpt::PathString> GetExtensions() const { return m_Extensions; }
|
|
std::vector<mpt::PathString> GetPrefixes() const { return m_Prefixes; }
|
|
public:
|
|
mpt::PathString AsFilterString(FlagSet<FileTypeFormat> format = FileTypeFormatNone) const;
|
|
mpt::PathString AsFilterOnlyString() const;
|
|
}; // class FileType
|
|
|
|
|
|
// "Ogg Vorbis|*.ogg;*.oga|" // FileTypeFormatNone
|
|
// "Ogg Vorbis (*.ogg,*.oga)|*.ogg;*.oga|" // FileTypeFormatShowExtensions
|
|
mpt::PathString ToFilterString(const FileType &fileType, FlagSet<FileTypeFormat> format = FileTypeFormatNone);
|
|
mpt::PathString ToFilterString(const std::vector<FileType> &fileTypes, FlagSet<FileTypeFormat> format = FileTypeFormatNone);
|
|
|
|
// "*.ogg;*.oga" / ";*.ogg;*.oga"
|
|
mpt::PathString ToFilterOnlyString(const FileType &fileType, bool prependSemicolonWhenNotEmpty = false);
|
|
mpt::PathString ToFilterOnlyString(const std::vector<FileType> &fileTypes, bool prependSemicolonWhenNotEmpty = false);
|
|
|
|
#endif // MODPLUG_TRACKER
|
|
|
|
|
|
OPENMPT_NAMESPACE_END
|