#include "Resources/ResourceFileSystem.h" #include #include namespace XCEngine { namespace Resources { ResourceFileSystem::ResourceFileSystem() = default; ResourceFileSystem::~ResourceFileSystem() { Shutdown(); } void ResourceFileSystem::Initialize(const Containers::String& rootPath) { std::lock_guard lock(m_mutex); m_rootPath = rootPath; } void ResourceFileSystem::Shutdown() { std::lock_guard lock(m_mutex); m_archives.Clear(); m_directories.Clear(); m_infoCache.Clear(); m_rootPath = ""; } bool ResourceFileSystem::AddArchive(const Containers::String& archivePath) { std::lock_guard lock(m_mutex); // TODO: Implement archive loading // For now, just store the path for later resolution m_directories.PushBack(archivePath); return true; } bool ResourceFileSystem::AddDirectory(const Containers::String& directoryPath) { std::lock_guard lock(m_mutex); m_directories.PushBack(directoryPath); return true; } void ResourceFileSystem::RemoveArchive(const Containers::String& archivePath) { std::lock_guard lock(m_mutex); // Remove directories - rebuild without the matching one Containers::Array newDirs; for (size_t i = 0; i < m_directories.Size(); ++i) { if (m_directories[i] != archivePath) { newDirs.PushBack(m_directories[i]); } } m_directories = std::move(newDirs); } bool ResourceFileSystem::FindResource(const Containers::String& relativePath, Containers::String& outAbsolutePath) const { std::lock_guard lock(m_mutex); if (FindInDirectories(relativePath, outAbsolutePath)) { return true; } if (FindInArchives(relativePath, outAbsolutePath)) { return true; } return false; } Containers::Array ResourceFileSystem::ReadResource(const Containers::String& relativePath) const { std::lock_guard lock(m_mutex); Containers::String absolutePath; if (!FindResource(relativePath, absolutePath)) { return Containers::Array(); } // Read file FILE* file = std::fopen(absolutePath.CStr(), "rb"); if (!file) { return Containers::Array(); } std::fseek(file, 0, SEEK_END); size_t size = std::ftell(file); std::fseek(file, 0, SEEK_SET); Containers::Array data; data.Resize(size); size_t readSize = std::fread(data.Data(), 1, size, file); std::fclose(file); if (readSize != size) { return Containers::Array(); } return data; } bool ResourceFileSystem::Exists(const Containers::String& relativePath) const { Containers::String absolutePath; return FindResource(relativePath, absolutePath); } bool ResourceFileSystem::GetResourceInfo(const Containers::String& relativePath, ResourceInfo& outInfo) const { std::lock_guard lock(m_mutex); // Check cache first auto* cached = m_infoCache.Find(relativePath); if (cached != nullptr) { outInfo = *cached; return true; } Containers::String absolutePath; if (!FindResource(relativePath, absolutePath)) { return false; } // Get file info outInfo.path = relativePath; outInfo.inArchive = false; // TODO: Get actual file size and modification time m_infoCache.Insert(relativePath, outInfo); return true; } void ResourceFileSystem::EnumerateResources(const Containers::String& pattern, Containers::Array& outResources) const { std::lock_guard lock(m_mutex); outResources.Clear(); // TODO: Implement pattern matching } ResourceFileSystem& ResourceFileSystem::Get() { static ResourceFileSystem instance; return instance; } IArchive* ResourceFileSystem::FindArchive(const Containers::String& relativePath) const { for (size_t i = 0; i < m_archives.Size(); ++i) { if (m_archives[i]->Exists(relativePath)) { return m_archives[i].get(); } } return nullptr; } bool ResourceFileSystem::FindInDirectories(const Containers::String& relativePath, Containers::String& outAbsolutePath) const { // Try root directory first if (m_rootPath.Length() > 0) { outAbsolutePath = m_rootPath; if (!outAbsolutePath.EndsWith("/") && !outAbsolutePath.EndsWith("\\")) { outAbsolutePath += "/"; } outAbsolutePath += relativePath; // Simple check - in real implementation, use OS APIs // For now, just return the path return true; } // Try each registered directory for (size_t i = 0; i < m_directories.Size(); ++i) { outAbsolutePath = m_directories[i]; if (!outAbsolutePath.EndsWith("/") && !outAbsolutePath.EndsWith("\\")) { outAbsolutePath += "/"; } outAbsolutePath += relativePath; return true; } return false; } bool ResourceFileSystem::FindInArchives(const Containers::String& relativePath, Containers::String& outArchivePath) const { // Check if resource is in any archive IArchive* archive = FindArchive(relativePath); if (archive != nullptr) { outArchivePath = archive->IsValid() ? "archive://" + relativePath : ""; return archive->IsValid(); } return false; } } // namespace Resources } // namespace XCEngine