mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-14 19:57:17 +01:00
1841 lines
54 KiB
C++
1841 lines
54 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "Library/System/Path.hpp"
|
|
#include "Library/System/Environment.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <cctype>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <limits>
|
|
#include <utility>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
#include <windows.h>
|
|
#else
|
|
#include <linux/limits.h>
|
|
#include <unistd.h>
|
|
#endif // SQMOD_OS_WINDOWS
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
// Maximum path size in characters
|
|
#define SQMOD_MAX_PATH (sizeof(TCHAR) * MAX_PATH)
|
|
// Character to be used when working with path
|
|
typedef TCHAR PChar;
|
|
#else
|
|
// Maximum path size in characters
|
|
#define SQMOD_MAX_PATH (PATH_MAX)
|
|
// Character to be used when working with path
|
|
typedef CharT PChar;
|
|
#endif // SQMOD_OS_WINDOWS
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SQMODE_DECL_TYPENAME(Typename, _SC("SqSysPath"))
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Buffer GetRealFilePath(CSStr path)
|
|
{
|
|
// Make sure the specified path is valid
|
|
if (!path || *path == '\0')
|
|
{
|
|
STHROWF("Cannot obtain real path of empty or invalid path");
|
|
}
|
|
// Allocate a buffer large enough to hold a full path
|
|
Buffer b(SQMOD_MAX_PATH);
|
|
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
// Attempt to obtain the full path to the file
|
|
DWORD ret = ::GetFullPathName(path, b.Size< PChar >(), b.Get< PChar >(), nullptr);
|
|
// Should we allocate a bigger buffer?
|
|
if (ret > b.Size< PChar >())
|
|
{
|
|
// Grab a bigger buffer
|
|
b.Adjust(ret);
|
|
// Grab the path again
|
|
ret = GetFullPathName(path, b.Size< PChar >(), b.Get< PChar >(), nullptr);
|
|
}
|
|
// Did we fail to obtain a path?
|
|
if (ret == 0 && ::GetLastError() != 0)
|
|
{
|
|
STHROWLASTF("Cannot obtain real path of (%s)", path);
|
|
}
|
|
// Adjust the buffer cursor
|
|
b.Move(ret);
|
|
#else
|
|
// Attempt to obtain the full path to the file
|
|
if (!realpath(path, b.Data()))
|
|
{
|
|
STHROWLASTF("Cannot obtain real path of (%s)", path);
|
|
}
|
|
// Adjust the buffer cursor
|
|
b.Move(std::strlen(b.Data()));
|
|
#endif // SQMOD_OS_WINDOWS
|
|
|
|
// Return ownership of the buffer
|
|
return std::move(b);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath()
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(bool absolute)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(absolute)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(CSStr path)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(CSStr path, Int32 style)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, static_cast< Style >(style));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(CSStr path, Style style)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, style);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const Buffer & path, Int32 size)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, Style::Guess, size);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const Buffer & path, Style style, Int32 size)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, style, size);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const String & path)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, Style::Guess);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const String & path, Style style)
|
|
: m_Dirs()
|
|
, m_Name()
|
|
, m_Drive(0)
|
|
, m_Absolute(false)
|
|
{
|
|
Assign(path, style);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const SysPath & parent, CSStr name)
|
|
: m_Dirs(parent.m_Dirs)
|
|
, m_Name(name ? name : "")
|
|
, m_Drive(parent.m_Drive)
|
|
, m_Absolute(parent.m_Absolute)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const SysPath & parent, const String & name)
|
|
: m_Dirs(parent.m_Dirs)
|
|
, m_Name(name)
|
|
, m_Drive(parent.m_Drive)
|
|
, m_Absolute(parent.m_Absolute)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const SysPath & parent, const SysPath & relative)
|
|
: m_Dirs(parent.m_Dirs)
|
|
, m_Name(parent.m_Name)
|
|
, m_Drive(parent.m_Drive)
|
|
, m_Absolute(parent.m_Absolute)
|
|
{
|
|
// Resolve the specified path
|
|
Resolve(relative);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(const SysPath & o)
|
|
: m_Dirs(o.m_Dirs)
|
|
, m_Name(o.m_Name)
|
|
, m_Drive(o.m_Drive)
|
|
, m_Absolute(o.m_Absolute)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::SysPath(SysPath && o)
|
|
: m_Dirs(std::move(o.m_Dirs))
|
|
, m_Name(std::move(o.m_Name))
|
|
, m_Drive(o.m_Drive)
|
|
, m_Absolute(o.m_Absolute)
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::~SysPath()
|
|
{
|
|
/* ... */
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::operator = (const SysPath & o)
|
|
{
|
|
// Prevent self assignment
|
|
if (this != &o)
|
|
{
|
|
m_Dirs = o.m_Dirs;
|
|
m_Name = o.m_Name;
|
|
m_Drive = o.m_Drive;
|
|
m_Absolute = o.m_Absolute;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::operator = (SysPath && o)
|
|
{
|
|
// Prevent self assignment
|
|
if (this != &o)
|
|
{
|
|
m_Dirs = std::move(o.m_Dirs);
|
|
m_Name = std::move(o.m_Name);
|
|
m_Drive = o.m_Drive;
|
|
m_Absolute = o.m_Absolute;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::operator = (CSStr path)
|
|
{
|
|
Assign(path);
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::operator = (const String & path)
|
|
{
|
|
Assign(path);
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool SysPath::operator == (const SysPath & o) const
|
|
{
|
|
return (m_Drive == o.m_Drive) && (m_Absolute == o.m_Absolute)
|
|
&& (m_Name == o.m_Name) && (m_Dirs == o.m_Dirs);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool SysPath::operator != (const SysPath & o) const
|
|
{
|
|
return !(*this == o);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath::operator bool () const
|
|
{
|
|
return (m_Dirs.empty() && m_Name.empty() && (m_Drive == 0) && !m_Absolute);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const String & SysPath::operator [] (Uint32 n) const
|
|
{
|
|
// Is this within the bounds of the directory list?
|
|
if (n < m_Dirs.size())
|
|
{
|
|
return m_Dirs[n];
|
|
}
|
|
// Fall back to the file name
|
|
else
|
|
{
|
|
return m_Name;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Int32 SysPath::Cmp(const SysPath & o) const
|
|
{
|
|
if (*this == o)
|
|
return 0;
|
|
else if (ToBuffer().Position() > o.ToBuffer().Position())
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Object SysPath::ToString() const
|
|
{
|
|
return BufferToStrObj(ToBuffer());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::Swap(SysPath & path)
|
|
{
|
|
m_Dirs.swap(path.m_Dirs);
|
|
m_Name.swap(path.m_Name);
|
|
std::swap(m_Drive, path.m_Drive);
|
|
std::swap(m_Absolute, path.m_Absolute);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::Clear()
|
|
{
|
|
m_Dirs.clear();
|
|
m_Name.clear();
|
|
m_Drive = 0;
|
|
m_Absolute = false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(CSStr path)
|
|
{
|
|
// Is the specified path valid?
|
|
if (!path || *path == '\0')
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else
|
|
{
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path, path + strlen(path));
|
|
#else
|
|
ParseUnix(path, path + strlen(path));
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(CSStr path, Int32 style)
|
|
{
|
|
return Assign(path, static_cast< Style >(style));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(CSStr path, Style style)
|
|
{
|
|
// Is the specified path valid?
|
|
if (!path || *path == '\0')
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else
|
|
{
|
|
// Identify which style was requested
|
|
switch (style)
|
|
{
|
|
case Style::Unix:
|
|
ParseUnix(path, path + strlen(path));
|
|
break;
|
|
case Style::Windows:
|
|
ParseWindows(path, path + strlen(path));
|
|
break;
|
|
case Style::Native:
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path, path + strlen(path));
|
|
#else
|
|
ParseUnix(path, path + strlen(path));
|
|
#endif // SQMOD_OS_WINDOWS
|
|
break;
|
|
case Style::Guess:
|
|
ParseGuess(path, path + strlen(path));
|
|
break;
|
|
case Style::Dynamic:
|
|
ParseDynamic(path, path + strlen(path));
|
|
break;
|
|
default:
|
|
STHROWF("Unknown system path style");
|
|
}
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const Buffer & path, Int32 size)
|
|
{
|
|
// Is the specified path valid?
|
|
if (!path)
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else if (size < 0)
|
|
{
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.Data(), &path.Cursor());
|
|
#else
|
|
ParseUnix(path.Data(), &path.Cursor());
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
else if (static_cast< Uint32 >(size) < path.Capacity())
|
|
{
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.Data(), path.Data() + size);
|
|
#else
|
|
ParseUnix(path.Data(), path.Data() + size);
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
else
|
|
{
|
|
STHROWF("The specified path size is out of range: %u >= %u", size, path.Capacity());
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const Buffer & path, Style style, Int32 size)
|
|
{
|
|
// Is the specified path valid?
|
|
if (!path)
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else if (size < 0)
|
|
{
|
|
// Identify which style was requested
|
|
switch (style)
|
|
{
|
|
case Style::Unix:
|
|
ParseUnix(path.Data(), &path.Cursor());
|
|
break;
|
|
case Style::Windows:
|
|
ParseWindows(path.Data(), &path.Cursor());
|
|
break;
|
|
case Style::Native:
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.Data(), &path.Cursor());
|
|
#else
|
|
ParseUnix(path.Data(), &path.Cursor());
|
|
#endif // SQMOD_OS_WINDOWS
|
|
break;
|
|
case Style::Guess:
|
|
ParseGuess(path.Data(), &path.Cursor());
|
|
break;
|
|
case Style::Dynamic:
|
|
ParseDynamic(path.Data(), &path.Cursor());
|
|
break;
|
|
default:
|
|
STHROWF("Unknown system path style");
|
|
}
|
|
}
|
|
else if (static_cast< Uint32 >(size) < path.Capacity())
|
|
{
|
|
// Identify which style was requested
|
|
switch (style)
|
|
{
|
|
case Style::Unix:
|
|
ParseUnix(path.Data(), path.Data() + size);
|
|
break;
|
|
case Style::Windows:
|
|
ParseWindows(path.Data(), path.Data() + size);
|
|
break;
|
|
case Style::Native:
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.Data(), path.Data() + size);
|
|
#else
|
|
ParseUnix(path.Data(), path.Data() + size);
|
|
#endif // SQMOD_OS_WINDOWS
|
|
break;
|
|
case Style::Guess:
|
|
ParseGuess(path.Data(), path.Data() + size);
|
|
break;
|
|
case Style::Dynamic:
|
|
ParseDynamic(path.Data(), path.Data() + size);
|
|
break;
|
|
default:
|
|
STHROWF("Unknown system path style");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
STHROWF("The specified path size is out of range: %u >= %u", size, path.Capacity());
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const String & path)
|
|
{
|
|
// Is the specified path valid?
|
|
if (path.empty())
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else
|
|
{
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.data(), path.data() + path.size());
|
|
#else
|
|
ParseUnix(path.data(), path.data() + path.size());
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const String & path, Style style)
|
|
{
|
|
// Is the specified path valid?
|
|
if (path.empty())
|
|
{
|
|
// Just clear current path
|
|
Clear();
|
|
}
|
|
else
|
|
{
|
|
// Identify which style was requested
|
|
switch (style)
|
|
{
|
|
case Style::Unix:
|
|
ParseUnix(path.data(), path.data() + path.size());
|
|
break;
|
|
case Style::Windows:
|
|
ParseWindows(path.data(), path.data() + path.size());
|
|
break;
|
|
case Style::Native:
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
ParseWindows(path.data(), path.data() + path.size());
|
|
#else
|
|
ParseUnix(path.data(), path.data() + path.size());
|
|
#endif // SQMOD_OS_WINDOWS
|
|
break;
|
|
case Style::Guess:
|
|
ParseGuess(path.data(), path.data() + path.size());
|
|
break;
|
|
case Style::Dynamic:
|
|
ParseDynamic(path.data(), path.data() + path.size());
|
|
break;
|
|
default:
|
|
STHROWF("Unknown system path style");
|
|
}
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const SysPath & parent, CSStr name)
|
|
{
|
|
// Copy the parent values
|
|
*this = parent;
|
|
// Set the specified file name
|
|
SetFilename(name);
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const SysPath & parent, const String & name)
|
|
{
|
|
// Copy the parent values
|
|
*this = parent;
|
|
// Set the specified file name
|
|
SetFilename(name);
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const SysPath & parent, const SysPath & relative)
|
|
{
|
|
// Copy the parent values
|
|
*this = parent;
|
|
// Resolve the specified path
|
|
Resolve(relative);
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(const SysPath & path)
|
|
{
|
|
// Just use regular assignment
|
|
*this = path;
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Assign(SysPath && path)
|
|
{
|
|
// Just use regular assignment
|
|
*this = path;
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(CSStr path)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(CSStr path, Int32 style)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path, style);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(CSStr path, Style style)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path, style);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(const Buffer & path, Int32 size)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path, size);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(const Buffer & path, Style style, Int32 size)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path, style, size);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(const String & path)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::AssignDir(const String & path, Style style)
|
|
{
|
|
// Assign the specified path
|
|
Assign(path, style);
|
|
// Force it to be a directory and allow chaining
|
|
return MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Buffer SysPath::ToBuffer() const
|
|
{
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
return BuildWindows();
|
|
#else
|
|
return BuildUnix();
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Buffer SysPath::ToBuffer(Style style) const
|
|
{
|
|
if (style == Style::Unix)
|
|
{
|
|
return BuildUnix();
|
|
}
|
|
else if (style == Style::Windows)
|
|
{
|
|
return BuildWindows();
|
|
}
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
return BuildWindows();
|
|
#else
|
|
return BuildUnix();
|
|
#endif // SQMOD_OS_WINDOWS
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Object SysPath::ToStr(Int32 style) const
|
|
{
|
|
return BufferToStrObj(ToBuffer(static_cast< Style >(style)));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::FromString(CSStr path)
|
|
{
|
|
Assign(path);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeDirectory()
|
|
{
|
|
// Do we even have a name?
|
|
if (!m_Name.empty())
|
|
{
|
|
// Make it a directory
|
|
m_Dirs.push_back(std::move(m_Name));
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeFile()
|
|
{
|
|
// Do we have some directories and no existing file?
|
|
if (!m_Dirs.empty() && m_Name.empty())
|
|
{
|
|
// Use the last directory as a file
|
|
m_Name = std::move(m_Dirs.back());
|
|
// Remove it from the directory list
|
|
m_Dirs.pop_back();
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeParent()
|
|
{
|
|
// Do we have a name?
|
|
if (m_Name.empty())
|
|
{
|
|
// Do we have any existing directories?
|
|
if (m_Dirs.empty())
|
|
{
|
|
// Make sure this path isn't absolute
|
|
if (!m_Absolute)
|
|
{
|
|
// Reference the parent directory
|
|
m_Dirs.emplace_back("..");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Are we already referencing a parent?
|
|
if (m_Dirs.back().compare("..") == 0)
|
|
{
|
|
// Then reference the parent of that parent
|
|
m_Dirs.emplace_back("..");
|
|
}
|
|
// Just pop the last directory
|
|
else
|
|
{
|
|
m_Dirs.pop_back();
|
|
}
|
|
}
|
|
}
|
|
// Just clear the name
|
|
else
|
|
{
|
|
m_Name.clear();
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeAbsolute()
|
|
{
|
|
// Is this path already absolute?
|
|
if (!m_Absolute)
|
|
{
|
|
MakeAbsolute(Working());
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeAbsolute(const SysPath & base)
|
|
{
|
|
// Is this path already absolute?
|
|
if (!m_Absolute)
|
|
{
|
|
MakeAbsolute(base);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::MakeAbsolute(SysPath && base)
|
|
{
|
|
// Is this path already absolute?
|
|
if (!m_Absolute)
|
|
{
|
|
// Reserve the space upfront
|
|
base.m_Dirs.reserve(base.m_Dirs.size() + m_Dirs.size());
|
|
// Move our directories at the back
|
|
for (auto & dir : m_Dirs)
|
|
{
|
|
base.m_Dirs.push_back(std::move(dir));
|
|
}
|
|
// Take ownership of base directories
|
|
m_Dirs.swap(base.m_Dirs);
|
|
// Copy the drive letter
|
|
m_Drive = base.m_Drive;
|
|
// Make absolute only if base is
|
|
m_Absolute = base.m_Absolute;
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(const SysPath & path)
|
|
{
|
|
// Make sure this is a directory
|
|
MakeDirectory();
|
|
// Only attempt to append if not empty
|
|
if (!path.Empty())
|
|
{
|
|
// Append the directories from the specified path
|
|
m_Dirs.insert(m_Dirs.end(), path.m_Dirs.begin(), path.m_Dirs.end());
|
|
// Copy the file name if any
|
|
m_Name = path.m_Name;
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(SysPath && path)
|
|
{
|
|
// Make sure this is a directory
|
|
MakeDirectory();
|
|
// Only attempt to append if not empty
|
|
if (!path.Empty())
|
|
{
|
|
// Request the necessary directory list size upfront
|
|
m_Dirs.reserve(m_Dirs.size() + path.m_Dirs.size());
|
|
// Move all directories at the back of our list
|
|
for (auto & dir : path.m_Dirs)
|
|
{
|
|
m_Dirs.push_back(std::move(dir));
|
|
}
|
|
// Move the file name if any
|
|
m_Name = std::move(path.m_Name);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(CSStr path)
|
|
{
|
|
return Append(SysPath(path));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(CSStr path, Int32 style)
|
|
{
|
|
return Append(SysPath(path, style));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(CSStr path, Style style)
|
|
{
|
|
return Append(SysPath(path, style));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(const Buffer & path, Int32 size)
|
|
{
|
|
return Append(SysPath(path, size));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(const Buffer & path, Style style, Int32 size)
|
|
{
|
|
return Append(SysPath(path, style, size));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(const String & path)
|
|
{
|
|
return Append(SysPath(path));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Append(const String & path, Style style)
|
|
{
|
|
return Append(SysPath(path, style));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const String & SysPath::Directory(Uint32 n) const
|
|
{
|
|
// Is this within the bounds of the directory list?
|
|
if (n < m_Dirs.size())
|
|
{
|
|
return m_Dirs[n];
|
|
}
|
|
// Fall back to the file name
|
|
else
|
|
{
|
|
return m_Name;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Push(CSStr dir)
|
|
{
|
|
// Is the specified directory valid?
|
|
if (dir && *dir != 0)
|
|
{
|
|
Push(String(dir));
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Push(const String & dir)
|
|
{
|
|
// Is the specified directory valid?
|
|
if (!dir.empty() && dir.compare(".") != 0)
|
|
{
|
|
Push(String(dir));
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Push(String && dir)
|
|
{
|
|
// Is the specified directory valid?
|
|
if (!dir.empty() && dir.compare(".") != 0)
|
|
{
|
|
// Does it refer to a parent directory?
|
|
if (dir.compare("..") == 0)
|
|
{
|
|
// Is out last directory already a reference to a parent?
|
|
if (!m_Dirs.empty() && m_Dirs.back().compare("..") != 0)
|
|
{
|
|
m_Dirs.pop_back();
|
|
}
|
|
// Move it at the back of our list
|
|
else if (!m_Absolute)
|
|
{
|
|
m_Dirs.push_back(dir);
|
|
}
|
|
}
|
|
// Move it at the back of our list
|
|
else
|
|
{
|
|
m_Dirs.push_back(dir);
|
|
}
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::PopBack()
|
|
{
|
|
// Do we even have any directories?
|
|
if (!m_Dirs.empty())
|
|
{
|
|
// Erase the last one
|
|
m_Dirs.pop_back();
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::PopFront()
|
|
{
|
|
// Do we even have any directories?
|
|
if (!m_Dirs.empty())
|
|
{
|
|
// Erase the first one
|
|
m_Dirs.erase(m_Dirs.begin());
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetFilename(CSStr name)
|
|
{
|
|
// Is the file name even valid?
|
|
if (name)
|
|
{
|
|
m_Name.assign(name);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetFilename(const String & name)
|
|
{
|
|
// Is the file name even valid?
|
|
m_Name.assign(name);
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetFilename(String && name)
|
|
{
|
|
// Is the file name even valid?
|
|
m_Name.assign(name);
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetBasename(CSStr name)
|
|
{
|
|
// Is the file name even valid?
|
|
if (name)
|
|
{
|
|
// Extract the current extension
|
|
String ext = GetExtension();
|
|
// Assign the new base name
|
|
m_Name.assign(name);
|
|
// Was there an extension before?
|
|
if (!ext.empty())
|
|
{
|
|
// Add the extension separator
|
|
m_Name.push_back('.');
|
|
// Add the original extension
|
|
m_Name.append(ext);
|
|
}
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetBasename(const String & name)
|
|
{
|
|
// Extract the current extension
|
|
String ext = GetExtension();
|
|
// Assign the new base name
|
|
m_Name.assign(name);
|
|
// Was there an extension before?
|
|
if (!ext.empty())
|
|
{
|
|
// Add the extension separator
|
|
m_Name.push_back('.');
|
|
// Add the original extension
|
|
m_Name.append(ext);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetBasename(String && name)
|
|
{
|
|
// Extract the current extension
|
|
String ext = GetExtension();
|
|
// Assign the new base name
|
|
m_Name.assign(name);
|
|
// Was there an extension before?
|
|
if (!ext.empty())
|
|
{
|
|
// Add the extension separator
|
|
m_Name.push_back('.');
|
|
// Add the original extension
|
|
m_Name.append(ext);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
String SysPath::GetBasename() const
|
|
{
|
|
// Attempt to find the last dot in the file name
|
|
const String::size_type pos = m_Name.rfind('.');
|
|
// Was there an extension separator?
|
|
if (pos != String::npos)
|
|
{
|
|
// Return everything before the separator
|
|
return m_Name.substr(0, pos);
|
|
}
|
|
// Return the whole name
|
|
return m_Name;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetExtension(CSStr ext)
|
|
{
|
|
// Attempt to find the last dot in the file name
|
|
const String::size_type pos = m_Name.rfind('.');
|
|
// Was there an extension separator?
|
|
if (pos != String::npos)
|
|
{
|
|
// Erase the current extension
|
|
m_Name.resize(pos);
|
|
}
|
|
// Is there an extension to append?
|
|
if (ext && *ext != 0)
|
|
{
|
|
m_Name.push_back('.');
|
|
m_Name.append(ext);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::SetExtension(const String & ext)
|
|
{
|
|
// Attempt to find the last dot in the file name
|
|
const String::size_type pos = m_Name.rfind('.');
|
|
// Was there an extension separator?
|
|
if (pos != String::npos)
|
|
{
|
|
// Erase the current extension
|
|
m_Name.resize(pos);
|
|
}
|
|
// Is there an extension to append?
|
|
if (!ext.empty())
|
|
{
|
|
m_Name.push_back('.');
|
|
m_Name.append(ext);
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
String SysPath::GetExtension() const
|
|
{
|
|
// Attempt to find the last dot in the file name
|
|
const String::size_type pos = m_Name.rfind('.');
|
|
// Was there an extension separator?
|
|
if (pos != String::npos)
|
|
{
|
|
// Return everything after the separator
|
|
return m_Name.substr(pos + 1);
|
|
}
|
|
// Default to an empty string
|
|
return String();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
CSStr SysPath::GetExtensionC() const
|
|
{
|
|
// Attempt to find the last dot in the file name
|
|
const String::size_type pos = m_Name.rfind('.');
|
|
// Was there an extension separator?
|
|
if (pos != String::npos)
|
|
{
|
|
// Because indexing starts from 0, the separator is skipped
|
|
return &m_Name[pos+1];
|
|
}
|
|
// Default to an empty string
|
|
return "";
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Parent() const
|
|
{
|
|
// Make a copy
|
|
SysPath p(*this);
|
|
// Force the copy to be parent
|
|
p.MakeParent();
|
|
// Return ownership of copy
|
|
return std::move(p);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath & SysPath::Resolve(const SysPath & path)
|
|
{
|
|
// Is the specified path absolute?
|
|
if (path.m_Absolute)
|
|
{
|
|
// Copy it's values
|
|
Assign(path);
|
|
}
|
|
else
|
|
{
|
|
// Append its directories
|
|
for (const auto & dir : path.m_Dirs)
|
|
{
|
|
Push(dir);
|
|
}
|
|
// Copy its file name
|
|
m_Name = path.m_Name;
|
|
}
|
|
// Allow chaining
|
|
return *this;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::ParseUnix(CSStr pos, CSStr end)
|
|
{
|
|
// Clear previous path information
|
|
Clear();
|
|
// Is there even a path to parse?
|
|
if (pos == end)
|
|
{
|
|
return;
|
|
}
|
|
// If the path starts with a forward slash then the path is absolute
|
|
else if (*pos == '/')
|
|
{
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
// Skip this directory separator
|
|
++pos;
|
|
}
|
|
// If the path starts with the tilde character then the home directory was requested
|
|
else if (*pos == '~')
|
|
{
|
|
// To be expanded, the tilde character must be followed by a slash or no other character
|
|
if (pos == end || *(++pos) == '/')
|
|
{
|
|
// Obtain the home path
|
|
SysPath up(Home());
|
|
// Take ownership, don't copy
|
|
m_Dirs.swap(up.m_Dirs);
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
}
|
|
// Go back to the previous character and use it literally
|
|
else
|
|
{
|
|
--pos;
|
|
}
|
|
}
|
|
// Make another iterator to slice directory names in one go
|
|
CSStr itr = pos;
|
|
// Extract the remaining directories from the specified path
|
|
while (itr != end)
|
|
{
|
|
// Have we encountered a directory separator?
|
|
if (*itr == '/')
|
|
{
|
|
// Slice the name from the path if valid
|
|
if (itr != pos)
|
|
{
|
|
m_Dirs.emplace_back(pos, itr);
|
|
}
|
|
// Move the iterator to the current position
|
|
pos = ++itr;
|
|
}
|
|
else
|
|
{
|
|
++itr;
|
|
}
|
|
}
|
|
// Grab the last name if any
|
|
if (pos != end)
|
|
{
|
|
m_Name.assign(pos, end);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::ParseWindows(CSStr pos, CSStr end)
|
|
{
|
|
// Clear previous path information
|
|
Clear();
|
|
// Is there even a path to parse?
|
|
if (pos == end)
|
|
{
|
|
return;
|
|
}
|
|
// If the path starts with a forward slash then the path is absolute
|
|
else if (*pos == '\\')
|
|
{
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
// Skip this directory separator
|
|
++pos;
|
|
}
|
|
// If the path starts with the tilde character then the home directory was requested
|
|
else if (*pos == '~')
|
|
{
|
|
// To be expanded, the tilde character must be followed by a slash or no other character
|
|
if (pos == end || *(++pos) == '\\')
|
|
{
|
|
// Obtain the home path
|
|
SysPath up(Home());
|
|
// Take ownership, don't copy
|
|
m_Dirs.swap(up.m_Dirs);
|
|
// Also copy the drive letter
|
|
m_Drive = up.m_Drive;
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
}
|
|
// Go back to the previous character and use it literally
|
|
else
|
|
{
|
|
--pos;
|
|
}
|
|
}
|
|
// Is it possible to have a drive letter?
|
|
else if ((end - pos) > 2 && pos[1] == ':' && pos[2] == '\\' && isalpha(*pos) != 0)
|
|
{
|
|
// Grab the drive letter
|
|
m_Drive = *pos;
|
|
// Skip the drive path and colon
|
|
pos += 2;
|
|
}
|
|
// Is it possible to have just the drive letter?
|
|
else if ((end - pos) == 2 && pos[1] == ':' && isalpha(*pos) != 0)
|
|
{
|
|
// Grab the drive letter
|
|
m_Drive = *pos;
|
|
// Nothing left to parse
|
|
return;
|
|
}
|
|
// Make another iterator to slice directory names in one go
|
|
CSStr itr = pos;
|
|
// Extract the remaining directories from the specified path
|
|
while (itr != end)
|
|
{
|
|
// Have we encountered a directory separator?
|
|
if (*itr == '\\')
|
|
{
|
|
// Slice the name from the path if valid
|
|
if (itr != pos)
|
|
{
|
|
m_Dirs.emplace_back(pos, itr);
|
|
}
|
|
// Move the iterator to the current position
|
|
pos = ++itr;
|
|
}
|
|
else
|
|
{
|
|
++itr;
|
|
}
|
|
}
|
|
// Grab the last name if any
|
|
if (pos != end)
|
|
{
|
|
m_Name.assign(pos, end);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::ParseDynamic(CSStr pos, CSStr end)
|
|
{
|
|
// Clear previous path information
|
|
Clear();
|
|
// Is there even a path to parse?
|
|
if (pos == end)
|
|
{
|
|
return;
|
|
}
|
|
// If the path starts with a slash then the path is absolute
|
|
else if (*pos == '\\' || *pos == '/')
|
|
{
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
// Skip this directory separator
|
|
++pos;
|
|
}
|
|
// If the path starts with the tilde character then the home directory was requested
|
|
else if (*pos == '~')
|
|
{
|
|
// Skip the tilde character
|
|
++pos;
|
|
// The tilde character must be followed by a slash or no other character to be expanded
|
|
if (pos == end || *pos == '/' || *pos == '\\')
|
|
{
|
|
// Obtain the home path
|
|
SysPath up(Home());
|
|
// Take ownership, don't copy
|
|
m_Dirs.swap(up.m_Dirs);
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
// Also copy the drive letter
|
|
m_Drive = up.m_Drive;
|
|
#endif // SQMOD_OS_WINDOWS
|
|
// This is now an absolute path
|
|
m_Absolute = true;
|
|
}
|
|
// Go back to the previous character and use it literally
|
|
else
|
|
{
|
|
--pos;
|
|
}
|
|
}
|
|
#ifdef SQMOD_OS_WINDOWS
|
|
// Is it possible to have a drive letter?
|
|
else if ((end - pos) > 2 && pos[1] == ':' && (pos[2] == '\\' || pos[2] == '/') && isalpha(*pos) != 0)
|
|
{
|
|
// Grab the drive letter
|
|
m_Drive = *pos;
|
|
// Skip the drive path and colon
|
|
pos += 2;
|
|
}
|
|
// Is it possible to have just the drive letter?
|
|
else if ((end - pos) == 2 && pos[1] == ':' && isalpha(*pos) != 0)
|
|
{
|
|
// Grab the drive letter
|
|
m_Drive = *pos;
|
|
// Nothing left to parse
|
|
return;
|
|
}
|
|
#endif // SQMOD_OS_WINDOWS
|
|
// Make another iterator to slice directory names in one go
|
|
CSStr itr = pos;
|
|
// Extract the remaining directories from the specified path
|
|
while (itr != end)
|
|
{
|
|
// Have we encountered a directory separator?
|
|
if (*itr == '/' || *itr == '\\')
|
|
{
|
|
// Slice the name from the path if valid
|
|
if (itr != pos)
|
|
{
|
|
m_Dirs.emplace_back(pos, itr);
|
|
}
|
|
// Move the iterator to the current position
|
|
pos = ++itr;
|
|
}
|
|
else
|
|
{
|
|
++itr;
|
|
}
|
|
}
|
|
// Grab the last name if any
|
|
if (pos != end)
|
|
{
|
|
m_Name.assign(pos, end);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SysPath::ParseGuess(CSStr pos, CSStr end)
|
|
{
|
|
// Scan for forward slash
|
|
const bool has_fwslash = (strchr(pos, '/') != NULL);
|
|
const bool has_bwslash = (strchr(pos, '\\') != NULL);
|
|
// Does it contain both forward and backward slashes?
|
|
if (has_fwslash && has_bwslash)
|
|
{
|
|
ParseDynamic(pos, end);
|
|
}
|
|
// Does it contain the forward slash?
|
|
else if (has_fwslash)
|
|
{
|
|
ParseUnix(pos, end);
|
|
}
|
|
// Does it contain the backward slash?
|
|
else if (has_bwslash)
|
|
{
|
|
ParseWindows(pos, end);
|
|
}
|
|
// Does it contain a drive letter?
|
|
else if ((end - pos) == 2 && pos[1] == ':' && isalpha(*pos) != 0)
|
|
{
|
|
ParseWindows(pos, end);
|
|
}
|
|
// Try to parse it as a dynamic path
|
|
else
|
|
{
|
|
ParseDynamic(pos, end);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Buffer SysPath::BuildUnix() const
|
|
{
|
|
// Obtain a buffer capable of storing a full path
|
|
Buffer b(SQMOD_MAX_PATH);
|
|
// Is this an absolute path?
|
|
if (m_Absolute)
|
|
{
|
|
// Start with a slash
|
|
b.Push('/');
|
|
}
|
|
// Concatenate all directories
|
|
for (const auto & dir : m_Dirs)
|
|
{
|
|
// Append the name
|
|
b.AppendS(dir.c_str(), dir.size());
|
|
// Separate from next
|
|
b.Push('/');
|
|
}
|
|
// Is there a file name to add?
|
|
if (!m_Name.empty())
|
|
{
|
|
b.AppendS(m_Name.c_str(), m_Name.size());
|
|
}
|
|
// Make sure the string is null terminated
|
|
b.Cursor() = '\0';
|
|
// Return ownership of buffer
|
|
return std::move(b);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
Buffer SysPath::BuildWindows() const
|
|
{
|
|
// Obtain a buffer capable of storing a full path
|
|
Buffer b(SQMOD_MAX_PATH);
|
|
// Does it have a drive letter?
|
|
if (isalpha(m_Drive) != 0)
|
|
{
|
|
// Add the drive letter
|
|
b.Push(m_Drive);
|
|
// Add the colon
|
|
b.Push(':');
|
|
// Add the slash
|
|
b.Push('\\');
|
|
}
|
|
// Is this an absolute path?
|
|
else if (m_Absolute)
|
|
{
|
|
// Start with a slash
|
|
b.Push('\\');
|
|
}
|
|
// Concatenate all directories
|
|
for (const auto & dir : m_Dirs)
|
|
{
|
|
// Append the name
|
|
b.AppendS(dir.c_str(), dir.size());
|
|
// Separate from next
|
|
b.Push('\\');
|
|
}
|
|
// Is there a file name to add?
|
|
if (!m_Name.empty())
|
|
{
|
|
b.AppendS(m_Name.c_str(), m_Name.size());
|
|
}
|
|
// Make sure the string is null terminated
|
|
b.Cursor() = '\0';
|
|
// Return ownership of buffer
|
|
return std::move(b);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ForDirectory(CSStr path)
|
|
{
|
|
return SysPath(path).MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ForDirectory(CSStr path, Int32 style)
|
|
{
|
|
return SysPath(path, style).MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ForDirectory(CSStr path, Style style)
|
|
{
|
|
return SysPath(path, style).MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ForDirectory(const String & path)
|
|
{
|
|
return SysPath(path).MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ForDirectory(const String & path, Style style)
|
|
{
|
|
return SysPath(path, style).MakeDirectory();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Expand(CSStr path)
|
|
{
|
|
return SysPath(SysEnv::ExpandPath(path));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Home()
|
|
{
|
|
return SysPath(SysEnv::HomeDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::ConfigHome()
|
|
{
|
|
return SysPath(SysEnv::ConfigHomeDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::DataHome()
|
|
{
|
|
return SysPath(SysEnv::DataHomeDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::TempHome()
|
|
{
|
|
return SysPath(SysEnv::TempHomeDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::CacheHome()
|
|
{
|
|
return SysPath(SysEnv::CacheHomeDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Working()
|
|
{
|
|
return SysPath(SysEnv::WorkingDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Temp()
|
|
{
|
|
return SysPath(SysEnv::TempDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Config()
|
|
{
|
|
return SysPath(SysEnv::ConfigDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::System()
|
|
{
|
|
return SysPath(SysEnv::SystemDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Null()
|
|
{
|
|
return SysPath(SysEnv::NullDir());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::Real(CSStr path)
|
|
{
|
|
return SysPath(GetRealFilePath(path));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::With(const SysPath & parent, CSStr name)
|
|
{
|
|
return SysPath(parent, name);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::MakeUnix(CSStr path)
|
|
{
|
|
return SysPath(path, Style::Unix);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::MakeWindows(CSStr path)
|
|
{
|
|
return SysPath(path, Style::Windows);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::MakeNative(CSStr path)
|
|
{
|
|
return SysPath(path, Style::Native);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::MakeGuess(CSStr path)
|
|
{
|
|
return SysPath(path, Style::Guess);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
SysPath SysPath::MakeDynamic(CSStr path)
|
|
{
|
|
return SysPath(path, Style::Dynamic);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
String SysPath::NormalizePath(SQInteger s, StackStrF & val)
|
|
{
|
|
// Have we failed to retrieve the string?
|
|
if (SQ_FAILED(val.Proc(true)))
|
|
{
|
|
STHROWLASTF("Invalid string");
|
|
}
|
|
// Is the string empty?
|
|
else if (!val.mLen)
|
|
{
|
|
return String();
|
|
}
|
|
// Turn it into a string that we can edit
|
|
String str(val.mPtr, val.mLen);
|
|
// Replace all occurences of the specified character
|
|
for (String::reference c : str)
|
|
{
|
|
if (c == '/' || c == '\\')
|
|
{
|
|
c = static_cast< String::value_type >(s);
|
|
}
|
|
}
|
|
// Return the new string
|
|
return str;
|
|
}
|
|
// ================================================================================================
|
|
void Register_SysPath(HSQUIRRELVM vm)
|
|
{
|
|
RootTable(vm).Bind(Typename::Str,
|
|
Class< SysPath >(vm, Typename::Str)
|
|
// Constructors
|
|
.Ctor()
|
|
.Ctor< CSStr >()
|
|
.Ctor< CSStr, Int32 >()
|
|
// Meta-methods
|
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
|
.Func(_SC("_tostring"), &SysPath::ToString)
|
|
.Func(_SC("cmp"), &SysPath::Cmp)
|
|
// Properties
|
|
.Prop(_SC("String"), &SysPath::ToString, &SysPath::FromString)
|
|
.Prop(_SC("IsAbs"), &SysPath::IsAbsolute)
|
|
.Prop(_SC("IsAbsolute"), &SysPath::IsAbsolute)
|
|
.Prop(_SC("IsRel"), &SysPath::IsRelative)
|
|
.Prop(_SC("IsRelative"), &SysPath::IsRelative)
|
|
.Prop(_SC("IsDir"), &SysPath::IsDirectory)
|
|
.Prop(_SC("IsDirectory"), &SysPath::IsDirectory)
|
|
.Prop(_SC("IsFile"), &SysPath::IsFile)
|
|
.Prop(_SC("IsEmpty"), &SysPath::Empty)
|
|
.Prop(_SC("Drive"), &SysPath::GetDrive, &SysPath::SetDrive)
|
|
.Prop(_SC("Depth"), &SysPath::Depth)
|
|
.Prop(_SC("Filename"), &SysPath::GetFilename, &SysPath::SqSetFilename)
|
|
.Prop(_SC("Basename"), &SysPath::GetBasename, &SysPath::SqSetBasename)
|
|
.Prop(_SC("Extension"), &SysPath::GetExtensionC, &SysPath::SqSetExtension)
|
|
.Prop(_SC("Parent"), &SysPath::Parent)
|
|
// Member Methods
|
|
.Func(_SC("Swap"), &SysPath::Swap)
|
|
.Func(_SC("Clear"), &SysPath::Clear)
|
|
.Func< SysPath & (SysPath::*)(const SysPath &) >(_SC("AssignPath"), &SysPath::Assign)
|
|
.Func< SysPath & (SysPath::*)(const SysPath &) >(_SC("AppendPath"), &SysPath::Append)
|
|
.Func(_SC("Build"), &SysPath::ToStr)
|
|
.Func(_SC("ToStr"), &SysPath::ToStr)
|
|
.Func(_SC("MakeDir"), &SysPath::MakeDirectory)
|
|
.Func(_SC("MakeDirectory"), &SysPath::MakeDirectory)
|
|
.Func(_SC("MakeFile"), &SysPath::MakeFile)
|
|
.Func(_SC("MakeParent"), &SysPath::MakeParent)
|
|
.Func(_SC("Dir"), &SysPath::Directory)
|
|
.Func(_SC("Directory"), &SysPath::Directory)
|
|
.Func< SysPath & (SysPath::*)(CSStr) >(_SC("Push"), &SysPath::Push)
|
|
.Func(_SC("PopBack"), &SysPath::PopBack)
|
|
.Func(_SC("PopFront"), &SysPath::PopFront)
|
|
.Func< SysPath & (SysPath::*)(CSStr) >(_SC("SetFilename"), &SysPath::SetFilename)
|
|
.Func(_SC("GetFilename"), &SysPath::GetFilename)
|
|
.Func< SysPath & (SysPath::*)(CSStr) >(_SC("SetBasename"), &SysPath::SetBasename)
|
|
.Func(_SC("GetBasename"), &SysPath::GetBasename)
|
|
.Func< SysPath & (SysPath::*)(CSStr) >(_SC("SetExtension"), &SysPath::SetExtension)
|
|
.Func(_SC("GetExtension"), &SysPath::GetExtension)
|
|
.Func(_SC("Resolve"), &SysPath::Resolve)
|
|
// Member Overloads
|
|
.Overload< SysPath & (SysPath::*)(CSStr) >(_SC("Assign"), &SysPath::Assign)
|
|
.Overload< SysPath & (SysPath::*)(CSStr, Int32) >(_SC("Assign"), &SysPath::Assign)
|
|
.Overload< SysPath & (SysPath::*)(CSStr) >(_SC("AssignDir"), &SysPath::AssignDir)
|
|
.Overload< SysPath & (SysPath::*)(CSStr, Int32) >(_SC("AssignDir"), &SysPath::AssignDir)
|
|
.Overload< SysPath & (SysPath::*)(CSStr) >(_SC("Append"), &SysPath::Append)
|
|
.Overload< SysPath & (SysPath::*)(CSStr, Int32) >(_SC("Append"), &SysPath::Append)
|
|
.Overload< SysPath & (SysPath::*)(void) >(_SC("MakeAbsolute"), &SysPath::MakeAbsolute)
|
|
.Overload< SysPath & (SysPath::*)(const SysPath &) >(_SC("MakeAbsolute"), &SysPath::MakeAbsolute)
|
|
// Static Functions
|
|
.StaticFunc(_SC("Separator"), &SysPath::Separator)
|
|
.StaticFunc(_SC("PathSeparator"), &SysPath::PathSeparator)
|
|
.StaticFunc< SysPath (*)(CSStr) >(_SC("Expand"), &SysPath::Expand)
|
|
.StaticFunc(_SC("Home"), &SysPath::Home)
|
|
.StaticFunc(_SC("ConfigHome"), &SysPath::ConfigHome)
|
|
.StaticFunc(_SC("DataHome"), &SysPath::DataHome)
|
|
.StaticFunc(_SC("TempHome"), &SysPath::TempHome)
|
|
.StaticFunc(_SC("CacheHome"), &SysPath::CacheHome)
|
|
.StaticFunc(_SC("Current"), &SysPath::Working)
|
|
.StaticFunc(_SC("Working"), &SysPath::Working)
|
|
.StaticFunc(_SC("Temp"), &SysPath::Temp)
|
|
.StaticFunc(_SC("Config"), &SysPath::Config)
|
|
.StaticFunc(_SC("System"), &SysPath::System)
|
|
.StaticFunc(_SC("Null"), &SysPath::Null)
|
|
.StaticFunc(_SC("Real"), &SysPath::Real)
|
|
.StaticFunc(_SC("With"), &SysPath::With)
|
|
.StaticFunc(_SC("Unix"), &SysPath::MakeUnix)
|
|
.StaticFunc(_SC("Windows"), &SysPath::MakeWindows)
|
|
.StaticFunc(_SC("Native"), &SysPath::MakeNative)
|
|
.StaticFunc(_SC("Guess"), &SysPath::MakeGuess)
|
|
.StaticFunc(_SC("Dynamic"), &SysPath::MakeDynamic)
|
|
.StaticFmtFunc(_SC("Normalize"), &SysPath::NormalizePath)
|
|
// Static Overloads
|
|
.StaticOverload< SysPath (*)(CSStr) >(_SC("ForDir"), &SysPath::ForDirectory)
|
|
.StaticOverload< SysPath (*)(CSStr, Int32) >(_SC("ForDir"), &SysPath::ForDirectory)
|
|
.StaticOverload< SysPath (*)(CSStr) >(_SC("ForDirectory"), &SysPath::ForDirectory)
|
|
.StaticOverload< SysPath (*)(CSStr, Int32) >(_SC("ForDirectory"), &SysPath::ForDirectory)
|
|
);
|
|
|
|
ConstTable(vm).Enum(_SC("SqSysPathStyle"), Enumeration(vm)
|
|
.Const(_SC("Unix"), static_cast< Int32 >(SysPath::Style::Unix))
|
|
.Const(_SC("Windows"), static_cast< Int32 >(SysPath::Style::Windows))
|
|
.Const(_SC("Native"), static_cast< Int32 >(SysPath::Style::Native))
|
|
.Const(_SC("Guess"), static_cast< Int32 >(SysPath::Style::Guess))
|
|
.Const(_SC("Dynamic"), static_cast< Int32 >(SysPath::Style::Dynamic))
|
|
);
|
|
}
|
|
|
|
} // Namespace:: SqMod
|