diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/common/mptPathString.h | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/mptPathString.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/common/mptPathString.h | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/common/mptPathString.h b/Src/external_dependencies/openmpt-trunk/common/mptPathString.h new file mode 100644 index 00000000..95224c5b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/common/mptPathString.h @@ -0,0 +1,505 @@ +/* + * 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 |