#pragma once
#include "BuildSettings.h"
#include <vector>
#include "FlagSet.h"
OPENMPT_NAMESPACE_BEGIN
#define MPT_DEPRECATED_PATH
namespace mpt
{
#if MPT_OS_WINDOWS
typedef mpt::winstring RawPathString;
#else
typedef std::string RawPathString;
#endif
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 & assign(const PathString & other)
{
path = other.path;
return *this;
}
PathString & operator = (const PathString & other)
{
return assign(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 #endif
#if MPT_OS_WINDOWS && (defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE))
void SplitPath(PathString *drive, PathString *dir, PathString *fname, PathString *ext) const;
PathString GetDrive() const; PathString GetDir() const; PathString GetPath() const; PathString GetFileName() const; PathString GetFileExt() const; PathString GetFullFileName() const;
bool IsDirectory() const;
bool IsFile() const;
#endif
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
bool FileOrDirectoryExists() const;
#endif
static bool IsPathSeparator(RawPathString::value_type c);
static RawPathString::value_type GetDefaultPathSeparator();
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
PathString ReplaceExt(const mpt::PathString &newExt) const;
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;
}
mpt::PathString AbsolutePathToRelative(const mpt::PathString &relativeTo) const;
mpt::PathString RelativePathToAbsolute(const mpt::PathString &relativeTo) const;
#endif
public:
#if MPT_OS_WINDOWS
#if !(MPT_WSTRING_CONVERT)
#error "mpt::PathString on Windows depends on MPT_WSTRING_CONVERT)"
#endif
#if defined(MPT_ENABLE_CHARSET_LOCALE)
MPT_DEPRECATED_PATH std::string ToLocale() const { return mpt::ToCharset(mpt::CharsetLocale, path); }
#endif
std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, 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::CharsetLocale, path)); }
static PathString FromLocaleSilent(const std::string &path) { return PathString(mpt::ToWin(mpt::CharsetLocale, path)); }
#endif
static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToWin(mpt::CharsetUTF8, 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; }
RawPathString AsNativePrefixed() const;
static PathString FromNative(const RawPathString &path) { return PathString(path); }
#if defined(_MFC_VER)
CString ToCString() const { return mpt::ToCString(path); }
static PathString FromCString(const CString &path) { return PathString(mpt::ToWin(path)); }
#endif
mpt::PathString Simplify() const;
#else
#if defined(MPT_ENABLE_CHARSET_LOCALE)
std::string ToLocale() const { return path; }
std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetLocale, path); }
#if MPT_WSTRING_CONVERT
std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetLocale, path); }
#endif
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::CharsetLocale, 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::CharsetLocale, mpt::CharsetUTF8, path)); }
#if MPT_WSTRING_CONVERT
static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, path)); }
#endif
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, path)); }
RawPathString AsNative() const { return path; }
RawPathString AsNativePrefixed() const { return path; }
static PathString FromNative(const RawPathString &path) { return PathString(path); }
#else
std::string ToUTF8() const { return path; }
#if MPT_WSTRING_CONVERT
std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetUTF8, path); }
#endif
mpt::ustring ToUnicode() const { return mpt::ToUnicode(mpt::CharsetUTF8, 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::CharsetUTF8, path)); }
#endif
static PathString FromUnicode(const mpt::ustring &path) { return PathString(mpt::ToCharset(mpt::CharsetUTF8, path)); }
RawPathString AsNative() const { return path; }
RawPathString AsNativePrefixed() const { return path; }
static PathString FromNative(const RawPathString &path) { return PathString(path); }
#endif
MPT_DEPRECATED mpt::PathString Simplify() const { return PathString(path); }
#endif
};
#if defined(MPT_ENABLE_CHARSET_LOCALE)
#if MPT_OS_WINDOWS
#ifdef UNICODE
MPT_DEPRECATED static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.ToUnicode()); }
#else
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.AsNative()); }
#endif
#else
MPT_DEPRECATED_PATH static inline std::string ToString(const mpt::PathString & x) { return mpt::ToCharset(mpt::CharsetLocale, x.ToUnicode()); }
#endif
#endif
static inline mpt::ustring ToUString(const mpt::PathString & x) { return x.ToUnicode(); }
#if MPT_WSTRING_FORMAT
static inline std::wstring ToWString(const mpt::PathString & x) { return x.ToWide(); }
#endif
}
#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
#define MPT_PATHSTRING_LITERAL(x) ( x )
#define MPT_PATHSTRING(x) mpt::PathString::FromNative( x )
#endif
#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
mpt::PathString GetAbsolutePath(const mpt::PathString &path);
#ifdef MODPLUG_TRACKER
bool DeleteWholeDirectoryTree(mpt::PathString path);
#endif
#endif
#if MPT_OS_WINDOWS
#if defined(MPT_ENABLE_DYNBIND) || defined(MPT_ENABLE_TEMPFILE)
mpt::PathString GetAppPath();
#endif
#if defined(MPT_ENABLE_DYNBIND)
#if !MPT_OS_WINDOWS_WINRT
mpt::PathString GetSystemPath();
#endif
#endif
#endif
#if defined(MPT_ENABLE_TEMPFILE)
#if MPT_OS_WINDOWS
mpt::PathString GetTempDirectory();
mpt::PathString CreateTempFileName(const mpt::PathString &fileNamePrefix = mpt::PathString(), const mpt::PathString &fileNameExtension = P_("tmp"));
class TempFileGuard
{
private:
const mpt::PathString filename;
public:
TempFileGuard(const mpt::PathString &filename = CreateTempFileName());
mpt::PathString GetFilename() const;
~TempFileGuard();
};
#ifdef MODPLUG_TRACKER
class TempDirGuard
{
private:
mpt::PathString dirname;
public:
TempDirGuard(const mpt::PathString &dirname_ = CreateTempFileName());
mpt::PathString GetDirname() const;
~TempDirGuard();
};
#endif
#endif #endif
}
#if defined(MODPLUG_TRACKER)
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
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(_MFC_VER)
void SanitizeFilename(CString &str);
#endif
#endif
#if defined(MODPLUG_TRACKER)
enum FileTypeFormat
{
FileTypeFormatNone = 0 , FileTypeFormatShowExtensions = 1<<0, };
MPT_DECLARE_ENUM(FileTypeFormat)
class FileType
{
private:
mpt::ustring m_ShortName; mpt::ustring m_Description; std::vector<std::string> m_MimeTypes; std::vector<mpt::PathString> m_Extensions; std::vector<mpt::PathString> m_Prefixes; public:
FileType() { }
FileType(const std::vector<FileType> &group)
{
for(const auto &type : group)
{
m_MimeTypes.insert(m_MimeTypes.end(), type.m_MimeTypes.begin(), type.m_MimeTypes.end());
m_Extensions.insert(m_Extensions.end(), type.m_Extensions.begin(), type.m_Extensions.end());
m_Prefixes.insert(m_Prefixes.end(), type.m_Prefixes.begin(), type.m_Prefixes.end());
}
}
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;
};
mpt::PathString ToFilterString(const FileType &fileType, FlagSet<FileTypeFormat> format = FileTypeFormatNone);
mpt::PathString ToFilterString(const std::vector<FileType> &fileTypes, FlagSet<FileTypeFormat> format = FileTypeFormatNone);
mpt::PathString ToFilterOnlyString(const FileType &fileType, bool prependSemicolonWhenNotEmpty = false);
mpt::PathString ToFilterOnlyString(const std::vector<FileType> &fileTypes, bool prependSemicolonWhenNotEmpty = false);
#endif
OPENMPT_NAMESPACE_END