123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- /*
- * 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
|