mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-01 21:17:44 -05:00
Refactor, added a pattern data display
This commit is contained in:
20
include/views/highlight.hpp
Normal file
20
include/views/highlight.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct Highlight {
|
||||
Highlight(u64 offset, size_t size, u32 color, std::string name)
|
||||
: offset(offset), size(size), color(color), name(name) {
|
||||
|
||||
}
|
||||
|
||||
u64 offset;
|
||||
size_t size;
|
||||
u32 color;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -12,106 +12,25 @@
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "views/highlight.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
class ViewHexEditor : public View {
|
||||
public:
|
||||
ViewHexEditor() : View() {
|
||||
this->m_memoryEditor.ReadFn = [](const ImU8* data, size_t off) -> ImU8 {
|
||||
ViewHexEditor *_this = (ViewHexEditor*)data;
|
||||
ViewHexEditor(FILE* &file, std::vector<Highlight> &highlights);
|
||||
virtual ~ViewHexEditor();
|
||||
|
||||
if (_this->m_file == nullptr)
|
||||
return 0x00;
|
||||
|
||||
fseek(_this->m_file, off, SEEK_SET);
|
||||
|
||||
ImU8 byte;
|
||||
fread(&byte, sizeof(ImU8), 1, _this->m_file);
|
||||
|
||||
return byte;
|
||||
};
|
||||
|
||||
this->m_memoryEditor.WriteFn = [](ImU8* data, size_t off, ImU8 d) -> void {
|
||||
ViewHexEditor *_this = (ViewHexEditor*)data;
|
||||
|
||||
if (_this->m_file == nullptr)
|
||||
return;
|
||||
|
||||
fseek(_this->m_file, off, SEEK_SET);
|
||||
|
||||
fwrite(&d, sizeof(ImU8), 1, _this->m_file);
|
||||
|
||||
};
|
||||
|
||||
this->m_memoryEditor.HighlightFn = [](const ImU8* data, size_t off, bool next) -> bool {
|
||||
ViewHexEditor *_this = (ViewHexEditor*)data;
|
||||
|
||||
for (auto& [offset, size, color] : _this->m_highlights) {
|
||||
if (next && off == (offset + size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (off >= offset && off < (offset + size)) {
|
||||
_this->m_memoryEditor.HighlightColor = color;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_this->m_memoryEditor.HighlightColor = 0x50C08080;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
virtual ~ViewHexEditor() { }
|
||||
|
||||
virtual void createView() override {
|
||||
this->m_memoryEditor.DrawWindow("Hex Editor", this, this->m_file == nullptr ? 0x00 : this->m_fileSize);
|
||||
}
|
||||
|
||||
virtual void createMenu() override {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open File...")) {
|
||||
auto filePath = openFileDialog();
|
||||
if (filePath.has_value()) {
|
||||
if (this->m_file != nullptr)
|
||||
fclose(this->m_file);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Window")) {
|
||||
ImGui::MenuItem("Hex View", "", &this->m_memoryEditor.Open);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void setHighlight(u64 offset, size_t size, u32 color = 0) {
|
||||
if (color == 0)
|
||||
color = std::mt19937(std::random_device()())();
|
||||
|
||||
color |= 0xFF00'0000;
|
||||
|
||||
this->m_highlights.emplace_back(offset, size, color);
|
||||
}
|
||||
|
||||
void clearHighlights() {
|
||||
this->m_highlights.clear();
|
||||
}
|
||||
virtual void createView() override;
|
||||
virtual void createMenu() override;
|
||||
|
||||
private:
|
||||
MemoryEditor m_memoryEditor;
|
||||
|
||||
FILE *m_file = nullptr;
|
||||
FILE* &m_file;
|
||||
size_t m_fileSize = 0;
|
||||
|
||||
std::vector<std::tuple<u64, size_t, u32>> m_highlights;
|
||||
std::vector<Highlight> &m_highlights;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -8,207 +8,30 @@
|
||||
#include <concepts>
|
||||
#include <cstring>
|
||||
|
||||
#include "views/view_hexeditor.hpp"
|
||||
#include "views/highlight.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
class ViewPattern : public View {
|
||||
public:
|
||||
ViewPattern(ViewHexEditor *hexEditor) : View(), m_hexEditor(hexEditor) {
|
||||
this->m_buffer = new char[0xFFFFFF];
|
||||
std::memset(this->m_buffer, 0x00, 0xFFFFFF);
|
||||
}
|
||||
virtual ~ViewPattern() {
|
||||
delete[] this->m_buffer;
|
||||
}
|
||||
ViewPattern(std::vector<Highlight> &highlights);
|
||||
virtual ~ViewPattern();
|
||||
|
||||
virtual void createMenu() {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Load pattern...")) {
|
||||
auto filePath = openFileDialog();
|
||||
if (filePath.has_value()) {
|
||||
FILE *file = fopen(filePath->c_str(), "r+b");
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
size_t size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
if (size > 0xFF'FFFF)
|
||||
return;
|
||||
|
||||
fread(this->m_buffer, size, 1, file);
|
||||
|
||||
fclose(file);
|
||||
|
||||
this->parsePattern(this->m_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Window")) {
|
||||
ImGui::MenuItem("Pattern View", "", &this->m_windowOpen);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void createView() override {
|
||||
if (!this->m_windowOpen)
|
||||
return;
|
||||
|
||||
ImGui::Begin("Pattern", &this->m_windowOpen, ImGuiWindowFlags_None);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||
|
||||
auto size = ImGui::GetWindowSize();
|
||||
size.y -= 50;
|
||||
ImGui::InputTextMultiline("Pattern", this->m_buffer, 0xFFFF, size, ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_CallbackEdit,
|
||||
[](ImGuiInputTextCallbackData* data) -> int {
|
||||
auto _this = static_cast<ViewPattern*>(data->UserData);
|
||||
|
||||
_this->parsePattern(data->Buf);
|
||||
|
||||
return 0;
|
||||
}, this
|
||||
);
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::End();
|
||||
}
|
||||
virtual void createMenu() override;
|
||||
virtual void createView() override;
|
||||
|
||||
private:
|
||||
char *m_buffer;
|
||||
|
||||
ViewHexEditor *m_hexEditor;
|
||||
std::vector<Highlight> &m_highlights;
|
||||
bool m_windowOpen = true;
|
||||
|
||||
void parsePattern(char *buffer) {
|
||||
static hex::lang::Lexer lexer;
|
||||
static hex::lang::Parser parser;
|
||||
|
||||
this->m_hexEditor->clearHighlights();
|
||||
void setHighlight(u64 offset, size_t size, std::string name, u32 color = 0);
|
||||
void parsePattern(char *buffer);
|
||||
|
||||
auto [lexResult, tokens] = lexer.lex(buffer);
|
||||
|
||||
if (lexResult.failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto [parseResult, ast] = parser.parse(tokens);
|
||||
if (parseResult.failed()) {
|
||||
for(auto &node : ast) delete node;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &varNode : this->findNodes<lang::ASTNodeVariableDecl>(lang::ASTNode::Type::VariableDecl, ast)) {
|
||||
if (!varNode->getOffset().has_value())
|
||||
continue;
|
||||
|
||||
u64 offset = varNode->getOffset().value();
|
||||
if (varNode->getVariableType() != lang::Token::TypeToken::Type::CustomType) {
|
||||
this->m_hexEditor->setHighlight(offset, static_cast<u32>(varNode->getVariableType()) >> 4);
|
||||
} else {
|
||||
for (auto &structNode : this->findNodes<lang::ASTNodeStruct>(lang::ASTNode::Type::Struct, ast))
|
||||
if (varNode->getCustomVariableTypeName() == structNode->getName())
|
||||
if (this->highlightStruct(ast, structNode, offset) == -1)
|
||||
this->m_hexEditor->clearHighlights();
|
||||
|
||||
for (auto &usingNode : this->findNodes<lang::ASTNodeTypeDecl>(lang::ASTNode::Type::TypeDecl, ast))
|
||||
if (varNode->getCustomVariableTypeName() == usingNode->getTypeName())
|
||||
if (this->highlightUsingDecls(ast, usingNode, offset) == -1)
|
||||
this->m_hexEditor->clearHighlights();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(auto &node : ast) delete node;
|
||||
}
|
||||
|
||||
template<std::derived_from<lang::ASTNode> T>
|
||||
std::vector<T*> findNodes(const lang::ASTNode::Type type, const std::vector<lang::ASTNode*> &nodes) const noexcept {
|
||||
std::vector<T*> result;
|
||||
|
||||
for (const auto & node : nodes)
|
||||
if (node->getType() == type)
|
||||
result.push_back(static_cast<T*>(node));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 highlightUsingDecls(std::vector<lang::ASTNode*> &ast, lang::ASTNodeTypeDecl* currTypeDeclNode, u64 offset) {
|
||||
if (currTypeDeclNode->getAssignedType() != lang::Token::TypeToken::Type::CustomType) {
|
||||
size_t size = static_cast<u32>(currTypeDeclNode->getAssignedType()) >> 4;
|
||||
|
||||
this->m_hexEditor->setHighlight(offset, size);
|
||||
offset += size;
|
||||
} else {
|
||||
bool foundType = false;
|
||||
for (auto &structNode : findNodes<lang::ASTNodeStruct>(lang::ASTNode::Type::Struct, ast))
|
||||
if (structNode->getName() == currTypeDeclNode->getAssignedCustomTypeName()) {
|
||||
offset = this->highlightStruct(ast, structNode, offset);
|
||||
foundType = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto &typeDeclNode : findNodes<lang::ASTNodeTypeDecl>(lang::ASTNode::Type::TypeDecl, ast))
|
||||
if (typeDeclNode->getTypeName() == currTypeDeclNode->getAssignedCustomTypeName()) {
|
||||
offset = this->highlightUsingDecls(ast, typeDeclNode, offset);
|
||||
foundType = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!foundType)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
s32 highlightStruct(std::vector<lang::ASTNode*> &ast, lang::ASTNodeStruct* currStructNode, u64 offset) {
|
||||
u64 startOffset = offset;
|
||||
|
||||
for (auto &node : currStructNode->getNodes()) {
|
||||
auto var = static_cast<lang::ASTNodeVariableDecl*>(node);
|
||||
|
||||
if (var->getVariableType() != lang::Token::TypeToken::Type::CustomType) {
|
||||
size_t size = static_cast<u32>(var->getVariableType()) >> 4;
|
||||
|
||||
this->m_hexEditor->setHighlight(offset, size);
|
||||
offset += size;
|
||||
} else {
|
||||
bool foundType = false;
|
||||
for (auto &structNode : findNodes<lang::ASTNodeStruct>(lang::ASTNode::Type::Struct, ast))
|
||||
if (structNode->getName() == var->getCustomVariableTypeName()) {
|
||||
auto size = this->highlightStruct(ast, structNode, offset);
|
||||
|
||||
if (size == -1)
|
||||
return -1;
|
||||
|
||||
offset += size;
|
||||
foundType = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto &typeDeclNode : findNodes<lang::ASTNodeTypeDecl>(lang::ASTNode::Type::TypeDecl, ast))
|
||||
if (typeDeclNode->getTypeName() == var->getCustomVariableTypeName()) {
|
||||
auto size = this->highlightUsingDecls(ast, typeDeclNode, offset);
|
||||
|
||||
if (size == -1)
|
||||
return -1;
|
||||
|
||||
offset = size;
|
||||
foundType = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!foundType)
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return offset - startOffset;
|
||||
}
|
||||
s32 highlightUsingDecls(std::vector<lang::ASTNode*> &ast, lang::ASTNodeTypeDecl* currTypeDeclNode, lang::ASTNodeVariableDecl* currVarDec, u64 offset);
|
||||
s32 highlightStruct(std::vector<lang::ASTNode*> &ast, lang::ASTNodeStruct* currStructNode, u64 offset);
|
||||
};
|
||||
|
||||
}
|
||||
29
include/views/view_pattern_data.hpp
Normal file
29
include/views/view_pattern_data.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "views/view.hpp"
|
||||
#include "views/highlight.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <cstdio>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class ViewPatternData : public View {
|
||||
public:
|
||||
ViewPatternData(FILE* &file,std::vector<Highlight> &highlights);
|
||||
virtual ~ViewPatternData();
|
||||
|
||||
virtual void createView() override;
|
||||
virtual void createMenu() override;
|
||||
|
||||
private:
|
||||
FILE* &m_file;
|
||||
std::vector<Highlight> &m_highlights;
|
||||
bool m_windowOpen = true;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user