diff --git a/examples/mountabletest.cpp b/examples/mountabletest.cpp index b5428c3..11c22e1 100644 --- a/examples/mountabletest.cpp +++ b/examples/mountabletest.cpp @@ -38,9 +38,8 @@ int main(int argc, char** argv) { std::string dir = "/"; if(argc > 2) dir = argv[2]; - std::vector paths; - fs.GetPaths(dir, paths); - for(auto item : paths) + + for(auto item : fs.EnumeratePaths(dir)) { std::cout << item.GetFileName() << std::endl; } diff --git a/include/TessesFramework/Filesystem/LocalFS.hpp b/include/TessesFramework/Filesystem/LocalFS.hpp index c28d6e5..c7d6ec4 100644 --- a/include/TessesFramework/Filesystem/LocalFS.hpp +++ b/include/TessesFramework/Filesystem/LocalFS.hpp @@ -17,12 +17,14 @@ namespace Tesses::Framework::Filesystem bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); - void GetPaths(VFSPath path, std::vector& paths); + VFSPathEnumerator EnumeratePaths(VFSPath path); void CreateHardlink(VFSPath existingFile, VFSPath newName); void MoveFile(VFSPath src, VFSPath dest); void MoveDirectory(VFSPath src, VFSPath dest); VFSPath ReadLink(VFSPath path); std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); + void GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess); + void SetDate(VFSPath path, time_t lastWrite, time_t lastAccess); }; } \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/MountableFilesystem.hpp b/include/TessesFramework/Filesystem/MountableFilesystem.hpp index 15a3429..7d145df 100644 --- a/include/TessesFramework/Filesystem/MountableFilesystem.hpp +++ b/include/TessesFramework/Filesystem/MountableFilesystem.hpp @@ -41,7 +41,7 @@ namespace Tesses::Framework::Filesystem bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); - void GetPaths(VFSPath path, std::vector& paths); + VFSPathEnumerator EnumeratePaths(VFSPath path); void CreateHardlink(VFSPath existingFile, VFSPath newName); void MoveFile(VFSPath src, VFSPath dest); void MoveDirectory(VFSPath src, VFSPath dest); @@ -49,5 +49,7 @@ namespace Tesses::Framework::Filesystem std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); ~MountableFilesystem(); + void GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess); + void SetDate(VFSPath path, time_t lastWrite, time_t lastAccess); }; } \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/NullFilesystem.hpp b/include/TessesFramework/Filesystem/NullFilesystem.hpp index e8da42a..49c8cc1 100644 --- a/include/TessesFramework/Filesystem/NullFilesystem.hpp +++ b/include/TessesFramework/Filesystem/NullFilesystem.hpp @@ -11,7 +11,7 @@ namespace Tesses::Framework::Filesystem bool RegularFileExists(VFSPath path); bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); - void GetPaths(VFSPath path, std::vector& paths); + VFSPathEnumerator EnumeratePaths(VFSPath path); void MoveFile(VFSPath src, VFSPath dest); std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); diff --git a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp index 3d341bf..86a6ff8 100644 --- a/include/TessesFramework/Filesystem/SubdirFilesystem.hpp +++ b/include/TessesFramework/Filesystem/SubdirFilesystem.hpp @@ -25,7 +25,7 @@ namespace Tesses::Framework::Filesystem bool DirectoryExists(VFSPath path); void DeleteFile(VFSPath path); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); - void GetPaths(VFSPath path, std::vector& paths); + VFSPathEnumerator EnumeratePaths(VFSPath path); void CreateHardlink(VFSPath existingFile, VFSPath newName); void MoveFile(VFSPath src, VFSPath dest); void MoveDirectory(VFSPath src, VFSPath dest); @@ -34,5 +34,8 @@ namespace Tesses::Framework::Filesystem std::string VFSPathToSystem(VFSPath path); VFSPath SystemToVFSPath(std::string path); ~SubdirFilesystem(); + void GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess); + void SetDate(VFSPath path, time_t lastWrite, time_t lastAccess); + }; } \ No newline at end of file diff --git a/include/TessesFramework/Filesystem/VFS.hpp b/include/TessesFramework/Filesystem/VFS.hpp index 7daf82f..5348774 100644 --- a/include/TessesFramework/Filesystem/VFS.hpp +++ b/include/TessesFramework/Filesystem/VFS.hpp @@ -1,6 +1,8 @@ #pragma once #include "../Common.hpp" #include "../Streams/Stream.hpp" +#include +#include namespace Tesses::Framework::Filesystem { class VFSPath { @@ -28,6 +30,58 @@ namespace Tesses::Framework::Filesystem VFSPath operator+(VFSPath p, VFSPath p2); VFSPath operator+(VFSPath p, std::string p2); VFSPath operator+(std::string p, VFSPath p2); + + class VFSPathEnumeratorData { + public: + VFSPathEnumeratorData(std::function moveNext, std::function destroy) + { + this->eof=false; + this->moveNext=moveNext; + this->destroy=destroy; + } + bool eof; + std::function moveNext; + std::function destroy; + ~VFSPathEnumeratorData() + { + this->destroy(); + } + }; + + class VFSPathEnumerator; + + class VFSPathEnumeratorItterator + { + VFSPath e; + VFSPathEnumerator* enumerator; + public: + VFSPathEnumeratorItterator(); + VFSPathEnumeratorItterator(VFSPathEnumerator* enumerator); + + VFSPathEnumeratorItterator& operator++(); + VFSPathEnumeratorItterator& operator++(int); + + VFSPath& operator*(); + VFSPath* operator->(); + + bool operator!=(VFSPathEnumeratorItterator right); + bool operator==(VFSPathEnumeratorItterator right); + }; + + class VFSPathEnumerator { + std::shared_ptr data; + public: + VFSPathEnumerator(); + VFSPathEnumerator* MakePointer(); + VFSPathEnumerator(std::function moveNext, std::function destroy); + VFSPath Current; + bool MoveNext(); + bool IsDone(); + + VFSPathEnumeratorItterator begin(); + + VFSPathEnumeratorItterator end(); + }; class VFS { @@ -49,13 +103,17 @@ namespace Tesses::Framework::Filesystem virtual bool DirectoryExists(VFSPath path)=0; virtual void DeleteFile(VFSPath path)=0; virtual void DeleteDirectoryRecurse(VFSPath path); - virtual void GetPaths(VFSPath path, std::vector& paths)=0; + virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0; virtual void MoveFile(VFSPath src, VFSPath dest)=0; virtual void MoveDirectory(VFSPath src, VFSPath dest); virtual VFSPath ReadLink(VFSPath path); virtual std::string VFSPathToSystem(VFSPath path)=0; virtual VFSPath SystemToVFSPath(std::string path)=0; + + virtual void GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess); + virtual void SetDate(VFSPath path, time_t lastWrite, time_t lastAccess); + virtual ~VFS(); }; } \ No newline at end of file diff --git a/include/TessesFramework/Streams/Stream.hpp b/include/TessesFramework/Streams/Stream.hpp index 4ac6944..d4378ea 100644 --- a/include/TessesFramework/Streams/Stream.hpp +++ b/include/TessesFramework/Streams/Stream.hpp @@ -11,7 +11,6 @@ namespace Tesses::Framework::Streams public: int32_t ReadByte(); void WriteByte(uint8_t b); - virtual bool EndOfStream(); virtual size_t Read(uint8_t* buff, size_t sz); virtual size_t Write(const uint8_t* buff, size_t sz); diff --git a/src/Filesystem/LocalFS.cpp b/src/Filesystem/LocalFS.cpp index 42e7807..bf127a9 100644 --- a/src/Filesystem/LocalFS.cpp +++ b/src/Filesystem/LocalFS.cpp @@ -1,8 +1,28 @@ #include "TessesFramework/Filesystem/LocalFS.hpp" #include "TessesFramework/Streams/FileStream.hpp" #include +#include +#include namespace Tesses::Framework::Filesystem { + void LocalFilesystem::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess) + { + std::string s = VFSPathToSystem(path); + struct stat st; + if(stat(s.c_str(),&st) == 0) + { + lastAccess = st.st_atime; + lastWrite = st.st_mtime; + } + } + void LocalFilesystem::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess) + { + std::string s = VFSPathToSystem(path); + struct utimbuf utim; + utim.actime = lastAccess; + utim.modtime = lastWrite; + utime(s.c_str(),&utim); + } VFSPath LocalFilesystem::ReadLink(VFSPath path) { return this->SystemToVFSPath(std::filesystem::read_symlink(this->VFSPathToSystem(path))); @@ -110,12 +130,22 @@ namespace Tesses::Framework::Filesystem } return p; } - void LocalFilesystem::GetPaths(VFSPath path, std::vector& paths) + + VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path) { - for(auto item : std::filesystem::directory_iterator(VFSPathToSystem(path))) - { - paths.push_back(VFSPath(path, item.path().filename().string())); - } + auto dir = new std::filesystem::directory_iterator(VFSPathToSystem(path)); + return VFSPathEnumerator([dir,path](VFSPath& path0)->bool { + std::filesystem::directory_iterator& ittr = *dir; + if(ittr != std::filesystem::directory_iterator()) + { + path0 = VFSPath(path, ittr->path().filename().string()); + ittr++; + return true; + } + return false; + },[dir]()->void{ + delete dir; + }); } } diff --git a/src/Filesystem/MountableFilesystem.cpp b/src/Filesystem/MountableFilesystem.cpp index eaa9f64..bdee13a 100644 --- a/src/Filesystem/MountableFilesystem.cpp +++ b/src/Filesystem/MountableFilesystem.cpp @@ -287,6 +287,34 @@ namespace Tesses::Framework::Filesystem if(vfs != nullptr) vfs->DeleteFile(destPath); + } + void MountableFilesystem::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess) + { + + path = path.CollapseRelativeParents(); + + VFSPath destRoot; + VFSPath destPath = path; + VFS* vfs = root; + + GetFS(path, destRoot, destPath, vfs); + + if(vfs != nullptr) + vfs->GetDate(destPath,lastWrite,lastAccess); + } + void MountableFilesystem::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess) + { + + path = path.CollapseRelativeParents(); + + VFSPath destRoot; + VFSPath destPath = path; + VFS* vfs = root; + + GetFS(path, destRoot, destPath, vfs); + + if(vfs != nullptr) + vfs->SetDate(destPath,lastWrite,lastAccess); } void MountableFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) { @@ -361,11 +389,19 @@ namespace Tesses::Framework::Filesystem if(existingVFS != nullptr && existingVFS == newNameVFS) existingVFS->CreateHardlink(existingDestPath, newNamePath); } - void MountableFilesystem::GetPaths(VFSPath path, std::vector& paths) + class MountableEnumerationState { + public: + VFSPathEnumerator* enumerator; + std::vector dirs; + size_t index; + }; + VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path) { + path = path.CollapseRelativeParents(); bool mydirs = path.path.empty(); std::vector* dirs = &this->directories; + if(!path.path.empty()) for(auto p : path.path) { @@ -396,32 +432,50 @@ namespace Tesses::Framework::Filesystem GetFS(path, destRoot, destPath, vfs); - if(vfs != nullptr) - { - std::vector paths2; - if(vfs->DirectoryExists(destPath) || !mydirs) - vfs->GetPaths(destPath,paths2); - for(auto item : paths2) + MountableEnumerationState* state = new MountableEnumerationState(); + state->dirs = *dirs; + state->index = 0; + if(vfs->DirectoryExists(destPath) || !mydirs) + state->enumerator = vfs->EnumeratePaths(destPath).MakePointer(); + else + state->enumerator = nullptr; + + return VFSPathEnumerator([state,path](VFSPath& path0)->bool{ + + while(state->enumerator != nullptr && state->enumerator->MoveNext()) { - paths.push_back(VFSPath(destPath, item.GetFileName())); - } - if(mydirs) - for(auto item : *dirs) - { - bool cantAdd=false; - for(auto d : paths) { - if(d.GetFileName() == item->name) + auto fname = state->enumerator->Current.GetFileName(); + + bool mustContinue=false; + for(auto item : state->dirs) + { + if(item->name == fname) { - cantAdd=true; + mustContinue=true; break; } } - if(!cantAdd) paths.push_back(VFSPath(destPath, item->name)); + if(mustContinue) continue; + path0 = path / fname; + return true; } - } + if(state->enumerator != nullptr) + { + delete state->enumerator; + state->enumerator = nullptr; + } + if(state->index < state->dirs.size()) + { + path0 = path / state->dirs[state->index++]->name; + return true; + } + return false; + },[state]()->void{ + if(state->enumerator) delete state->enumerator; + delete state; + }); } - - + void MountableFilesystem::Mount(VFSPath path, VFS* fs, bool owns) { path = path.CollapseRelativeParents(); diff --git a/src/Filesystem/NullFilesystem.cpp b/src/Filesystem/NullFilesystem.cpp index b556f0b..adbf9e2 100644 --- a/src/Filesystem/NullFilesystem.cpp +++ b/src/Filesystem/NullFilesystem.cpp @@ -26,9 +26,9 @@ namespace Tesses::Framework::Filesystem { } - void NullFilesystem::GetPaths(VFSPath path, std::vector& paths) + VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path) { - + return VFSPathEnumerator(); } void NullFilesystem::MoveFile(VFSPath src, VFSPath dest) { diff --git a/src/Filesystem/SubdirFilesystem.cpp b/src/Filesystem/SubdirFilesystem.cpp index f1f52b4..40f03dc 100644 --- a/src/Filesystem/SubdirFilesystem.cpp +++ b/src/Filesystem/SubdirFilesystem.cpp @@ -82,15 +82,31 @@ namespace Tesses::Framework::Filesystem { this->parent->CreateSymlink(ToParent(existingFile),ToParent(symlinkFile)); } - void SubdirFilesystem::GetPaths(VFSPath path, std::vector& paths) + + VFSPathEnumerator SubdirFilesystem::EnumeratePaths(VFSPath path) { - std::vector paths2; - this->parent->GetPaths(ToParent(path),paths2); - for(auto item : paths2) - { - paths.push_back(FromParent(item)); - } + VFSPathEnumerator* enumerator = this->parent->EnumeratePaths(ToParent(path)).MakePointer(); + + return VFSPathEnumerator([enumerator,path,this](VFSPath& path0)->bool{ + if(enumerator->MoveNext()) + { + path0 = FromParent( path / enumerator->Current); + return true; + } + return false; + },[enumerator]()->void{ + delete enumerator; + }); } + void SubdirFilesystem::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess) + { + this->parent->GetDate(ToParent(path),lastWrite,lastAccess); + } + void SubdirFilesystem::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess) + { + this->parent->SetDate(ToParent(path),lastWrite,lastAccess); + } + void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName) { this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName)); diff --git a/src/Filesystem/VFS.cpp b/src/Filesystem/VFS.cpp index d1a90f8..dff7c26 100644 --- a/src/Filesystem/VFS.cpp +++ b/src/Filesystem/VFS.cpp @@ -2,6 +2,110 @@ #include "TessesFramework/Http/HttpUtils.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 moveNext, std::function destroy) + { + data = std::make_shared(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); @@ -198,10 +302,8 @@ namespace Tesses::Framework::Filesystem bool VFS::SymlinkExists(VFSPath path) {return false;} void VFS::MoveDirectory(VFSPath src, VFSPath dest) { - std::vector paths; - GetPaths(src, paths); - - for(auto item : paths) + + for(auto item : EnumeratePaths(src)) { if(DirectoryExists(item)) { @@ -236,10 +338,8 @@ namespace Tesses::Framework::Filesystem void VFS::DeleteDirectoryRecurse(VFSPath path) { if(!DirectoryExists(path)) return; - std::vector paths; - GetPaths(path, paths); - - for(auto item : paths) + + for(auto item : EnumeratePaths(path)) { if(DirectoryExists(item)) { @@ -252,4 +352,13 @@ namespace Tesses::Framework::Filesystem } DeleteDirectory(path); } + void VFS::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess) + { + + } + void VFS::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess) + { + + } + } \ No newline at end of file diff --git a/src/Http/FileServer.cpp b/src/Http/FileServer.cpp index a675031..6324ed1 100644 --- a/src/Http/FileServer.cpp +++ b/src/Http/FileServer.cpp @@ -74,10 +74,9 @@ namespace Tesses::Framework::Http html.append("

Index of "); html.append(p); html.append("


../\r\n");
-                std::vector ents;
-                vfs->GetPaths(path, ents);
+                
 
-                for(auto item : ents)
+                for(auto item : vfs->EnumeratePaths(path))
                 {
                     if(vfs->DirectoryExists(item))
                     {
diff --git a/src/Streams/Stream.cpp b/src/Streams/Stream.cpp
index b0de9cf..922cd4c 100644
--- a/src/Streams/Stream.cpp
+++ b/src/Streams/Stream.cpp
@@ -94,8 +94,8 @@ namespace Tesses::Framework::Streams {
     }
     void Stream::CopyTo(Stream* strm, size_t buffSize)
     {
-        if(strm == nullptr)
-        strm->CopyTo(strm, buffSize);
+        if(strm != nullptr)
+        strm->CopyTo(*strm, buffSize);
     }
     void Stream::CopyTo(Stream& strm, size_t buffSize)
     {
@@ -112,4 +112,4 @@ namespace Tesses::Framework::Streams {
     {
 
     }
-}
\ No newline at end of file
+}