diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index 973edbed0..e948733aa 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -58,6 +58,9 @@ namespace hex::plugin::builtin { [[nodiscard]] std::pair getRegionValidity(u64 address) const override; + private: + void convertToMemoryFile(); + protected: std::fs::path m_path; wolv::io::File m_file; diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 6610b4419..d88e63577 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -485,6 +485,7 @@ "hex.builtin.provider.file.error.open": "Failed to open file {}: {}", "hex.builtin.provider.file.access": "Last access time", "hex.builtin.provider.file.creation": "Creation time", + "hex.builtin.provider.file.menu.into_memory": "Load into memory", "hex.builtin.provider.file.modification": "Last modification time", "hex.builtin.provider.file.path": "File path", "hex.builtin.provider.file.size": "Size", diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index 0b795667e..41f55f818 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -1,10 +1,13 @@ #include "content/providers/file_provider.hpp" +#include "content/providers/memory_file_provider.hpp" #include #include #include #include +#include + #include #include @@ -204,14 +207,9 @@ namespace hex::plugin::builtin { std::vector FileProvider::getMenuEntries(){ return { - {"hex.builtin.provider.file.menu.open_folder"_lang, [path = this->m_path] { - fs::openFolderWithSelectionExternal(path); - }}, - - {"hex.builtin.provider.file.menu.open_file"_lang, [path = this->m_path] { - fs::openFileExternal(path); - }}, - + { "hex.builtin.provider.file.menu.open_folder"_lang, [this] { fs::openFolderWithSelectionExternal(this->m_path); } }, + { "hex.builtin.provider.file.menu.open_file"_lang, [this] { fs::openFileExternal(this->m_path); } }, + { "hex.builtin.provider.file.menu.into_memory", [this] { this->convertToMemoryFile(); } } }; } @@ -299,4 +297,36 @@ namespace hex::plugin::builtin { return { Region::Invalid(), false }; } + void FileProvider::convertToMemoryFile() { + auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true); + + if (auto memoryProvider = dynamic_cast(newProvider); memoryProvider != nullptr) { + if (!memoryProvider->open()) + ImHexApi::Provider::remove(newProvider); + else { + const auto size = this->getActualSize(); + TaskManager::createTask("Loading into memory", size, [this, size, memoryProvider](Task &task) { + task.setInterruptCallback([memoryProvider]{ + ImHexApi::Provider::remove(memoryProvider); + }); + + constexpr static size_t BufferSize = 0x10000; + std::vector buffer(BufferSize); + + memoryProvider->resize(size); + + for (u64 i = 0; i < size; i += BufferSize) { + auto copySize = std::min(BufferSize, size - i); + this->read(i, buffer.data(), copySize, true); + memoryProvider->writeRaw(i, buffer.data(), copySize); + task.update(i); + } + + memoryProvider->markDirty(true); + ImHexApi::Provider::remove(this, false); + }); + } + } + } + } diff --git a/plugins/builtin/source/content/providers/memory_file_provider.cpp b/plugins/builtin/source/content/providers/memory_file_provider.cpp index 4cbf59057..d3ca05118 100644 --- a/plugins/builtin/source/content/providers/memory_file_provider.cpp +++ b/plugins/builtin/source/content/providers/memory_file_provider.cpp @@ -47,12 +47,16 @@ namespace hex::plugin::builtin { auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.file", true); - if (auto fileProvider = dynamic_cast(newProvider); fileProvider != nullptr && (fileProvider->setPath(path), !fileProvider->open())) - ImHexApi::Provider::remove(newProvider); - else { - fileProvider->markDirty(false); - EventManager::post(newProvider); - ImHexApi::Provider::remove(this, true); + if (auto fileProvider = dynamic_cast(newProvider); fileProvider != nullptr) { + fileProvider->setPath(path); + + if (!fileProvider->open()) + ImHexApi::Provider::remove(newProvider); + else { + fileProvider->markDirty(false); + EventManager::post(newProvider); + ImHexApi::Provider::remove(this, true); + } } }); } @@ -134,11 +138,13 @@ namespace hex::plugin::builtin { this->m_data = settings["data"].get>(); this->m_name = settings["name"].get(); + this->m_readOnly = settings["readOnly"].get(); } [[nodiscard]] nlohmann::json MemoryFileProvider::storeSettings(nlohmann::json settings) const { settings["data"] = this->m_data; settings["name"] = this->m_name; + settings["readOnly"] = this->m_readOnly; return Provider::storeSettings(settings); }