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
|
hsThread.cpp
|
||||||
hsWide.cpp
|
hsWide.cpp
|
||||||
pcSmallRect.cpp
|
pcSmallRect.cpp
|
||||||
|
plFileSystem.cpp
|
||||||
plGeneric.cpp
|
plGeneric.cpp
|
||||||
plLoadMask.cpp
|
plLoadMask.cpp
|
||||||
plProduct.cpp
|
plProduct.cpp
|
||||||
@ -85,6 +86,7 @@ set(CoreLib_HEADERS
|
|||||||
hsWide.h
|
hsWide.h
|
||||||
hsWindows.h
|
hsWindows.h
|
||||||
pcSmallRect.h
|
pcSmallRect.h
|
||||||
|
plFileSystem.h
|
||||||
plGeneric.h
|
plGeneric.h
|
||||||
plLoadMask.h
|
plLoadMask.h
|
||||||
plProduct.h
|
plProduct.h
|
||||||
|
@ -46,7 +46,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|||||||
|
|
||||||
#include "HeadSpin.h"
|
#include "HeadSpin.h"
|
||||||
#include "hsMemory.h"
|
#include "hsMemory.h"
|
||||||
#include "plString.h"
|
#include "plFileSystem.h"
|
||||||
|
|
||||||
|
|
||||||
// Define this for use of Streams with Logging (commonly used w/ a packet sniffer)
|
// 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;
|
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
|
* \note This constructor expects the input to be UTF-8 encoded. For
|
||||||
* conversion from ISO-8859-1 8-bit data, use FromIso8859_1().
|
* 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. */
|
/** Copy constructor. */
|
||||||
plString(const plString ©) : fUtf8Buffer(copy.fUtf8Buffer) { }
|
plString(const plString ©) : fUtf8Buffer(copy.fUtf8Buffer) { }
|
||||||
@ -539,13 +539,6 @@ public:
|
|||||||
static plString Fill(size_t count, char c);
|
static plString Fill(size_t count, char c);
|
||||||
|
|
||||||
public:
|
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. */
|
/** Functor which compares two strings case-insensitively for sorting. */
|
||||||
struct less_i
|
struct less_i
|
||||||
{
|
{
|
||||||
@ -553,13 +546,6 @@ public:
|
|||||||
{ return _L.Compare(_R, kCaseInsensitive) < 0; }
|
{ 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. */
|
/** Functor which compares two strings case-insensitively for equality. */
|
||||||
struct equal_i
|
struct equal_i
|
||||||
{
|
{
|
||||||
@ -660,124 +646,4 @@ private:
|
|||||||
/** \p strlen implementation for UniChar based C-style string buffers. */
|
/** \p strlen implementation for UniChar based C-style string buffers. */
|
||||||
size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto);
|
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
|
#endif //plString_Defined
|
||||||
|
Reference in New Issue
Block a user