132 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #include "./filesystem.hpp"
 | |
| 
 | |
| #include "../platform/folders.hpp"
 | |
| 
 | |
| #include <filesystem>
 | |
| 
 | |
| namespace fs = std::filesystem;
 | |
| 
 | |
| namespace mijin
 | |
| {
 | |
| 
 | |
| //
 | |
| // internal defines
 | |
| //
 | |
| 
 | |
| //
 | |
| // internal constants
 | |
| //
 | |
| 
 | |
| //
 | |
| // internal types
 | |
| //
 | |
| 
 | |
| //
 | |
| // internal variables
 | |
| //
 | |
| 
 | |
| //
 | |
| // internal functions
 | |
| //
 | |
| 
 | |
| namespace
 | |
| {
 | |
| void doGetFileInfo(const fs::path& stlPath, FileInfo& outInfo)
 | |
| {
 | |
|     std::error_code err;
 | |
| 
 | |
|     outInfo.isFolder = fs::is_directory(stlPath, err);
 | |
|     outInfo.isSymlink = fs::is_symlink(stlPath, err);
 | |
|     outInfo.isSpecial = !outInfo.isFolder && !fs::is_regular_file(stlPath, err);
 | |
|     outInfo.isHidden = stlPath.c_str()[0] == '.'; // at least for Linux
 | |
|     if (outInfo.isFolder)
 | |
|     {
 | |
|         const fs::directory_iterator dirIt(stlPath, err);
 | |
|         if (err != std::error_code{})
 | |
|         {
 | |
|             outInfo.size = std::distance(dirIt, fs::directory_iterator());
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             outInfo.size = 0;
 | |
|         }
 | |
|     }
 | |
|     else if (!outInfo.isSpecial)
 | |
|     {
 | |
|         outInfo.size = fs::file_size(stlPath, err);
 | |
|         if (err)
 | |
|         {
 | |
|             outInfo.size = 0;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| }
 | |
| 
 | |
| //
 | |
| // public functions
 | |
| //
 | |
| 
 | |
| std::vector<FolderEntry> OSFileSystemAdapter::listFiles(PathView folder)
 | |
| {
 | |
|     std::vector<FolderEntry> entries;
 | |
|     std::error_code err;
 | |
| 
 | |
|     const fs::path stlFolder(folder.stringView());
 | |
|     const fs::directory_iterator iterator(stlFolder, fs::directory_options::skip_permission_denied, err);
 | |
|     if (err) {
 | |
|         return {}; // TODO: propagate?
 | |
|     }
 | |
|     for (const fs::directory_entry& stlEntry : iterator)
 | |
|     {
 | |
|         FolderEntry& entry = entries.emplace_back();
 | |
|         entry.path = stlEntry.path().generic_string();
 | |
|         entry.info.exists = true;
 | |
|         doGetFileInfo(stlEntry.path(), entry.info);
 | |
|     }
 | |
|     return entries;
 | |
| }
 | |
| 
 | |
| FileInfo OSFileSystemAdapter::getFileInfo(PathView file)
 | |
| {
 | |
|     const fs::path stlFile(file.stringView());
 | |
| 
 | |
|     FileInfo info = {};
 | |
|     std::error_code err;
 | |
|     info.exists = fs::exists(stlFile, err);
 | |
|     if (info.exists)
 | |
|     {
 | |
|         doGetFileInfo(fs::path(file.stringView()), info);
 | |
|     }
 | |
|     return info;
 | |
| }
 | |
| 
 | |
| Optional<NativePath> OSFileSystemAdapter::getNativePath(PathView file)
 | |
| {
 | |
|     return NativePath(file);
 | |
| }
 | |
| 
 | |
| StreamError OSFileSystemAdapter::open(PathView path, FileOpenMode mode, std::unique_ptr<Stream>& outStream)
 | |
| {
 | |
|     const PathView::string_view_t pathSv = path.stringView();
 | |
|     char* pathStr = static_cast<char*>(alloca(pathSv.size() + 1));
 | |
|     std::memcpy(pathStr, pathSv.data(), pathSv.size());
 | |
|     pathStr[pathSv.size()] = '\0';
 | |
| 
 | |
|     auto stream = std::make_unique<FileStream>();
 | |
|     const StreamError error = stream->open(pathStr, mode);
 | |
|     if (error != StreamError::SUCCESS) {
 | |
|         return error;
 | |
|     }
 | |
|     outStream = std::move(stream);
 | |
|     return StreamError::SUCCESS;
 | |
| }
 | |
| 
 | |
| OSFileSystemAdapter& OSFileSystemAdapter::getInstance() // static
 | |
| {
 | |
|     static OSFileSystemAdapter instance;
 | |
|     return instance;
 | |
| }
 | |
| 
 | |
| } // namespace mijin
 |