#include "./memory.hpp" #include "../io/stream.hpp" namespace mijin { std::vector MemoryFileSystemAdapter::listFiles(PathView folder) { const detail::MemoryFolder* folderObj = findFolder(folder); if (folderObj == nullptr) { return {}; } std::vector result; result.reserve(folderObj->folders.size() + folderObj->files.size()); const Path folderPath(folder); for (const auto& [name, subFolder] : folderObj->folders) { result.emplace_back(folderPath / name, folderInfo(subFolder)); } for (const auto& [name, file] : folderObj->files) { result.emplace_back(folderPath / name, fileInfo(file)); } return result; } FileInfo MemoryFileSystemAdapter::getFileInfo(PathView 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.getParent()); if (folderObj == nullptr) { return {}; } const std::string_view filename = file.getName(); if (auto itFolder = folderObj->folders.find(filename); itFolder != folderObj->folders.end()) { return folderInfo(itFolder->second); } if (auto itFile = folderObj->files.find(filename); itFile != folderObj->files.end()) { return fileInfo(itFile->second); } return {}; } StreamError MemoryFileSystemAdapter::open(PathView path, FileOpenMode mode, std::unique_ptr& outStream) { if (mode != FileOpenMode::READ) { return StreamError::IO_ERROR; } const detail::MemoryFolder* folderObj = findFolder(path.getParent()); if (folderObj == nullptr) { return StreamError::IO_ERROR; } auto itFile = folderObj->files.find(path.getName()); 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(PathView path, std::span data, Overwrite overwrite, CopyData copyData) { detail::MemoryFolder& folder = *findFolder(path.getParent(), true); const std::string_view filename = path.getName(); 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(filename, detail::MemoryFile{.data = data}); return true; } void MemoryFileSystemAdapter::addFolder(PathView path) { (void) findFolder(path, true); } detail::MemoryFolder* MemoryFileSystemAdapter::findFolder(PathView path, bool create) MIJIN_NOEXCEPT { detail::MemoryFolder* folder = &root_; for (const std::string_view part : path) { auto it = folder->folders.find(part); if (it == folder->folders.end()) { if (!create) { return nullptr; } folder = &folder->folders[std::string(part)]; } else { folder = &it->second; } } return folder; } FileInfo MemoryFileSystemAdapter::folderInfo(const detail::MemoryFolder& folder) const MIJIN_NOEXCEPT { return { .size = folder.folders.size() + folder.files.size(), .exists = true, .isFolder = true }; } FileInfo MemoryFileSystemAdapter::fileInfo(const detail::MemoryFile& file) const MIJIN_NOEXCEPT { return { .size = file.data.size(), .exists = true }; } }