mirror of
https://git.tesses.org/tesses50/tessesframework.git
synced 2026-08-01 16:15:31 +00:00
626 lines
19 KiB
C++
626 lines
19 KiB
C++
/*
|
|
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
|
https://git.tesses.org/tesses50/crosslang
|
|
|
|
Copyright (C) 2026 Mike Nolan
|
|
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
|
|
|
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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "TessesFramework/Filesystem/VFS.hpp"
|
|
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
|
#include "TessesFramework/Http/HttpUtils.hpp"
|
|
#include <TessesFramework/Filesystem/FSHelpers.hpp>
|
|
namespace Tesses::Framework::Filesystem {
|
|
VFSPathEnumeratorItterator::VFSPathEnumeratorItterator() {
|
|
this->enumerator = nullptr;
|
|
}
|
|
VFSPathEnumeratorItterator::VFSPathEnumeratorItterator(
|
|
VFSPathEnumerator *enumerator) {
|
|
this->enumerator = enumerator;
|
|
}
|
|
VFSPathEnumeratorItterator &VFSPathEnumeratorItterator::operator++(int) {
|
|
enumerator->MoveNext();
|
|
return *this;
|
|
}
|
|
VFSPathEnumeratorItterator &VFSPathEnumeratorItterator::operator++() {
|
|
enumerator->MoveNext();
|
|
return *this;
|
|
}
|
|
|
|
VFSPath &VFSPathEnumeratorItterator::operator*() {
|
|
std::filesystem::directory_iterator i;
|
|
|
|
if (enumerator != nullptr)
|
|
return enumerator->Current;
|
|
return this->e;
|
|
}
|
|
VFSPath *VFSPathEnumeratorItterator::operator->() {
|
|
if (enumerator != nullptr)
|
|
return &enumerator->Current;
|
|
return nullptr;
|
|
}
|
|
bool VFSPathEnumeratorItterator::operator!=(VFSPathEnumeratorItterator right) {
|
|
if (enumerator == right.enumerator) {
|
|
return false;
|
|
}
|
|
if (right.enumerator == nullptr) {
|
|
auto r = !enumerator->IsDone();
|
|
|
|
return r;
|
|
}
|
|
return true;
|
|
}
|
|
bool VFSPathEnumeratorItterator::operator==(VFSPathEnumeratorItterator right) {
|
|
if (enumerator == right.enumerator) {
|
|
return true;
|
|
}
|
|
if (right.enumerator == nullptr)
|
|
return enumerator->IsDone();
|
|
return false;
|
|
}
|
|
VFSPathEnumerator::VFSPathEnumerator() { data = nullptr; }
|
|
VFSPathEnumerator *VFSPathEnumerator::MakePointer() {
|
|
VFSPathEnumerator *enumerator = new VFSPathEnumerator();
|
|
enumerator->Current = Current;
|
|
enumerator->data = data;
|
|
return enumerator;
|
|
}
|
|
VFSPathEnumerator::VFSPathEnumerator(std::function<bool(VFSPath &)> moveNext,
|
|
std::function<void()> destroy) {
|
|
data = std::make_shared<VFSPathEnumeratorData>(moveNext, destroy);
|
|
}
|
|
bool VFSPathEnumerator::MoveNext() {
|
|
if (this->data) {
|
|
auto r = data->moveNext(Current);
|
|
if (!r)
|
|
data->eof = true;
|
|
return r;
|
|
}
|
|
return false;
|
|
}
|
|
bool VFSPathEnumerator::IsDone() {
|
|
|
|
if (this->data) {
|
|
return data->eof;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
VFSPathEnumeratorItterator VFSPathEnumerator::begin() {
|
|
MoveNext();
|
|
VFSPathEnumeratorItterator ittr(this);
|
|
return ittr;
|
|
}
|
|
|
|
VFSPathEnumeratorItterator VFSPathEnumerator::end() {
|
|
return VFSPathEnumeratorItterator();
|
|
}
|
|
VFSPath operator/(VFSPath p, VFSPath p2) { return VFSPath(p, p2); }
|
|
VFSPath operator/(VFSPath p, std::string p2) { return VFSPath(p, p2); }
|
|
VFSPath operator/(std::string p, VFSPath p2) { return VFSPath(p, p2); }
|
|
VFSPath operator+(VFSPath p, VFSPath p2) {
|
|
VFSPath pout;
|
|
pout.relative = p.relative;
|
|
if (p.path.size() > 1) {
|
|
pout.path.insert(pout.path.end(), p.path.begin(), p.path.end() - 1);
|
|
}
|
|
std::string mid = {};
|
|
if (!p.path.empty()) {
|
|
mid.append(p.path.back());
|
|
}
|
|
|
|
if (!p2.path.empty()) {
|
|
mid.append(p2.path.front());
|
|
}
|
|
pout.path.push_back(mid);
|
|
|
|
if (p2.path.size() > 1) {
|
|
pout.path.insert(pout.path.end(), p2.path.begin() + 1, p2.path.end());
|
|
}
|
|
|
|
return pout;
|
|
}
|
|
VFSPath operator+(VFSPath p, std::string p2) { return p + VFSPath(p2); }
|
|
VFSPath operator+(std::string p, VFSPath p2) { return VFSPath(p) + p2; }
|
|
bool operator==(VFSPath p, VFSPath p2) {
|
|
if (p.relative != p2.relative)
|
|
return false;
|
|
if (p.path.size() != p2.path.size())
|
|
return false;
|
|
for (size_t i = 0; i < p.path.size(); i++)
|
|
if (p.path[i] != p2.path[i])
|
|
return false;
|
|
return true;
|
|
}
|
|
bool operator!=(VFSPath p, VFSPath p2) {
|
|
if (p.relative != p2.relative)
|
|
return true;
|
|
if (p.path.size() != p2.path.size())
|
|
return true;
|
|
for (size_t i = 0; i < p.path.size(); i++)
|
|
if (p.path[i] != p2.path[i])
|
|
return true;
|
|
return false;
|
|
}
|
|
bool operator==(std::string p, VFSPath p2) { return VFSPath(p) == p2; }
|
|
bool operator!=(std::string p, VFSPath p2) { return VFSPath(p) != p2; }
|
|
bool operator==(VFSPath p, std::string p2) { return p == VFSPath(p2); }
|
|
bool operator!=(VFSPath p, std::string p2) { return p != VFSPath(p2); }
|
|
VFSPath VFS::ReadLink(VFSPath path) { return VFSPath("/"); }
|
|
VFSPath VFSPath::GetAbsoluteCurrentDirectory() {
|
|
auto p = std::filesystem::current_path();
|
|
return LocalFS->SystemToVFSPath(p.string());
|
|
}
|
|
void VFSPath::SetAbsoluteCurrentDirectory(VFSPath path) {
|
|
auto res = LocalFS->VFSPathToSystem(path);
|
|
std::filesystem::path mpath = res;
|
|
std::filesystem::current_path(mpath);
|
|
}
|
|
VFSPath VFSPath::MakeAbsolute() const {
|
|
return MakeAbsolute(GetAbsoluteCurrentDirectory());
|
|
}
|
|
VFSPath VFSPath::MakeAbsolute(VFSPath curDir) const {
|
|
if (!this->relative)
|
|
return *this;
|
|
VFSPath p2 = curDir / *this;
|
|
return p2.CollapseRelativeParents();
|
|
}
|
|
VFSPath VFSPath::MakeRelative() const {
|
|
return MakeRelative(GetAbsoluteCurrentDirectory());
|
|
}
|
|
FIFOCreationResult VFS::CreateFIFO(VFSPath path, uint32_t mode) {
|
|
return FIFOCreationResult::Unsupported;
|
|
}
|
|
bool VFS::DirectoryExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsDirectory();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::RegularFileExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsRegularFile();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::SymlinkExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsSymlink();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::CharacterDeviceExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsCharDevice();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::BlockDeviceExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsBlockDevice();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::SocketFileExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsSocket();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::FIFOFileExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsFIFO();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::FileExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return !data.IsDirectory();
|
|
}
|
|
return false;
|
|
}
|
|
bool VFS::SpecialFileExists(VFSPath path) {
|
|
StatData data;
|
|
if (this->Stat(path, data)) {
|
|
return data.IsSpecial();
|
|
}
|
|
return false;
|
|
}
|
|
VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const {
|
|
|
|
if (this->relative)
|
|
return *this;
|
|
|
|
size_t i;
|
|
size_t len = std::min(toMakeRelativeTo.path.size(), this->path.size());
|
|
for (i = 0; i < len; i++) {
|
|
if (this->path[i] != toMakeRelativeTo.path[i])
|
|
break;
|
|
}
|
|
|
|
if (i == this->path.size() - 1 && i == toMakeRelativeTo.path.size() - 1) {
|
|
std::vector<std::string> paths{this->path[this->path.size() - 1]};
|
|
VFSPath path(paths);
|
|
path.relative = true;
|
|
return path;
|
|
}
|
|
|
|
std::vector<std::string> parts(this->path.begin() + i, this->path.end());
|
|
|
|
if (i < toMakeRelativeTo.path.size()) {
|
|
for (; i < toMakeRelativeTo.path.size(); i++) {
|
|
parts.insert(parts.begin(), "..");
|
|
}
|
|
}
|
|
VFSPath p2(parts);
|
|
p2.relative = true;
|
|
return p2;
|
|
}
|
|
VFSPath VFSPath::CollapseRelativeParents() const {
|
|
std::vector<std::string> parts;
|
|
|
|
for (auto item : this->path) {
|
|
if (item == "..") {
|
|
if (!parts.empty()) {
|
|
parts.erase(parts.end() - 1);
|
|
}
|
|
} else if (item == ".") {
|
|
// do nothing but don't emit this
|
|
} else {
|
|
parts.push_back(item);
|
|
}
|
|
}
|
|
VFSPath newpath;
|
|
newpath.relative = relative;
|
|
newpath.path = parts;
|
|
return newpath;
|
|
}
|
|
VFSPath VFSPath::CurrentDirectoryAsRelative() {
|
|
VFSPath path;
|
|
path.relative = true;
|
|
return path;
|
|
}
|
|
|
|
std::vector<std::string> VFSPath::SplitPath(std::string path) {
|
|
std::vector<std::string> parts;
|
|
std::string curPath = {};
|
|
for (auto c : path) {
|
|
if (c == '/') {
|
|
if (!curPath.empty()) {
|
|
parts.push_back(curPath);
|
|
curPath = {};
|
|
}
|
|
}
|
|
#if defined(WIN32)
|
|
else if (c == '\\') {
|
|
if (!curPath.empty()) {
|
|
parts.push_back(curPath);
|
|
curPath = {};
|
|
}
|
|
}
|
|
#endif
|
|
else {
|
|
curPath.push_back(c);
|
|
}
|
|
}
|
|
if (!curPath.empty()) {
|
|
parts.push_back(curPath);
|
|
curPath = {};
|
|
}
|
|
|
|
return parts;
|
|
}
|
|
VFSPath::VFSPath() { this->relative = false; }
|
|
VFSPath::VFSPath(std::vector<std::string> p) { this->path = p; }
|
|
|
|
VFSPath VFSPath::ParseUriPath(std::string path) {
|
|
std::string builder = {};
|
|
VFSPath vpath;
|
|
vpath.relative = true;
|
|
|
|
if (!path.empty() && path[0] == '/')
|
|
vpath.relative = false;
|
|
|
|
for (auto item : path) {
|
|
if (item == '/') {
|
|
if (!builder.empty()) {
|
|
vpath.path.push_back(builder);
|
|
builder.clear();
|
|
}
|
|
} else {
|
|
builder.push_back(item);
|
|
}
|
|
}
|
|
if (!builder.empty()) {
|
|
vpath.path.push_back(builder);
|
|
}
|
|
return vpath;
|
|
}
|
|
|
|
bool VFSPath::HasExtension() const {
|
|
if (this->path.empty())
|
|
return false;
|
|
auto &str = this->path.back();
|
|
auto index = str.find_last_of('.');
|
|
if (index == std::string::npos)
|
|
return false;
|
|
return true;
|
|
}
|
|
std::string VFSPath::GetExtension() const {
|
|
if (this->path.empty())
|
|
return {};
|
|
auto &str = this->path.back();
|
|
auto index = str.find_last_of('.');
|
|
if (index == std::string::npos)
|
|
return {};
|
|
return str.substr(index);
|
|
}
|
|
void VFSPath::ChangeExtension(std::string ext) {
|
|
if (this->path.empty())
|
|
return;
|
|
auto &str = this->path.back();
|
|
auto index = str.find_last_of('.');
|
|
if (index != std::string::npos) {
|
|
str = str.substr(0, index);
|
|
}
|
|
if (ext.empty())
|
|
return;
|
|
if (ext[0] != '.') {
|
|
str += '.';
|
|
str += ext;
|
|
} else {
|
|
str += ext;
|
|
}
|
|
}
|
|
void VFSPath::RemoveExtension() { ChangeExtension({}); }
|
|
|
|
VFSPath::VFSPath(std::string str) {
|
|
this->path = SplitPath(str);
|
|
this->relative = true;
|
|
if (!str.empty()) {
|
|
if (str.front() == '/')
|
|
this->relative = false;
|
|
#if defined(_WIN32)
|
|
if (str.front() == '\\')
|
|
this->relative = false;
|
|
#endif
|
|
if (!this->path.empty()) {
|
|
auto firstPartPath = this->path.front();
|
|
|
|
if (!firstPartPath.empty() && firstPartPath.back() == ':')
|
|
this->relative = false;
|
|
}
|
|
}
|
|
}
|
|
void VFS::CreateDirectory(VFSPath path) {}
|
|
void VFS::DeleteDirectory(VFSPath path) {}
|
|
VFSPath::VFSPath(VFSPath p1, VFSPath p2) {
|
|
this->relative = p1.relative;
|
|
this->path.insert(this->path.end(), p1.path.begin(), p1.path.end());
|
|
this->path.insert(this->path.end(), p2.path.begin(), p2.path.end());
|
|
}
|
|
VFSPath::VFSPath(VFSPath p1, std::string subpath)
|
|
: VFSPath(p1, VFSPath(subpath)) {}
|
|
VFSPath VFSPath::GetParent() const {
|
|
std::vector<std::string> paths;
|
|
if (this->path.empty())
|
|
return VFSPath();
|
|
if (!this->relative && this->path.size() == 1 && !this->path[0].empty() &&
|
|
this->path[0].back() == ':')
|
|
return *this;
|
|
|
|
paths.insert(paths.begin(), this->path.begin(), this->path.end() - 1);
|
|
auto res = VFSPath(paths);
|
|
res.relative = this->relative;
|
|
return res;
|
|
}
|
|
|
|
std::string VFSPath::GetFileName() const {
|
|
if (this->path.empty())
|
|
return "";
|
|
return this->path.back();
|
|
}
|
|
|
|
std::string VFSPath::ToString() const {
|
|
if (this->path.empty() && !this->relative)
|
|
return "/";
|
|
if (!this->relative && this->path.size() == 1 && !this->path[0].empty() &&
|
|
this->path[0].back() == ':')
|
|
return this->path[0] + "/";
|
|
bool first = true;
|
|
std::string p = {};
|
|
for (auto item : this->path) {
|
|
if (!(first && !item.empty() && item.back() == ':') &&
|
|
!(first && this->relative))
|
|
p.push_back('/');
|
|
p.append(item);
|
|
first = false;
|
|
}
|
|
return p;
|
|
}
|
|
void VFS::DeleteFile(VFSPath path) {}
|
|
void VFS::MoveFile(VFSPath src, VFSPath dest) {
|
|
{
|
|
auto srcStrm = this->OpenFile(src, "rb");
|
|
if (!srcStrm->CanRead())
|
|
return;
|
|
auto destStrm = this->OpenFile(dest, "wb");
|
|
if (!destStrm->CanWrite())
|
|
return;
|
|
srcStrm->CopyTo(destStrm);
|
|
}
|
|
|
|
VFS::DeleteFile(src);
|
|
}
|
|
VFS::~VFS() {}
|
|
|
|
void VFS::MoveDirectory(VFSPath src, VFSPath dest) {
|
|
|
|
for (auto item : EnumeratePaths(src)) {
|
|
if (DirectoryExists(item)) {
|
|
MoveDirectory(item, VFSPath(dest, item.GetFileName()));
|
|
} else {
|
|
MoveFile(item, VFSPath(dest, item.GetFileName()));
|
|
}
|
|
}
|
|
|
|
DeleteDirectory(src);
|
|
}
|
|
void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) {}
|
|
void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName) {}
|
|
|
|
void VFS::DeleteDirectoryRecurse(VFSPath path) {
|
|
if (!DirectoryExists(path))
|
|
return;
|
|
|
|
for (auto item : EnumeratePaths(path)) {
|
|
if (DirectoryExists(item)) {
|
|
DeleteDirectoryRecurse(item);
|
|
} else {
|
|
DeleteFile(item);
|
|
}
|
|
}
|
|
DeleteDirectory(path);
|
|
}
|
|
void VFS::GetDate(VFSPath path, Date::DateTime &lastWrite,
|
|
Date::DateTime &lastAccess) {
|
|
StatData data;
|
|
if (Stat(path, data)) {
|
|
lastWrite = data.LastModified;
|
|
lastAccess = data.LastAccess;
|
|
}
|
|
}
|
|
void VFS::SetDate(VFSPath path, Date::DateTime lastWrite,
|
|
Date::DateTime lastAccess) {}
|
|
bool VFS::StatVFS(VFSPath path, StatVFSData &data) {
|
|
data.BlockSize = 512;
|
|
data.Blocks = 10000000000000;
|
|
data.BlocksFree = 10000000000000;
|
|
data.BlocksAvailable = 10000000000000;
|
|
data.AvailableInodes = 10000000000000;
|
|
data.TotalInodes = 10000000000000;
|
|
data.FreeInodes = 10000000000000;
|
|
data.FragmentSize = 512;
|
|
data.Id = 85138;
|
|
data.Flags = 0;
|
|
data.MaxNameLength = 255;
|
|
return true;
|
|
}
|
|
void VFS::Chmod(VFSPath path, uint32_t mode) {}
|
|
void VFS::Chown(VFSPath path, uint32_t uid, uint32_t gid) {}
|
|
void VFS::Close() {}
|
|
void VFS::Lock(VFSPath path) {}
|
|
void VFS::Unlock(VFSPath path) {}
|
|
|
|
std::shared_ptr<FSWatcher> VFS::CreateWatcher(std::shared_ptr<VFS> vfs,
|
|
VFSPath path) {
|
|
return std::make_shared<FSWatcher>(vfs, path);
|
|
}
|
|
void FSWatcher::SetEnabled(bool enabled) {
|
|
if (this->enabled == enabled)
|
|
return;
|
|
this->enabled = enabled;
|
|
this->SetEnabledImpl(enabled);
|
|
}
|
|
|
|
bool FSWatcher::GetEnabled() { return this->enabled; }
|
|
|
|
void FSWatcher::SetEnabledImpl(bool enabled) {}
|
|
|
|
std::shared_ptr<VFS> FSWatcher::GetFilesystem() { return this->vfs; }
|
|
const VFSPath &FSWatcher::GetPath() { return this->path; }
|
|
|
|
FSWatcher::FSWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
|
|
: vfs(vfs), path(path) {}
|
|
|
|
std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs,
|
|
VFSPath path) {
|
|
return vfs->CreateWatcher(vfs, path);
|
|
}
|
|
|
|
bool FSWatcherEvent::IsEvent(FSWatcherEventType e) {
|
|
if (e == FSWatcherEventType::All)
|
|
return this->type != FSWatcherEventType::None;
|
|
if (e == FSWatcherEventType::Moved)
|
|
return ((uint32_t)this->type & (uint32_t)FSWatcherEventType::Moved) ==
|
|
(uint32_t)FSWatcherEventType::Moved;
|
|
if (e == FSWatcherEventType::Closed)
|
|
return ((uint32_t)this->type & (uint32_t)FSWatcherEventType::Closed) !=
|
|
0;
|
|
return (uint32_t)this->type & (uint32_t)e;
|
|
}
|
|
|
|
std::string FSWatcherEvent::ToString() {
|
|
if (IsEvent(FSWatcherEventType::Moved)) {
|
|
return (this->isDir ? "Moved directory " : "Moved file ") +
|
|
this->src.ToString() + " -> " + this->dest.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::MoveOld)) {
|
|
return (this->isDir ? "Move source directory " : "Move source file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::MoveNew)) {
|
|
return (this->isDir ? "Move destination directory "
|
|
: "Move destination file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Accessed)) {
|
|
return (this->isDir ? "Accessed directory " : "Accessed file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::AttributeChanged)) {
|
|
return (this->isDir ? "Changed attr on directory "
|
|
: "Changed attr on file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Writen)) {
|
|
return (this->isDir ? "Finished changing directory "
|
|
: "Finished writing to file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Read)) {
|
|
return (this->isDir ? "Finished reading directory "
|
|
: "Finished reading from file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Created)) {
|
|
return (this->isDir ? "Created directory " : "Created file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Deleted)) {
|
|
return (this->isDir ? "Deleted directory " : "Deleted file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::WatchEntryDeleted)) {
|
|
|
|
return (this->isDir ? "Deleted watched directory "
|
|
: "Deleted watched file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Modified)) {
|
|
return (this->isDir ? "Modified directory " : "Modified file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::WatchEntryMoved)) {
|
|
return (this->isDir ? "Moved watched directory "
|
|
: "Moved watched file ") +
|
|
this->src.ToString();
|
|
} else if (IsEvent(FSWatcherEventType::Opened)) {
|
|
return (this->isDir ? "Opened directory " : "Opened file ") +
|
|
this->src.ToString();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
} // namespace Tesses::Framework::Filesystem
|