#include "./memory.hpp" #include "../io/stream.hpp" namespace mijin { std::vector MemoryFileSystemAdapter::listFiles(const fs::path& folder) { const detail::MemoryFolder* folderObj = findFolder(folder); if (folderObj == nullptr) { return {}; } std::vector result; result.reserve(folderObj->folders.size() + folderObj->files.size()); for (const auto& [name, subFolder] : folderObj->folders) { result.push_back(folderInfo(folder / name, subFolder)); } for (const auto& [name, file] : folderObj->files) { result.push_back(fileInfo(folder / name, file)); } return result; } FileInfo MemoryFileSystemAdapter::getFileInfo(const fs::path& file) { #if 0 // shouldn't be necessary // empty means root if (file.empty()) { return { .path = {}, .size = root_.folders.size() + root_.files.size(), .exists = true, .isFolder = true }; } #endif const detail::MemoryFolder* folderObj = findFolder(file.parent_path()); if (folderObj == nullptr) { return {}; } const std::string filename = file.filename().generic_string(); if (auto itFolder = folderObj->folders.find(filename); itFolder != folderObj->folders.end()) { return folderInfo(file, itFolder->second); } if (auto itFile = folderObj->files.find(filename); itFile != folderObj->files.end()) { return fileInfo(file, itFile->second); } return {}; } StreamError MemoryFileSystemAdapter::open(const fs::path& path, FileOpenMode mode, std::unique_ptr& outStream) { if (mode != FileOpenMode::READ) { return StreamError::IO_ERROR; } const detail::MemoryFolder* folderObj = findFolder(path.parent_path()); if (folderObj == nullptr) { return StreamError::IO_ERROR; } auto itFile = folderObj->files.find(path.filename().generic_string()); if (itFile == folderObj->files.end()) { return StreamError::IO_ERROR; } std::unique_ptr stream = std::make_unique(); stream->openRO(itFile->second.data); outStream = std::move(stream); return StreamError::SUCCESS; } bool MemoryFileSystemAdapter::addFile(const fs::path& path, std::span data, Overwrite overwrite, CopyData copyData) { detail::MemoryFolder& folder = *findFolder(path.parent_path(), true); std::string filename = path.filename().generic_string(); if (folder.folders.contains(filename)) { return false; } if (!overwrite && folder.files.contains(filename)) { return false; } if (copyData) { data = fileData_.emplace_back(data.begin(), data.end()); } folder.files.emplace(std::move(filename), detail::MemoryFile{.data = data}); return true; } void MemoryFileSystemAdapter::addFolder(const fs::path& path) { (void) findFolder(path, true); } detail::MemoryFolder* MemoryFileSystemAdapter::findFolder(const fs::path& path, bool create) MIJIN_NOEXCEPT { detail::MemoryFolder* folder = &root_; for (const fs::path& part : path) { std::string partname = part.generic_string(); auto it = folder->folders.find(partname); if (it == folder->folders.end()) { if (!create) { return nullptr; } folder = &folder->folders[std::move(partname)]; } else { folder = &it->second; } } return folder; } FileInfo MemoryFileSystemAdapter::folderInfo(const fs::path& path, const detail::MemoryFolder& folder) const MIJIN_NOEXCEPT { return { .path = path, .size = folder.folders.size() + folder.files.size(), .exists = true, .isFolder = true }; } FileInfo MemoryFileSystemAdapter::fileInfo(const fs::path& path, const detail::MemoryFile& file) const MIJIN_NOEXCEPT { return { .path = path, .size = file.data.size(), .exists = true }; } }