mirror of https://github.com/WerWolv/ImHex.git
113 lines
3.5 KiB
C++
113 lines
3.5 KiB
C++
#include "content/providers/memory_file_provider.hpp"
|
|
#include "content/providers/file_provider.hpp"
|
|
|
|
#include <cstring>
|
|
|
|
#include <hex/api/imhex_api.hpp>
|
|
#include <hex/api/localization.hpp>
|
|
#include <hex/api/event.hpp>
|
|
|
|
#include <wolv/io/file.hpp>
|
|
|
|
namespace hex::plugin::builtin {
|
|
|
|
bool MemoryFileProvider::open() {
|
|
this->m_data.resize(1);
|
|
this->markDirty();
|
|
return true;
|
|
}
|
|
|
|
void MemoryFileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
|
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
|
return;
|
|
|
|
std::memcpy(buffer, &this->m_data.front() + offset, size);
|
|
}
|
|
|
|
void MemoryFileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
|
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
|
return;
|
|
|
|
std::memcpy(&this->m_data.front() + offset, buffer, size);
|
|
}
|
|
|
|
void MemoryFileProvider::save() {
|
|
fs::openFileBrowser(fs::DialogMode::Save, { }, [this](const std::fs::path &path) {
|
|
if (path.empty())
|
|
return;
|
|
|
|
this->saveAs(path);
|
|
|
|
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
|
|
|
if (auto fileProvider = dynamic_cast<FileProvider*>(newProvider); fileProvider != nullptr && (fileProvider->setPath(path), !fileProvider->open()))
|
|
ImHexApi::Provider::remove(newProvider);
|
|
else {
|
|
fileProvider->markDirty(false);
|
|
EventManager::post<EventProviderOpened>(newProvider);
|
|
ImHexApi::Provider::remove(this, true);
|
|
}
|
|
});
|
|
}
|
|
|
|
void MemoryFileProvider::resize(size_t newSize) {
|
|
this->m_data.resize(newSize);
|
|
|
|
Provider::resize(newSize);
|
|
}
|
|
|
|
void MemoryFileProvider::insert(u64 offset, size_t size) {
|
|
auto oldSize = this->getActualSize();
|
|
this->resize(oldSize + size);
|
|
|
|
std::vector<u8> buffer(0x1000);
|
|
const std::vector<u8> zeroBuffer(0x1000);
|
|
|
|
auto position = oldSize;
|
|
while (position > offset) {
|
|
const auto readSize = std::min<size_t>(position - offset, buffer.size());
|
|
|
|
position -= readSize;
|
|
|
|
this->readRaw(position, buffer.data(), readSize);
|
|
this->writeRaw(position, zeroBuffer.data(), readSize);
|
|
this->writeRaw(position + size, buffer.data(), readSize);
|
|
}
|
|
|
|
Provider::insert(offset, size);
|
|
}
|
|
|
|
void MemoryFileProvider::remove(u64 offset, size_t size) {
|
|
auto oldSize = this->getActualSize();
|
|
this->resize(oldSize + size);
|
|
|
|
std::vector<u8> buffer(0x1000);
|
|
|
|
const auto newSize = oldSize - size;
|
|
auto position = offset;
|
|
while (position < newSize) {
|
|
const auto readSize = std::min<size_t>(newSize - position, buffer.size());
|
|
|
|
this->readRaw(position + size, buffer.data(), readSize);
|
|
this->writeRaw(position, buffer.data(), readSize);
|
|
|
|
position += readSize;
|
|
}
|
|
|
|
this->resize(newSize);
|
|
|
|
Provider::insert(offset, size);
|
|
Provider::remove(offset, size);
|
|
}
|
|
|
|
std::pair<Region, bool> MemoryFileProvider::getRegionValidity(u64 address) const {
|
|
address -= this->getBaseAddress();
|
|
|
|
if (address < this->getActualSize())
|
|
return { Region { this->getBaseAddress() + address, this->getActualSize() - address }, true };
|
|
else
|
|
return { Region::Invalid(), false };
|
|
}
|
|
|
|
}
|