1
0
mirror of synced 2025-01-18 09:04:52 +01:00

Abstracted FILE handle into a generic data provider class

This commit is contained in:
WerWolv 2020-11-11 09:18:35 +01:00
parent c87bc6aebe
commit 434bb3494a
11 changed files with 229 additions and 93 deletions

View File

@ -16,6 +16,8 @@ add_executable(ImHex
source/parser/lexer.cpp
source/parser/parser.cpp
source/provider/file_provider.cpp
source/views/view_hexeditor.cpp
source/views/view_pattern.cpp
source/views/view_pattern_data.cpp

View File

@ -0,0 +1,28 @@
#pragma once
#include "providers/provider.hpp"
#include <string_view>
namespace hex::prv {
class FileProvider : public Provider {
public:
FileProvider(std::string_view path);
virtual ~FileProvider();
virtual bool isAvailable() override;
virtual bool isReadable() override;
virtual bool isWritable() override;
virtual void read(u64 offset, void *buffer, size_t size) override;
virtual void write(u64 offset, void *buffer, size_t size) override;
virtual size_t getSize() override;
private:
FILE *m_file;
bool m_readable, m_writable;
};
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <hex.hpp>
namespace hex::prv {
class Provider {
public:
Provider() { }
virtual ~Provider() { }
virtual bool isAvailable() = 0;
virtual bool isReadable() = 0;
virtual bool isWritable() = 0;
virtual void read(u64 offset, void *buffer, size_t size) = 0;
virtual void write(u64 offset, void *buffer, size_t size) = 0;
virtual size_t getSize() = 0;
};
}

View File

@ -4,18 +4,20 @@
#include <cstdio>
#include "providers/provider.hpp"
namespace hex {
class ViewHashes : public View {
public:
ViewHashes(FILE* &file);
ViewHashes(prv::Provider* &dataProvider);
virtual ~ViewHashes();
virtual void createView() override;
virtual void createMenu() override;
private:
FILE* &m_file;
prv::Provider* &m_dataProvider;
bool m_windowOpen = true;
int m_currHashFunction = 0;

View File

@ -14,11 +14,13 @@
#include "views/highlight.hpp"
#include "providers/provider.hpp"
namespace hex {
class ViewHexEditor : public View {
public:
ViewHexEditor(FILE* &file, std::vector<Highlight> &highlights);
ViewHexEditor(prv::Provider* &dataProvider, std::vector<Highlight> &highlights);
virtual ~ViewHexEditor();
virtual void createView() override;
@ -27,8 +29,7 @@ namespace hex {
private:
MemoryEditor m_memoryEditor;
FILE* &m_file;
size_t m_fileSize = 0;
prv::Provider* &m_dataProvider;
std::vector<Highlight> &m_highlights;
};

View File

@ -10,18 +10,20 @@
#include <tuple>
#include <cstdio>
#include "providers/provider.hpp"
namespace hex {
class ViewPatternData : public View {
public:
ViewPatternData(FILE* &file,std::vector<Highlight> &highlights);
ViewPatternData(prv::Provider* &dataProvider, std::vector<Highlight> &highlights);
virtual ~ViewPatternData();
virtual void createView() override;
virtual void createMenu() override;
private:
FILE* &m_file;
prv::Provider* &m_dataProvider;
std::vector<Highlight> &m_highlights;
bool m_windowOpen = true;
};

View File

@ -6,6 +6,8 @@
#include "views/view_pattern_data.hpp"
#include "views/view_hashes.hpp"
#include "providers/provider.hpp"
#include <tuple>
#include <vector>
@ -14,13 +16,13 @@ int main() {
// Shared Data
std::vector<hex::Highlight> highlights;
FILE *file = nullptr;
hex::prv::Provider *dataProvider = nullptr;
// Create views
window.addView<hex::ViewHexEditor>(file, highlights);
window.addView<hex::ViewHexEditor>(dataProvider, highlights);
window.addView<hex::ViewPattern>(highlights);
window.addView<hex::ViewPatternData>(file, highlights);
window.addView<hex::ViewHashes>(file);
window.addView<hex::ViewPatternData>(dataProvider, highlights);
window.addView<hex::ViewHashes>(dataProvider);
window.loop();

View File

@ -0,0 +1,59 @@
#include "providers/file_provider.hpp"
#include <cstdio>
namespace hex::prv {
FileProvider::FileProvider(std::string_view path) {
this->m_file = fopen(path.data(), "r+b");
this->m_readable = true;
this->m_writable = true;
if (this->m_file == nullptr) {
this->m_file = fopen(path.data(), "rb");
this->m_writable = false;
}
}
FileProvider::~FileProvider() {
if (this->m_file != nullptr)
fclose(this->m_file);
}
bool FileProvider::isAvailable() {
return this->m_file != nullptr;
}
bool FileProvider::isReadable() {
return this->m_readable;
}
bool FileProvider::isWritable() {
return this->m_writable;
}
void FileProvider::read(u64 offset, void *buffer, size_t size) {
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
return;
fseek(this->m_file, offset, SEEK_SET);
fread(buffer, 1, size, this->m_file);
}
void FileProvider::write(u64 offset, void *buffer, size_t size) {
if (buffer == nullptr || size == 0)
return;
fseek(this->m_file, offset, SEEK_SET);
fwrite(buffer, 1, size, this->m_file);
}
size_t FileProvider::getSize() {
fseek(this->m_file, 0, SEEK_END);
return ftell(this->m_file);
}
}

View File

@ -6,7 +6,7 @@
namespace hex {
ViewHashes::ViewHashes(FILE* &file) : View(), m_file(file) {
ViewHashes::ViewHashes(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) {
}
@ -19,11 +19,15 @@ namespace hex {
if (!this->m_windowOpen)
return;
static bool invalidate = false;
if (ImGui::Begin("Hashing", &this->m_windowOpen)) {
ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav);
ImGui::NewLine();
if (this->m_dataProvider != nullptr && this->m_dataProvider->isAvailable()) {
ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames, sizeof(HashFunctionNames) / sizeof(const char*));
ImGui::NewLine();
@ -31,67 +35,87 @@ namespace hex {
ImGui::NewLine();
ImGui::InputInt("Begin", &this->m_hashStart, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::InputInt("End", &this->m_hashEnd, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::NewLine();
ImGui::Separator();
ImGui::NewLine();
if (this->m_hashEnd >= this->m_hashStart) {
std::vector<u8> buffer;
if (invalidate) {
buffer = std::vector<u8>(this->m_hashEnd - this->m_hashStart + 1, 0x00);
this->m_dataProvider->read(this->m_hashStart, buffer.data(), buffer.size());
}
switch (this->m_currHashFunction) {
case 0: // CRC16
{
if (this->m_file == nullptr)
break;
std::vector<u8> buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00);
fseek(this->m_file, this->m_hashStart, SEEK_SET);
fread(buffer.data(), 1, buffer.size(), this->m_file);
static int polynomial = 0, init = 0;
ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::InputInt("Polynomial", &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::NewLine();
ImGui::Separator();
ImGui::NewLine();
ImGui::LabelText("Result", "%X", crc16(buffer.data(), buffer.size(), polynomial, init));
static u16 result = 0;
if (invalidate)
result = crc16(buffer.data(), buffer.size(), polynomial, init);
ImGui::LabelText("##nolabel", "%X", result);
}
break;
case 1: // CRC32
{
if (this->m_file == nullptr)
break;
std::vector<u8> buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00);
fseek(this->m_file, this->m_hashStart, SEEK_SET);
fread(buffer.data(), 1, buffer.size(), this->m_file);
static int polynomial = 0, init = 0;
ImGui::InputInt("Initial Value", &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::InputInt("Polynomial", &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
ImGui::NewLine();
ImGui::Separator();
ImGui::NewLine();
ImGui::LabelText("Result", "%X", crc32(buffer.data(), buffer.size(), polynomial, init));
static u32 result = 0;
if (invalidate)
result = crc32(buffer.data(), buffer.size(), polynomial, init);
ImGui::LabelText("##nolabel", "%X", result);
}
break;
case 2: // MD5
{
if (this->m_file == nullptr)
break;
static std::array<u32, 4> result;
std::vector<u8> buffer(this->m_hashEnd - this->m_hashStart + 1, 0x00);
fseek(this->m_file, this->m_hashStart, SEEK_SET);
fread(buffer.data(), 1, buffer.size(), this->m_file);
if (invalidate)
result = md5(buffer.data(), buffer.size());
auto result = md5(buffer.data(), buffer.size());
ImGui::LabelText("Result", "%08X%08X%08X%08X", __builtin_bswap32(result[0]), __builtin_bswap32(result[1]), __builtin_bswap32(result[2]), __builtin_bswap32(result[3]));
ImGui::LabelText("##nolabel", "%08X%08X%08X%08X",
__builtin_bswap32(result[0]),
__builtin_bswap32(result[1]),
__builtin_bswap32(result[2]),
__builtin_bswap32(result[3]));
}
break;
}
}
invalidate = false;
ImGui::SameLine();
if (ImGui::Button("Hash"))
invalidate = true;
}
ImGui::EndChild();
ImGui::End();
}

View File

@ -1,20 +1,20 @@
#include "views/view_hexeditor.hpp"
#include "providers/file_provider.hpp"
namespace hex {
ViewHexEditor::ViewHexEditor(FILE *&file, std::vector<Highlight> &highlights)
: View(), m_file(file), m_highlights(highlights) {
ViewHexEditor::ViewHexEditor(prv::Provider* &dataProvider, std::vector<Highlight> &highlights)
: View(), m_dataProvider(dataProvider), m_highlights(highlights) {
this->m_memoryEditor.ReadFn = [](const ImU8 *data, size_t off) -> ImU8 {
ViewHexEditor *_this = (ViewHexEditor *) data;
if (_this->m_file == nullptr)
if (!_this->m_dataProvider->isAvailable() || !_this->m_dataProvider->isReadable())
return 0x00;
fseek(_this->m_file, off, SEEK_SET);
ImU8 byte;
fread(&byte, sizeof(ImU8), 1, _this->m_file);
_this->m_dataProvider->read(off, &byte, sizeof(ImU8));
return byte;
};
@ -22,13 +22,10 @@ namespace hex {
this->m_memoryEditor.WriteFn = [](ImU8 *data, size_t off, ImU8 d) -> void {
ViewHexEditor *_this = (ViewHexEditor *) data;
if (_this->m_file == nullptr)
if (!_this->m_dataProvider->isAvailable() || !_this->m_dataProvider->isWritable())
return;
fseek(_this->m_file, off, SEEK_SET);
fwrite(&d, sizeof(ImU8), 1, _this->m_file);
_this->m_dataProvider->write(off, &d, sizeof(ImU8));
};
this->m_memoryEditor.HighlightFn = [](const ImU8 *data, size_t off, bool next) -> bool {
@ -53,7 +50,7 @@ namespace hex {
ViewHexEditor::~ViewHexEditor() {}
void ViewHexEditor::createView() {
this->m_memoryEditor.DrawWindow("Hex Editor", this, this->m_file == nullptr ? 0x00 : this->m_fileSize);
this->m_memoryEditor.DrawWindow("Hex Editor", this, (this->m_dataProvider == nullptr || !this->m_dataProvider->isReadable()) ? 0x00 : this->m_dataProvider->getSize());
}
void ViewHexEditor::createMenu() {
@ -61,14 +58,10 @@ namespace hex {
if (ImGui::MenuItem("Open File...")) {
auto filePath = openFileDialog();
if (filePath.has_value()) {
if (this->m_file != nullptr)
fclose(this->m_file);
if (this->m_dataProvider != nullptr)
delete this->m_dataProvider;
this->m_file = fopen(filePath->c_str(), "r+b");
fseek(this->m_file, 0, SEEK_END);
this->m_fileSize = ftell(this->m_file);
rewind(this->m_file);
this->m_dataProvider = new prv::FileProvider(filePath.value());
}
}

View File

@ -4,8 +4,8 @@
namespace hex {
ViewPatternData::ViewPatternData(FILE* &file, std::vector<Highlight> &highlights)
: View(), m_file(file), m_highlights(highlights) {
ViewPatternData::ViewPatternData(prv::Provider* &dataProvider, std::vector<Highlight> &highlights)
: View(), m_dataProvider(dataProvider), m_highlights(highlights) {
}
@ -34,13 +34,15 @@ namespace hex {
for (auto& [offset, size, color, name] : this->m_highlights) {
std::vector<u8> buffer(size + 1, 0x00);
this->m_dataProvider->read(offset, buffer.data(), size);
if (size <= 8) {
u64 data = 0;
fseek(this->m_file, offset, SEEK_SET);
fread(buffer.data(), 1, size, this->m_file);
std::memcpy(&data, buffer.data(), size);
if (size <= 8)
ImGui::LabelText(name.c_str(), "[0x%08lx:0x%08lx] %lu (0x%08lx) \"%s\"", offset, offset + size, data, data, makeDisplayable(buffer.data(), buffer.size()).c_str());
}
else
ImGui::LabelText(name.c_str(), "[0x%08lx:0x%08lx] [ ARRAY ] \"%s\"", offset, offset + size, makeDisplayable(buffer.data(), buffer.size()).c_str());
}