Abstracted FILE handle into a generic data provider class
This commit is contained in:
parent
c87bc6aebe
commit
434bb3494a
@ -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
|
||||
|
28
include/providers/file_provider.hpp
Normal file
28
include/providers/file_provider.hpp
Normal 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;
|
||||
};
|
||||
|
||||
}
|
21
include/providers/provider.hpp
Normal file
21
include/providers/provider.hpp
Normal 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;
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
|
||||
|
59
source/provider/file_provider.cpp
Normal file
59
source/provider/file_provider.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
ViewHashes::ViewHashes(FILE* &file) : View(), m_file(file) {
|
||||
ViewHashes::ViewHashes(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) {
|
||||
|
||||
}
|
||||
|
||||
@ -19,77 +19,101 @@ 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();
|
||||
|
||||
ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames, sizeof(HashFunctionNames) / sizeof(const char*));
|
||||
if (this->m_dataProvider != nullptr && this->m_dataProvider->isAvailable()) {
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
ImGui::NewLine();
|
||||
ImGui::Combo("Hash Function", &this->m_currHashFunction, HashFunctionNames, sizeof(HashFunctionNames) / sizeof(const char*));
|
||||
|
||||
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();
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
ImGui::NewLine();
|
||||
ImGui::InputInt("Begin", &this->m_hashStart, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
switch (this->m_currHashFunction) {
|
||||
case 0: // CRC16
|
||||
{
|
||||
if (this->m_file == nullptr)
|
||||
break;
|
||||
ImGui::InputInt("End", &this->m_hashEnd, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
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);
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
ImGui::NewLine();
|
||||
|
||||
static int polynomial = 0, init = 0;
|
||||
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
|
||||
{
|
||||
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();
|
||||
|
||||
static u16 result = 0;
|
||||
|
||||
if (invalidate)
|
||||
result = crc16(buffer.data(), buffer.size(), polynomial, init);
|
||||
|
||||
ImGui::LabelText("##nolabel", "%X", result);
|
||||
}
|
||||
break;
|
||||
case 1: // CRC32
|
||||
{
|
||||
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();
|
||||
|
||||
static u32 result = 0;
|
||||
|
||||
if (invalidate)
|
||||
result = crc32(buffer.data(), buffer.size(), polynomial, init);
|
||||
|
||||
ImGui::LabelText("##nolabel", "%X", result);
|
||||
}
|
||||
break;
|
||||
case 2: // MD5
|
||||
{
|
||||
static std::array<u32, 4> result;
|
||||
|
||||
if (invalidate)
|
||||
result = md5(buffer.data(), buffer.size());
|
||||
|
||||
ImGui::LabelText("##nolabel", "%08X%08X%08X%08X",
|
||||
__builtin_bswap32(result[0]),
|
||||
__builtin_bswap32(result[1]),
|
||||
__builtin_bswap32(result[2]),
|
||||
__builtin_bswap32(result[3]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
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);
|
||||
invalidate = false;
|
||||
|
||||
static int polynomial = 0, init = 0;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Hash"))
|
||||
invalidate = true;
|
||||
|
||||
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));
|
||||
}
|
||||
break;
|
||||
case 2: // MD5
|
||||
{
|
||||
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);
|
||||
|
||||
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]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
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)
|
||||
this->m_dataProvider->read(offset, buffer.data(), size);
|
||||
|
||||
if (size <= 8) {
|
||||
u64 data = 0;
|
||||
std::memcpy(&data, buffer.data(), size);
|
||||
|
||||
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());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user