mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-18 19:29:09 +00:00
Add plFilesystem module, which replaces previous filesystem APIs with a plFileName-based one
This commit is contained in:
@ -41,6 +41,7 @@ set(CoreLib_SOURCES
|
||||
hsThread.cpp
|
||||
hsWide.cpp
|
||||
pcSmallRect.cpp
|
||||
plFileSystem.cpp
|
||||
plGeneric.cpp
|
||||
plLoadMask.cpp
|
||||
plProduct.cpp
|
||||
@ -85,6 +86,7 @@ set(CoreLib_HEADERS
|
||||
hsWide.h
|
||||
hsWindows.h
|
||||
pcSmallRect.h
|
||||
plFileSystem.h
|
||||
plGeneric.h
|
||||
plLoadMask.h
|
||||
plProduct.h
|
||||
|
@ -46,7 +46,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsMemory.h"
|
||||
#include "plString.h"
|
||||
#include "plFileSystem.h"
|
||||
|
||||
|
||||
// Define this for use of Streams with Logging (commonly used w/ a packet sniffer)
|
||||
|
367
Sources/Plasma/CoreLib/plFileSystem.cpp
Normal file
367
Sources/Plasma/CoreLib/plFileSystem.cpp
Normal file
@ -0,0 +1,367 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "plFileSystem.h"
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
# include "hsWindows.h"
|
||||
# include <shlobj.h>
|
||||
#else
|
||||
# include <limits.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
# include <cstdlib>
|
||||
# include <functional>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include "plProduct.h"
|
||||
|
||||
/* NOTE For this file: Windows uses UTF-16 filenames, and does not support
|
||||
* the use of UTF-8 in their ANSI API. In order to ensure proper unicode
|
||||
* support, we convert the UTF-8 format stored in plString to UTF-16 before
|
||||
* passing them along to Windows.
|
||||
*/
|
||||
|
||||
plString plFileName::GetFileName() const
|
||||
{
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
if (end < 0)
|
||||
return fName;
|
||||
|
||||
return fName.Substr(end + 1);
|
||||
}
|
||||
|
||||
plString plFileName::GetFileExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
if (dot > end)
|
||||
return fName.Substr(dot + 1);
|
||||
|
||||
return plString::Null;
|
||||
}
|
||||
|
||||
plString plFileName::GetFileNameNoExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
if (dot > end)
|
||||
return fName.Substr(end + 1, dot - end - 1);
|
||||
return fName.Substr(end + 1);
|
||||
}
|
||||
|
||||
plFileName plFileName::StripFileName() const
|
||||
{
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
if (end < 0)
|
||||
return "";
|
||||
|
||||
return fName.Left(end);
|
||||
}
|
||||
|
||||
plFileName plFileName::StripFileExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
if (dot > end)
|
||||
return fName.Left(dot);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
plFileName plFileName::Normalize(char slash) const
|
||||
{
|
||||
plStringBuffer<char> norm;
|
||||
char *norm_p = norm.CreateWritableBuffer(fName.GetSize());
|
||||
for (const char *p = fName.c_str(); *p; ++p) {
|
||||
if (*p == '/' || *p == '\\')
|
||||
*norm_p++ = slash;
|
||||
else
|
||||
*norm_p++ = *p;
|
||||
}
|
||||
*norm_p = 0;
|
||||
return plString(norm);
|
||||
}
|
||||
|
||||
plFileName plFileName::AbsolutePath() const
|
||||
{
|
||||
if (!IsValid())
|
||||
return *this;
|
||||
|
||||
plFileName path = Normalize();
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
plStringBuffer<wchar_t> wideName = path.fName.ToWchar();
|
||||
wchar_t path_sm[MAX_PATH];
|
||||
uint32_t path_length = GetFullPathNameW(wideName, MAX_PATH, path_sm, nullptr);
|
||||
if (path_length >= MAX_PATH) {
|
||||
// Buffer not big enough
|
||||
wchar_t *path_lg = new wchar_t[path_length];
|
||||
GetFullPathNameW(wideName, path_length, path_lg, nullptr);
|
||||
path = plString::FromWchar(path_lg);
|
||||
delete [] path_lg;
|
||||
} else {
|
||||
path = plString::FromWchar(path_sm);
|
||||
}
|
||||
#else
|
||||
char *path_a = realpath(path.c_str(), nullptr);
|
||||
hsAssert(path_a, "Failure to get absolute path (unsupported libc?)");
|
||||
path = path_a;
|
||||
free(path_a);
|
||||
#endif
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
plFileName plFileName::Join(const plFileName &base, const plFileName &path)
|
||||
{
|
||||
if (!base.IsValid())
|
||||
return path;
|
||||
if (!path.IsValid())
|
||||
return base;
|
||||
|
||||
char last = base.fName.CharAt(base.GetSize() - 1);
|
||||
char first = path.fName.CharAt(0);
|
||||
if (last != '/' && last != '\\') {
|
||||
if (first != '/' && first != '\\') {
|
||||
return plString::Format("%s" PATH_SEPARATOR_STR "%s",
|
||||
base.fName.c_str(), path.fName.c_str());
|
||||
}
|
||||
return base.fName + path.fName;
|
||||
} else if (first != '/' && first != '\\') {
|
||||
return base.fName + path.fName;
|
||||
}
|
||||
// Both have a slash, but we only need one
|
||||
return base.fName + path.fName.Substr(1);
|
||||
}
|
||||
|
||||
|
||||
/* plFileInfo */
|
||||
plFileInfo::plFileInfo(const plFileName &filename)
|
||||
: fFileSize(-1), fCreateTime(), fModifyTime(), fFlags()
|
||||
{
|
||||
if (!filename.IsValid())
|
||||
return;
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
struct __stat64 info;
|
||||
if (!_wstat64(filename.AsString().ToWchar(), &info) == 0)
|
||||
return;
|
||||
#else
|
||||
struct stat info;
|
||||
if (!stat(filename.AsString().c_str(), &info) == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
fFlags |= kEntryExists;
|
||||
fFileSize = info.st_size;
|
||||
fCreateTime = info.st_ctime;
|
||||
fModifyTime = info.st_mtime;
|
||||
if (info.st_mode & S_IFDIR)
|
||||
fFlags |= kIsDirectory;
|
||||
if (info.st_mode & S_IFREG)
|
||||
fFlags |= kIsNormalFile;
|
||||
}
|
||||
|
||||
|
||||
/* plFileSystem */
|
||||
plFileName plFileSystem::GetCWD()
|
||||
{
|
||||
plFileName cwd;
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
wchar_t cwd_sm[MAX_PATH];
|
||||
uint32_t cwd_length = GetCurrentDirectoryW(MAX_PATH, cwd_sm);
|
||||
if (cwd_length >= MAX_PATH) {
|
||||
// Buffer not big enough
|
||||
wchar_t *cwd_lg = new wchar_t[cwd_length];
|
||||
GetCurrentDirectoryW(cwd_length, cwd_lg);
|
||||
cwd = plString::FromWchar(cwd_lg);
|
||||
delete [] cwd_lg;
|
||||
} else {
|
||||
cwd = plString::FromWchar(cwd_sm);
|
||||
}
|
||||
#else
|
||||
char *cwd_a = getcwd(nullptr, 0);
|
||||
hsAssert(cwd_a, "Failure to get working directory (unsupported libc?)");
|
||||
cwd = cwd_a;
|
||||
free(cwd_a);
|
||||
#endif
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
FILE *plFileSystem::Open(const plFileName &filename, const char *mode)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
wchar_t wmode[8];
|
||||
size_t mlen = strlen(mode);
|
||||
hsAssert(mlen < arrsize(wmode), "Mode string too long");
|
||||
|
||||
// Quick and dirty, because mode should only ever be ANSI chars
|
||||
for (size_t i = 0; i < mlen; ++i) {
|
||||
hsAssert(!(mode[i] & 0x80), "I SAID mode should ONLY ever be ANSI chars!");
|
||||
wmode[i] = static_cast<wchar_t>(mode[i]);
|
||||
}
|
||||
wmode[mlen] = 0;
|
||||
|
||||
return _wfopen(filename.AsString().ToWchar(), wmode);
|
||||
#else
|
||||
return fopen(filename.AsString().c_str(), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileSystem::Unlink(const plFileName &filename)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return _wunlink(filename.AsString().ToWchar()) == 0;
|
||||
#else
|
||||
return unlink(filename.AsString().c_str()) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileSystem::Move(const plFileName &from, const plFileName &to)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return MoveFileW(from.AsString().ToWchar(), to.AsString().ToWchar());
|
||||
#else
|
||||
if (!Copy(from, to))
|
||||
return false;
|
||||
return Unlink(from);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileSystem::Copy(const plFileName &from, const plFileName &to)
|
||||
{
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return CopyFileW(from.AsString().ToWchar(), to.AsString().ToWchar(), FALSE);
|
||||
#else
|
||||
typedef std::unique_ptr<FILE, std::function<int (FILE *)>> _FileRef;
|
||||
|
||||
_FileRef ffrom(Open(from, "rb"), fclose);
|
||||
_FileRef fto(Open(to, "wb"), fclose);
|
||||
if (!ffrom.get() || !fto.get())
|
||||
return false;
|
||||
|
||||
size_t count;
|
||||
uint8_t buffer[4096];
|
||||
while (!feof(ffrom.get())) {
|
||||
count = fread(buffer, sizeof(uint8_t), arrsize(buffer), ffrom.get());
|
||||
if (ferror(ffrom.get()))
|
||||
return false;
|
||||
fwrite(data, sizeof(uint8_t), count, fto.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool plFileSystem::CreateDir(const plFileName &dir, bool checkParents)
|
||||
{
|
||||
if (checkParents) {
|
||||
plFileName parent = dir.StripFileName();
|
||||
if (parent.IsValid() && !plFileInfo(parent).Exists() && !CreateDir(parent, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plFileInfo(dir).Exists())
|
||||
return true;
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
return CreateDirectoryW(dir.AsString().ToWchar(), nullptr);
|
||||
#else
|
||||
return (mkdir(dir.AsString().c_str(), 0755) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
plFileName plFileSystem::GetUserDataPath()
|
||||
{
|
||||
static plFileName _userData;
|
||||
|
||||
if (!_userData.IsValid()) {
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
wchar_t path[MAX_PATH];
|
||||
if (!SHGetSpecialFolderPathW(NULL, path, CSIDL_LOCAL_APPDATA, TRUE))
|
||||
return "";
|
||||
|
||||
_userData = plFileName::Join(plString::FromWchar(path), plProduct::LongName());
|
||||
#else
|
||||
_userData = plFileName::Join(getenv("HOME"), "." + plProduct::LongName());
|
||||
#endif
|
||||
plFileSystem::CreateDir(_userData);
|
||||
}
|
||||
|
||||
return _userData;
|
||||
}
|
||||
|
||||
plFileName plFileSystem::GetInitPath()
|
||||
{
|
||||
static plFileName _initPath = plFileName::Join(GetUserDataPath(), "Init");
|
||||
plFileSystem::CreateDir(_initPath);
|
||||
return _initPath;
|
||||
}
|
||||
|
||||
plFileName plFileSystem::GetLogPath()
|
||||
{
|
||||
static plFileName _logPath = plFileName::Join(GetUserDataPath(), "Log");
|
||||
plFileSystem::CreateDir(_logPath);
|
||||
return _logPath;
|
||||
}
|
284
Sources/Plasma/CoreLib/plFileSystem.h
Normal file
284
Sources/Plasma/CoreLib/plFileSystem.h
Normal file
@ -0,0 +1,284 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plFileSystem_Defined
|
||||
#define plFileSystem_Defined
|
||||
|
||||
#include "plString.h"
|
||||
#include <cstdio>
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
# define PATH_SEPARATOR '\\'
|
||||
# define PATH_SEPARATOR_STR "\\"
|
||||
#else
|
||||
# define PATH_SEPARATOR '/'
|
||||
# define PATH_SEPARATOR_STR "/"
|
||||
#endif
|
||||
|
||||
/** Represents a filename or path, including utilities for manipulating,
|
||||
* splitting, and joining path components.
|
||||
* \sa plFileInfo
|
||||
*/
|
||||
class plFileName
|
||||
{
|
||||
public:
|
||||
/** Construct an empty filename. */
|
||||
plFileName() { }
|
||||
|
||||
/** Construct a filename from the UTF-8 character data in \a cstr. */
|
||||
plFileName(const char *cstr) : fName(cstr) { }
|
||||
|
||||
/** Construct a filename from the plString argument \a copy. */
|
||||
plFileName(const plString ©) : fName(copy) { }
|
||||
|
||||
/** Copy constructor. */
|
||||
plFileName(const plFileName ©) : fName(copy.fName) { }
|
||||
|
||||
/** Assignment operator. Same as plFileName(const char *). */
|
||||
plFileName &operator=(const char *cstr)
|
||||
{
|
||||
fName.operator=(cstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assignment operator. Same as plFileName(const plString &). */
|
||||
plFileName &operator=(const plString ©)
|
||||
{
|
||||
fName.operator=(copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assignment operator. Same as plFileName(const plFileName &). */
|
||||
plFileName &operator=(const plFileName ©)
|
||||
{
|
||||
fName.operator=(copy.fName);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Comparison operator. */
|
||||
bool operator==(const char *other) const { return fName.operator==(other); }
|
||||
|
||||
/** Comparison operator. */
|
||||
bool operator==(const plFileName &other) const { return fName.operator==(other.fName); }
|
||||
|
||||
/** Inverse of operator==(const char *other) const. */
|
||||
bool operator!=(const char *other) const { return fName.operator!=(other); }
|
||||
|
||||
/** Inverse of operator==(const plFileName &other) const. */
|
||||
bool operator!=(const plFileName &other) const { return fName.operator!=(other.fName); }
|
||||
|
||||
/** Operator overload for use in containers which depend on \c std::less. */
|
||||
bool operator<(const plFileName &other) const { return fName.Compare(other.fName) < 0; }
|
||||
|
||||
/** Functor which compares two filenames case-insensitively for sorting. */
|
||||
struct less_i
|
||||
{
|
||||
bool operator()(const plFileName &_L, const plFileName &_R) const
|
||||
{ return _L.fName.Compare(_R.fName, plString::kCaseInsensitive) < 0; }
|
||||
};
|
||||
|
||||
/** Return whether this filename is valid (not empty). */
|
||||
bool IsValid() const { return !fName.IsEmpty(); }
|
||||
|
||||
/** Return the length of the filename string (UTF-8). */
|
||||
size_t GetSize() const { return fName.GetSize(); }
|
||||
|
||||
/** Convert the filename to a string. This does not resolve relative
|
||||
* paths or normalize slashes, it just returns the stored name string.
|
||||
*/
|
||||
const plString &AsString() const { return fName; }
|
||||
|
||||
/** Return the name portion of the path (including extension).
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "Filename.ext"</pre>
|
||||
*/
|
||||
plString GetFileName() const;
|
||||
|
||||
/** Return the file extension from the filename.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "ext"</pre>
|
||||
*/
|
||||
plString GetFileExt() const;
|
||||
|
||||
/** Return the name portion of the path, excluding its extension.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "Filename"</pre>
|
||||
*/
|
||||
plString GetFileNameNoExt() const;
|
||||
|
||||
/** Return the path with the filename portion stripped off.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "C:\\Path"</pre>
|
||||
*/
|
||||
plFileName StripFileName() const;
|
||||
|
||||
/** Return the filename with the extension stripped off.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "C:\\Path\\Filename"</pre>
|
||||
*/
|
||||
plFileName StripFileExt() const;
|
||||
|
||||
/** Normalize slashes to a particular format. By default, we use the
|
||||
* OS's native slash format.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path/Filename.ext").Normalize('\\') => "C:\\Path\\Filename.ext"</pre>
|
||||
*/
|
||||
plFileName Normalize(char slash = PATH_SEPARATOR) const;
|
||||
|
||||
/** Expand relative filenames and ./.. pieces to an absolute path. */
|
||||
plFileName AbsolutePath() const;
|
||||
|
||||
/** Join two path components together with the correct path separator.
|
||||
* For example:
|
||||
* <pre>plFileName::Join("C:\\Path", "Filename.ext") => "C:\\Path\\Filename.ext"</pre>
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path);
|
||||
|
||||
/** Join three path components together with the correct path separator.
|
||||
* \todo Make this more efficient.
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path,
|
||||
const plFileName& path2)
|
||||
{ return Join(Join(base, path), path2); }
|
||||
|
||||
/** Join four path components together with the correct path separator.
|
||||
* \todo Make this more efficient.
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path,
|
||||
const plFileName& path2, const plFileName &path3)
|
||||
{ return Join(Join(Join(base, path), path2), path3); }
|
||||
|
||||
private:
|
||||
plString fName;
|
||||
};
|
||||
|
||||
|
||||
/** Structure to get information about a file by name.
|
||||
* \sa plFileName
|
||||
*/
|
||||
class plFileInfo
|
||||
{
|
||||
public:
|
||||
/** Construct an invalid plFileInfo which points to no file. */
|
||||
plFileInfo()
|
||||
: fFileSize(-1), fCreateTime(), fModifyTime(), fFlags() { }
|
||||
|
||||
/** Construct a plFileInfo and fill it with info about the specified
|
||||
* file, if it exists.
|
||||
*/
|
||||
explicit plFileInfo(const plFileName &filename);
|
||||
|
||||
/** Retrieve the filename associated with this info structure. */
|
||||
const plFileName &FileName() const { return fName; }
|
||||
|
||||
/** Return whether the plFileInfo has been initialized. */
|
||||
bool IsValid() const { return fName.IsValid(); }
|
||||
|
||||
/** Determine whether the file exists on the filesystem. */
|
||||
bool Exists() const { return (fFlags & kEntryExists); }
|
||||
|
||||
/** Returns the size of the file on the disk, in bytes. */
|
||||
int64_t FileSize() const { return fFileSize; }
|
||||
|
||||
/** Returns the creation time of the file. */
|
||||
uint64_t CreateTime() const { return fCreateTime; }
|
||||
|
||||
/** Returns the last modification time of the file. */
|
||||
uint64_t ModifyTime() const { return fModifyTime; }
|
||||
|
||||
/** Returns \p true if this file is a directory. */
|
||||
bool IsDirectory() const { return (fFlags & kIsDirectory); }
|
||||
|
||||
/** Returns \p true if this file is a regular file. */
|
||||
bool IsFile() const { return (fFlags & kIsNormalFile); }
|
||||
|
||||
private:
|
||||
plFileName fName;
|
||||
int64_t fFileSize;
|
||||
uint64_t fCreateTime, fModifyTime;
|
||||
|
||||
enum {
|
||||
kEntryExists = (1<<0),
|
||||
kIsDirectory = (1<<1),
|
||||
kIsNormalFile = (1<<2),
|
||||
};
|
||||
uint32_t fFlags;
|
||||
};
|
||||
|
||||
|
||||
namespace plFileSystem
|
||||
{
|
||||
/** Get the current working directory of the application. */
|
||||
plFileName GetCWD();
|
||||
|
||||
/** Open a file using the correct platform fopen API. */
|
||||
FILE *Open(const plFileName &filename, const char *mode);
|
||||
|
||||
/** Delete a file from the filesystem. */
|
||||
bool Unlink(const plFileName &filename);
|
||||
|
||||
/** Move or rename a file. */
|
||||
bool Move(const plFileName &from, const plFileName &to);
|
||||
|
||||
/** Copy a file to a new location. */
|
||||
bool Copy(const plFileName &from, const plFileName &to);
|
||||
|
||||
/** Create a directory. If \a checkParents is \p true, this will also
|
||||
* check the whole path and create any parent directories as needed.
|
||||
*/
|
||||
bool CreateDir(const plFileName &dir, bool checkParents = false);
|
||||
|
||||
/** Get the User's data directory. If it doesn't exist, this will
|
||||
* create it.
|
||||
*/
|
||||
plFileName GetUserDataPath();
|
||||
|
||||
/** Get the Init script direcotory. If it doesn't exist, this will
|
||||
* create it. */
|
||||
plFileName GetInitPath();
|
||||
|
||||
/** Get the Log output directory. If it doesn't exist, this will
|
||||
* create it. */
|
||||
plFileName GetLogPath();
|
||||
}
|
||||
|
||||
#endif // plFileSystem_Defined
|
@ -877,110 +877,3 @@ size_t ustrlen(const UniChar *ustr, size_t max)
|
||||
;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/* plFileName */
|
||||
static_assert(sizeof(plFileName) == sizeof(plString),
|
||||
"plFileName should be a thin wrapper around plString");
|
||||
|
||||
plString plFileName::GetFileName() const
|
||||
{
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
if (end < 0)
|
||||
return fName;
|
||||
|
||||
return fName.Substr(end + 1);
|
||||
}
|
||||
|
||||
plString plFileName::GetFileExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
if (dot > end)
|
||||
return fName.Substr(dot + 1);
|
||||
|
||||
return plString::Null;
|
||||
}
|
||||
|
||||
plString plFileName::GetFileNameNoExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
if (dot > end)
|
||||
return fName.Substr(end + 1, dot - end - 1);
|
||||
return fName.Substr(end + 1);
|
||||
}
|
||||
|
||||
plFileName plFileName::StripFileName() const
|
||||
{
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
if (end < 0)
|
||||
return *this;
|
||||
|
||||
return fName.Left(end);
|
||||
}
|
||||
|
||||
plFileName plFileName::StripFileExt() const
|
||||
{
|
||||
int dot = fName.FindLast('.');
|
||||
|
||||
// Be sure not to get a dot in the directory!
|
||||
int end = fName.FindLast('/');
|
||||
if (end < 0)
|
||||
end = fName.FindLast('\\');
|
||||
|
||||
if (dot > end)
|
||||
return fName.Left(dot);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
plFileName plFileName::Normalize(char slash) const
|
||||
{
|
||||
plStringBuffer<char> norm;
|
||||
char *norm_p = norm.CreateWritableBuffer(fName.GetSize());
|
||||
for (const char *p = fName.c_str(); *p; ++p) {
|
||||
if (*p == '/' || *p == '\\')
|
||||
*norm_p++ = slash;
|
||||
else
|
||||
*norm_p++ = *p;
|
||||
}
|
||||
*norm_p = 0;
|
||||
return plString(norm);
|
||||
}
|
||||
|
||||
plFileName plFileName::Join(const plFileName &base, const plFileName &path)
|
||||
{
|
||||
if (!base.IsValid())
|
||||
return path;
|
||||
if (!path.IsValid())
|
||||
return base;
|
||||
|
||||
char last = base.fName.CharAt(base.GetSize() - 1);
|
||||
char first = path.fName.CharAt(0);
|
||||
if (last != '/' && last != '\\') {
|
||||
if (first != '/' && first != '\\') {
|
||||
return plString::Format("%s" PATH_SEPARATOR_STR "%s",
|
||||
base.fName.c_str(), path.fName.c_str());
|
||||
}
|
||||
return base.fName + path.fName;
|
||||
} else if (first != '/' && first != '\\') {
|
||||
return base.fName + path.fName;
|
||||
}
|
||||
// Both have a slash, but we only need one
|
||||
return base.fName + path.fName.Substr(1);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ public:
|
||||
* \note This constructor expects the input to be UTF-8 encoded. For
|
||||
* conversion from ISO-8859-1 8-bit data, use FromIso8859_1().
|
||||
*/
|
||||
plString(const char *cstr) { IConvertFromUtf8(cstr, kSizeAuto); }
|
||||
plString(const char *cstr, size_t size = kSizeAuto) { IConvertFromUtf8(cstr, size); }
|
||||
|
||||
/** Copy constructor. */
|
||||
plString(const plString ©) : fUtf8Buffer(copy.fUtf8Buffer) { }
|
||||
@ -539,13 +539,6 @@ public:
|
||||
static plString Fill(size_t count, char c);
|
||||
|
||||
public:
|
||||
/** Functor which compares two strings case-sensitively for sorting. */
|
||||
struct less
|
||||
{
|
||||
bool operator()(const plString &_L, const plString &_R) const
|
||||
{ return _L.Compare(_R, kCaseSensitive) < 0; }
|
||||
};
|
||||
|
||||
/** Functor which compares two strings case-insensitively for sorting. */
|
||||
struct less_i
|
||||
{
|
||||
@ -553,13 +546,6 @@ public:
|
||||
{ return _L.Compare(_R, kCaseInsensitive) < 0; }
|
||||
};
|
||||
|
||||
/** Functor which compares two strings case-sensitively for equality. */
|
||||
struct equal
|
||||
{
|
||||
bool operator()(const plString &_L, const plString &_R) const
|
||||
{ return _L.Compare(_R, kCaseSensitive) == 0; }
|
||||
};
|
||||
|
||||
/** Functor which compares two strings case-insensitively for equality. */
|
||||
struct equal_i
|
||||
{
|
||||
@ -660,124 +646,4 @@ private:
|
||||
/** \p strlen implementation for UniChar based C-style string buffers. */
|
||||
size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto);
|
||||
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
# define PATH_SEPARATOR '\\'
|
||||
# define PATH_SEPARATOR_STR "\\"
|
||||
#else
|
||||
# define PATH_SEPARATOR '/'
|
||||
# define PATH_SEPARATOR_STR "/"
|
||||
#endif
|
||||
|
||||
/** Subclass of plString with specific methods to help deal with common
|
||||
* filename manipulation tasks.
|
||||
*/
|
||||
class plFileName
|
||||
{
|
||||
public:
|
||||
/** Construct an empty filename. */
|
||||
plFileName() { }
|
||||
|
||||
/** Construct a filename from the UTF-8 character data in \a cstr. */
|
||||
plFileName(const char *cstr) : fName(cstr) { }
|
||||
|
||||
/** Construct a filename from the plString argument \a copy. */
|
||||
plFileName(const plString ©) : fName(copy) { }
|
||||
|
||||
/** Copy constructor. */
|
||||
plFileName(const plFileName ©) : fName(copy.fName) { }
|
||||
|
||||
/** Assignment operator. Same as plFileName(const char *). */
|
||||
plFileName &operator=(const char *cstr)
|
||||
{
|
||||
fName.operator=(cstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assignment operator. Same as plFileName(const plString &). */
|
||||
plFileName &operator=(const plString ©)
|
||||
{
|
||||
fName.operator=(copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assignment operator. Same as plFileName(const plFileName &). */
|
||||
plFileName &operator=(const plFileName ©)
|
||||
{
|
||||
fName.operator=(copy.fName);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Return whether this filename is valid (not empty). */
|
||||
bool IsValid() const { return !fName.IsEmpty(); }
|
||||
|
||||
/** Return the length of the filename string (UTF-8). */
|
||||
size_t GetSize() const { return fName.GetSize(); }
|
||||
|
||||
/** Convert the filename to a string. This does not resolve relative
|
||||
* paths or normalize slashes, it just returns the stored name string.
|
||||
*/
|
||||
const plString &AsString() const { return fName; }
|
||||
|
||||
/** Return the name portion of the path (including extension).
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "Filename.ext"</pre>
|
||||
*/
|
||||
plString GetFileName() const;
|
||||
|
||||
/** Return the file extension from the filename.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "ext"</pre>
|
||||
*/
|
||||
plString GetFileExt() const;
|
||||
|
||||
/** Return the name portion of the path, excluding its extension.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "Filename"</pre>
|
||||
*/
|
||||
plString GetFileNameNoExt() const;
|
||||
|
||||
/** Return the path with the filename portion stripped off.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "C:\\Path"</pre>
|
||||
*/
|
||||
plFileName StripFileName() const;
|
||||
|
||||
/** Return the filename with the extension stripped off.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path\\Filename.ext") => "C:\\Path\\Filename"</pre>
|
||||
*/
|
||||
plFileName StripFileExt() const;
|
||||
|
||||
/** Normalize slashes to a particular format. By default, we use the
|
||||
* OS's native slash format.
|
||||
* For example:
|
||||
* <pre>plFileName("C:\\Path/Filename.ext").Normalize("\\") => "C:\\Path\\Filename.ext"</pre>
|
||||
*/
|
||||
plFileName Normalize(char slash = PATH_SEPARATOR) const;
|
||||
|
||||
/** Join two path components together with the correct path separator.
|
||||
* For example:
|
||||
* <pre>plFileName::Join("C:\\Path", "Filename.ext") => "C:\\Path\\Filename.ext"</pre>
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path);
|
||||
|
||||
/** Join three path components together with the correct path separator.
|
||||
* \todo Make this more efficient.
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path,
|
||||
const plFileName& path2)
|
||||
{ return Join(Join(base, path), path2); }
|
||||
|
||||
/** Join four path components together with the correct path separator.
|
||||
* \todo Make this more efficient.
|
||||
*/
|
||||
static plFileName Join(const plFileName &base, const plFileName &path,
|
||||
const plFileName& path2, const plFileName &path3)
|
||||
{ return Join(Join(Join(base, path), path2), path3); }
|
||||
|
||||
private:
|
||||
plString fName;
|
||||
};
|
||||
|
||||
#endif //plString_Defined
|
||||
|
Reference in New Issue
Block a user