From df55a02fa7454b7bb4f12f852116d033c75ba1ad Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 8 May 2022 15:50:59 +0200 Subject: [PATCH] Core/VirtualDirectory: Add GetFileContent method --- include/Nazara/Core/VirtualDirectory.hpp | 1 + include/Nazara/Core/VirtualDirectory.inl | 40 ++++++++++++++++++++++ tests/Engine/Core/VirtualDirectoryTest.cpp | 36 +++++++++++++++++-- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/include/Nazara/Core/VirtualDirectory.hpp b/include/Nazara/Core/VirtualDirectory.hpp index 6d9fa25ee..db6d15aa0 100644 --- a/include/Nazara/Core/VirtualDirectory.hpp +++ b/include/Nazara/Core/VirtualDirectory.hpp @@ -44,6 +44,7 @@ namespace Nz template void Foreach(F&& callback, bool includeDots = false); template bool GetEntry(std::string_view path, F&& callback); + template bool GetFileContent(std::string_view path, F&& callback); inline DirectoryEntry& StoreDirectory(std::string_view path, VirtualDirectoryPtr directory); inline PhysicalDirectoryEntry& StoreDirectory(std::string_view path, std::filesystem::path directoryPath); diff --git a/include/Nazara/Core/VirtualDirectory.inl b/include/Nazara/Core/VirtualDirectory.inl index f37f9f163..4fbaa099e 100644 --- a/include/Nazara/Core/VirtualDirectory.inl +++ b/include/Nazara/Core/VirtualDirectory.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -153,6 +154,45 @@ namespace Nz }); } + template + bool VirtualDirectory::GetFileContent(std::string_view path, F&& callback) + { + return GetEntry(path, [&](const Entry& entry) + { + return std::visit([&](auto&& entry) + { + using T = std::decay_t; + + using P1 = const void*; + using P2 = std::size_t; + + if constexpr (std::is_same_v) + { + return CallbackReturn(callback, static_cast(entry.data), SafeCast(entry.size)); + } + else if constexpr (std::is_same_v) + { + return CallbackReturn(callback, static_cast(entry.data.data()), SafeCast(entry.data.size())); + } + else if constexpr (std::is_same_v) + { + std::optional> source = File::ReadWhole(entry.filePath); + if (!source.has_value()) + return false; + + return CallbackReturn(callback, static_cast(source->data()), SafeCast(source->size())); + } + else if constexpr (std::is_same_v || std::is_same_v) + { + NazaraError("entry is a directory"); + return false; + } + else + static_assert(AlwaysFalse(), "incomplete visitor"); + }, entry); + }); + } + inline auto VirtualDirectory::StoreDirectory(std::string_view path, VirtualDirectoryPtr directory) -> DirectoryEntry& { assert(!path.empty()); diff --git a/tests/Engine/Core/VirtualDirectoryTest.cpp b/tests/Engine/Core/VirtualDirectoryTest.cpp index 04879f4af..e18a9f944 100644 --- a/tests/Engine/Core/VirtualDirectoryTest.cpp +++ b/tests/Engine/Core/VirtualDirectoryTest.cpp @@ -105,8 +105,21 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]") } const auto& contentEntry = std::get(entry); - CHECK(std::equal(expectedData.begin(), expectedData.end(), contentEntry.data.begin(), contentEntry.data.end())); - return true; + return std::equal(expectedData.begin(), expectedData.end(), contentEntry.data.begin(), contentEntry.data.end()); + }); + }; + + auto CheckFileContent = [&](std::string_view path, const std::vector& expectedData) + { + return virtualDir->GetFileContent(path, [&](const void* data, std::size_t size) + { + if (expectedData.size() != size) + { + FAIL("size doesn't match"); + return false; + } + + return std::memcmp(expectedData.data(), data, expectedData.size()) == 0; }); }; @@ -118,6 +131,7 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]") WHEN("We retrieve it") { CHECK(CheckFile("File.bin", randomData)); + CHECK(CheckFileContent("File.bin", randomData)); } } @@ -165,6 +179,8 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]") { INFO("Retrieving " << file.path); CHECK(CheckFile(file.path, file.data)); + INFO("Retrieving " << file.path << " using GetFileContent"); + CHECK(CheckFileContent(file.path, file.data)); } } } @@ -208,6 +224,20 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]") }); }; + auto CheckFileContentHash = [&](const char* filepath, const char* expectedHash) + { + return virtualDir->GetFileContent(filepath, [&](const void* data, std::size_t size) + { + Nz::SHA256Hash hash; + WHEN("We compute " << hash.GetHashName() << " of " << filepath << " file") + { + hash.Begin(); + hash.Append(static_cast(data), size); + CHECK(Nz::ToUpper(hash.End().ToHex()) == expectedHash); + } + }); + }; + WHEN("Accessing files") { CHECK(CheckFileHash("Logo.png", "5C4B9387327C039A6CE9ED51983D6C2ADA9F9DD01D024C2D5D588237ADFC7423")); @@ -244,6 +274,8 @@ TEST_CASE("VirtualDirectory", "[Core][VirtualDirectory]") virtualDir->StoreFile("Logo.png", GetResourceDir() / "ambience.ogg"); CHECK(CheckFileHash("ambience.ogg", "49C486F44E43F023D54C9F375D902C21375DDB2748D3FA1863C9581D30E17F94")); CHECK(CheckFileHash("Logo.png", "49C486F44E43F023D54C9F375D902C21375DDB2748D3FA1863C9581D30E17F94")); + CHECK(CheckFileContentHash("ambience.ogg", "49C486F44E43F023D54C9F375D902C21375DDB2748D3FA1863C9581D30E17F94")); + CHECK(CheckFileContentHash("Logo.png", "49C486F44E43F023D54C9F375D902C21375DDB2748D3FA1863C9581D30E17F94")); } } }