Update release

This commit is contained in:
vczh
2025-08-31 22:44:06 -07:00
parent 9c91710e2d
commit 3f0e43b724
19 changed files with 1447 additions and 865 deletions
+184 -171
View File
@@ -24,151 +24,194 @@ static_assert(false, "Do not build this file for non-Windows applications.");
namespace vl
{
namespace stream
{
extern Ptr<IFileStreamImpl> CreateOSFileStreamImpl(const WString& fileName, FileStream::AccessRight accessRight);
}
namespace filesystem
{
using namespace collections;
using namespace stream;
/***********************************************************************
FilePath
WindowsFileSystemImpl
***********************************************************************/
void FilePath::Initialize()
class WindowsFileSystemImpl : public Object, public virtual IFileSystemImpl
{
public:
void Initialize(WString& fullPath) const override
{
Array<wchar_t> buffer(fullPath.Length() + 1);
wcscpy_s(&buffer[0], fullPath.Length() + 1, fullPath.Buffer());
NormalizeDelimiters(buffer);
fullPath = &buffer[0];
{
Array<wchar_t> buffer(fullPath.Length() + 1);
wcscpy_s(&buffer[0], fullPath.Length() + 1, fullPath.Buffer());
FilePath::NormalizeDelimiters(buffer);
fullPath = &buffer[0];
}
if (fullPath != L"")
{
if (fullPath.Length() < 2 || fullPath[1] != L':')
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"Failed to call GetCurrentDirectory.", L"vl::filesystem::FilePath::Initialize", L"");
}
fullPath = WString(buffer) + L"\\" + fullPath;
}
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
if (fullPath.Length() == 2 && fullPath[1] == L':')
{
fullPath += L"\\";
}
auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"The path is illegal.", L"vl::filesystem::FilePath::FilePath", L"_filePath");
}
{
wchar_t shortPath[MAX_PATH + 1];
wchar_t longPath[MAX_PATH + 1];
if (GetShortPathName(buffer, shortPath, MAX_PATH) > 0)
{
if (GetLongPathName(shortPath, longPath, MAX_PATH) > 0)
{
memcpy(buffer, longPath, sizeof(buffer));
}
}
}
fullPath = buffer;
}
}
FilePath::TrimLastDelimiter(fullPath);
}
if (fullPath != L"")
bool IsFile(const WString& fullPath) const override
{
if (fullPath.Length() < 2 || fullPath[1] != L':')
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"Failed to call GetCurrentDirectory.", L"vl::filesystem::FilePath::Initialize", L"");
}
fullPath = WString(buffer) + L"\\" + fullPath;
}
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
if (fullPath.Length() == 2 && fullPath[1] == L':')
{
fullPath += L"\\";
}
auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL);
if (result > MAX_PATH + 1 || result == 0)
{
throw ArgumentException(L"The path is illegal.", L"vl::filesystem::FilePath::FilePath", L"_filePath");
}
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
bool IsFolder(const WString& fullPath) const override
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
bool IsRoot(const WString& fullPath) const override
{
return fullPath == L"";
}
WString GetRelativePathFor(const WString& fromPath, const WString& toPath) const override
{
if (fromPath.Length() == 0 || toPath.Length() == 0 || fromPath[0] != toPath[0])
{
return toPath;
}
wchar_t buffer[MAX_PATH + 1] = { 0 };
PathRelativePathTo(
buffer,
fromPath.Buffer(),
(IsFolder(fromPath) ? FILE_ATTRIBUTE_DIRECTORY : 0),
toPath.Buffer(),
(IsFolder(toPath) ? FILE_ATTRIBUTE_DIRECTORY : 0)
);
return buffer;
}
bool FileDelete(const FilePath& filePath) const override
{
return DeleteFile(filePath.GetFullPath().Buffer()) != 0;
}
bool FileRename(const FilePath& filePath, const WString& newName) const override
{
WString oldFileName = filePath.GetFullPath();
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
bool GetFolders(const FilePath& folderPath, collections::List<Folder>& folders) const override
{
if (folderPath.IsRoot())
{
auto bufferSize = GetLogicalDriveStrings(0, nullptr);
if (bufferSize > 0)
{
wchar_t shortPath[MAX_PATH + 1];
wchar_t longPath[MAX_PATH + 1];
if (GetShortPathName(buffer, shortPath, MAX_PATH) > 0)
Array<wchar_t> buffer(bufferSize);
if (GetLogicalDriveStrings((DWORD)buffer.Count(), &buffer[0]) > 0)
{
if (GetLongPathName(shortPath, longPath, MAX_PATH) > 0)
auto begin = &buffer[0];
auto end = begin + buffer.Count();
while (begin < end && *begin)
{
memcpy(buffer, longPath, sizeof(buffer));
WString driveString = begin;
begin += driveString.Length() + 1;
folders.Add(Folder(FilePath(driveString)));
}
return true;
}
}
return false;
}
else
{
if (!IsFolder(folderPath.GetFullPath())) return false;
WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while (true)
{
if (findHandle == INVALID_HANDLE_VALUE)
{
WString searchPath = (folderPath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
break;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
if (result == 0)
{
FindClose(findHandle);
break;
}
}
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (wcscmp(findData.cFileName, L".") != 0 && wcscmp(findData.cFileName, L"..") != 0)
{
folders.Add(Folder(folderPath / findData.cFileName));
}
}
}
fullPath = buffer;
return true;
}
}
TrimLastDelimiter(fullPath);
}
bool FilePath::IsFile()const
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
}
bool FilePath::IsFolder()const
{
WIN32_FILE_ATTRIBUTE_DATA info;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if (!result) return false;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
bool FilePath::IsRoot()const
{
return fullPath == L"";
}
WString FilePath::GetRelativePathFor(const FilePath& _filePath) const
{
if (fullPath.Length() == 0 || _filePath.fullPath.Length() == 0 || fullPath[0] != _filePath.fullPath[0])
bool GetFiles(const FilePath& folderPath, collections::List<File>& files) const override
{
return _filePath.fullPath;
}
wchar_t buffer[MAX_PATH + 1] = { 0 };
PathRelativePathTo(
buffer,
fullPath.Buffer(),
(IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0),
_filePath.fullPath.Buffer(),
(_filePath.IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0)
);
return buffer;
}
/***********************************************************************
File
***********************************************************************/
bool File::Delete()const
{
return DeleteFile(filePath.GetFullPath().Buffer()) != 0;
}
bool File::Rename(const WString& newName)const
{
WString oldFileName = filePath.GetFullPath();
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
/***********************************************************************
Folder
***********************************************************************/
bool Folder::GetFolders(collections::List<Folder>& folders)const
{
if (filePath.IsRoot())
{
auto bufferSize = GetLogicalDriveStrings(0, nullptr);
if (bufferSize > 0)
if (IsRoot(folderPath.GetFullPath()))
{
Array<wchar_t> buffer(bufferSize);
if (GetLogicalDriveStrings((DWORD)buffer.Count(), &buffer[0]) > 0)
{
auto begin = &buffer[0];
auto end = begin + buffer.Count();
while (begin < end && *begin)
{
WString driveString = begin;
begin += driveString.Length() + 1;
folders.Add(Folder(FilePath(driveString)));
}
return true;
}
return true;
}
return false;
}
else
{
if (!Exists()) return false;
if (!IsFolder(folderPath.GetFullPath())) return false;
WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE;
@@ -176,7 +219,7 @@ Folder
{
if (findHandle == INVALID_HANDLE_VALUE)
{
WString searchPath = (filePath / L"*").GetFullPath();
WString searchPath = (folderPath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
@@ -193,72 +236,42 @@ Folder
}
}
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
if (wcscmp(findData.cFileName, L".") != 0 && wcscmp(findData.cFileName, L"..") != 0)
{
folders.Add(Folder(filePath / findData.cFileName));
}
files.Add(File(folderPath / findData.cFileName));
}
}
return true;
}
}
bool Folder::GetFiles(collections::List<File>& files)const
{
if (filePath.IsRoot())
bool CreateFolder(const FilePath& folderPath) const override
{
return true;
return CreateDirectory(folderPath.GetFullPath().Buffer(), NULL) != 0;
}
if (!Exists()) return false;
WIN32_FIND_DATA findData;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while (true)
bool DeleteFolder(const FilePath& folderPath) const override
{
if (findHandle == INVALID_HANDLE_VALUE)
{
WString searchPath = (filePath / L"*").GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
break;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
if (result == 0)
{
FindClose(findHandle);
break;
}
}
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
files.Add(File(filePath / findData.cFileName));
}
return RemoveDirectory(folderPath.GetFullPath().Buffer()) != 0;
}
return true;
}
bool Folder::CreateNonRecursively()const
{
return CreateDirectory(filePath.GetFullPath().Buffer(), NULL) != 0;
}
bool FolderRename(const FilePath& folderPath, const WString& newName) const override
{
WString oldFileName = folderPath.GetFullPath();
WString newFileName = (folderPath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
}
bool Folder::DeleteNonRecursively()const
{
return RemoveDirectory(filePath.GetFullPath().Buffer()) != 0;
}
Ptr<stream::IFileStreamImpl> GetFileStreamImpl(const WString& fileName, stream::FileStream::AccessRight accessRight) const override
{
return stream::CreateOSFileStreamImpl(fileName, accessRight);
}
};
bool Folder::Rename(const WString& newName)const
WindowsFileSystemImpl osFileSystemImpl;
IFileSystemImpl* GetOSFileSystemImpl()
{
WString oldFileName = filePath.GetFullPath();
WString newFileName = (filePath.GetFolder() / newName).GetFullPath();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
return &osFileSystemImpl;
}
}
}