diff --git a/CMakeLists.txt b/CMakeLists.txt index 97cf33873..1c587824b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ add_executable(ImHex source/lang/lexer.cpp source/lang/parser.cpp source/lang/validator.cpp + source/lang/evaluator.cpp source/provider/file_provider.cpp diff --git a/include/lang/evaluator.hpp b/include/lang/evaluator.hpp new file mode 100644 index 000000000..6eb201d72 --- /dev/null +++ b/include/lang/evaluator.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "lang/pattern_data.hpp" +#include "ast_node.hpp" + +#include +#include +#include + +namespace hex::lang { + + class Evaluator { + public: + Evaluator(); + + std::pair> evaluate(const std::vector& ast); + + private: + std::unordered_map m_types; + + std::pair createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + std::pair createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + std::pair createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + std::pair createStringPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + std::pair createCustomTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + std::pair createBuiltInTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset); + + }; + +} \ No newline at end of file diff --git a/include/lang/pattern_data.hpp b/include/lang/pattern_data.hpp new file mode 100644 index 000000000..2d2803c06 --- /dev/null +++ b/include/lang/pattern_data.hpp @@ -0,0 +1,389 @@ +#pragma once + +#include +#include + +#include "imgui.h" +#include "imgui_memory_editor.h" + +#include "providers/provider.hpp" +#include "utils.hpp" + +#include + +namespace hex::lang { + + namespace { + + std::string makeDisplayable(u8 *data, size_t size) { + std::string result; + for (u8* c = data; c < (data + size); c++) { + if (iscntrl(*c) || *c > 0x7F) + result += " "; + else + result += *c; + } + + return result; + } + + } + + class PatternData { + public: + PatternData(u64 offset, size_t size, const std::string &name, u32 color = 0) + : m_offset(offset), m_size(size), m_color(color), m_name(name) { + constexpr u32 Palette[] = { 0x50b4771f, 0x500e7fff, 0x502ca02c, 0x502827d6, 0x50bd6794, 0x504b568c, 0x50c277e3, 0x507f7f7f, 0x5022bdbc, 0x50cfbe17 }; + + if (color != 0) + return; + + this->m_color = Palette[PatternData::s_paletteOffset++]; + + if (PatternData::s_paletteOffset >= (sizeof(Palette) / sizeof(u32))) + PatternData::s_paletteOffset = 0; + } + virtual ~PatternData() = default; + + [[nodiscard]] u64 getOffset() const { return this->m_offset; } + [[nodiscard]] size_t getSize() const { return this->m_size; } + + [[nodiscard]] u32 getColor() const { return this->m_color; } + [[nodiscard]] const std::string& getName() const { return this->m_name; } + + virtual void createEntry(prv::Provider* &provider) = 0; + virtual std::string getTypeName() = 0; + + virtual std::optional highlightBytes(size_t offset) { + if (offset >= this->getOffset() && offset < (this->getOffset() + this->getSize())) + return this->getColor(); + else + return { }; + } + + + static void resetPalette() { PatternData::s_paletteOffset = 0; } + + static bool beginPatternDataTable(prv::Provider* &provider, const std::vector &patterns, std::vector &sortedPatterns) { + if (ImGui::BeginTable("##patterndatatable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("Color", 0, -1, ImGui::GetID("color")); + ImGui::TableSetupColumn("Name", 0, -1, ImGui::GetID("name")); + ImGui::TableSetupColumn("Position", 0, -1, ImGui::GetID("position")); + ImGui::TableSetupColumn("Size", 0, -1, ImGui::GetID("size")); + ImGui::TableSetupColumn("Type", 0, -1, ImGui::GetID("type")); + ImGui::TableSetupColumn("Value", 0, -1, ImGui::GetID("value")); + + auto sortSpecs = ImGui::TableGetSortSpecs(); + + if (sortSpecs->SpecsDirty || sortedPatterns.empty()) { + sortedPatterns = patterns; + + std::sort(sortedPatterns.begin(), sortedPatterns.end(), [&sortSpecs, &provider](lang::PatternData* left, lang::PatternData* right) -> bool { + if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("name")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left->getName() > right->getName(); + else + return left->getName() < right->getName(); + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("position")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left->getOffset() > right->getOffset(); + else + return left->getOffset() < right->getOffset(); + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left->getSize() > right->getSize(); + else + return left->getSize() < right->getSize(); + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) { + size_t biggerSize = std::max(left->getSize(), right->getSize()); + std::vector leftBuffer(biggerSize, 0x00), rightBuffer(biggerSize, 0x00); + + provider->read(left->getOffset(), leftBuffer.data(), left->getSize()); + provider->read(right->getOffset(), rightBuffer.data(), right->getSize()); + + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return leftBuffer > rightBuffer; + else + return leftBuffer < rightBuffer; + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("type")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left->getTypeName() > right->getTypeName(); + else + return left->getTypeName() < right->getTypeName(); + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("color")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left->getColor() > right->getColor(); + else + return left->getColor() < right->getColor(); + } + + return false; + }); + + sortSpecs->SpecsDirty = false; + } + + ImGui::TableHeadersRow(); + + return true; + } + + return false; + } + + protected: + void createDefaultEntry(std::string value) { + ImGui::TableNextRow(); + ImGui::TreeNodeEx(this->getName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth); + ImGui::TableNextColumn(); + ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip); + ImGui::TableNextColumn(); + ImGui::Text("%s", this->getName().c_str()); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx : 0x%08lx", this->getOffset(), this->getOffset() + this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx", this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("%s", this->getTypeName().c_str()); + ImGui::TableNextColumn(); + ImGui::Text("%s", value.c_str()); + } + + private: + u64 m_offset; + size_t m_size; + + u32 m_color; + std::string m_name; + + static inline u8 s_paletteOffset = 0; + }; + + + class PatternDataUnsigned : public PatternData { + public: + PatternDataUnsigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } + + void createEntry(prv::Provider* &provider) override { + u64 data = 0; + provider->read(this->getOffset(), &data, this->getSize()); + + this->createDefaultEntry(hex::format("%lu (0x%08lx)", data, data)); + } + + std::string getTypeName() override { + switch (this->getSize()) { + case 1: return "u8"; + case 2: return "u16"; + case 4: return "u32"; + case 8: return "u64"; + case 16: return "u128"; + default: return "Unsigned data"; + } + } + }; + + class PatternDataSigned : public PatternData { + public: + PatternDataSigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } + + void createEntry(prv::Provider* &provider) override { + u64 data = 0; + provider->read(this->getOffset(), &data, this->getSize()); + + s64 signedData = signedData = hex::signExtend(data, this->getSize(), 64); + + this->createDefaultEntry(hex::format("%ld (0x%08lx)", signedData, data)); + } + + std::string getTypeName() override { + switch (this->getSize()) { + case 1: return "s8"; + case 2: return "s16"; + case 4: return "s32"; + case 8: return "s64"; + case 16: return "s128"; + default: return "Signed data"; + } + } + }; + + class PatternDataFloat : public PatternData { + public: + PatternDataFloat(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } + + void createEntry(prv::Provider* &provider) override { + double formatData = 0; + if (this->getSize() == 4) { + float data = 0; + provider->read(this->getOffset(), &data, 4); + formatData = data; + } else if (this->getSize() == 8) { + double data = 0; + provider->read(this->getOffset(), &data, 8); + formatData = data; + } + + this->createDefaultEntry(hex::format("%f (0x%08lx)", formatData, formatData)); + } + + std::string getTypeName() override { + switch (this->getSize()) { + case 4: return "float"; + case 8: return "double"; + default: return "Floating point data"; + } + } + }; + + class PatternDataCharacter : public PatternData { + public: + PatternDataCharacter(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } + + void createEntry(prv::Provider* &provider) override { + char character; + provider->read(this->getOffset(), &character, 1); + + this->createDefaultEntry(hex::format("'%c'", character)); + } + + std::string getTypeName() override { + return "Character"; + } + }; + + class PatternDataString : public PatternData { + public: + PatternDataString(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } + + void createEntry(prv::Provider* &provider) override { + std::vector buffer(this->getSize() + 1, 0x00); + provider->read(this->getOffset(), buffer.data(), this->getSize()); + buffer[this->getSize()] = '\0'; + + this->createDefaultEntry(hex::format("\"%s\"", makeDisplayable(buffer.data(), this->getSize()).c_str())); + } + + std::string getTypeName() override { + return "String"; + } + }; + + class PatternDataArray : public PatternData { + public: + PatternDataArray(u64 offset, size_t size, const std::string &name, const std::vector & entries, u32 color = 0) + : PatternData(offset, size, name, color), m_entries(entries) { } + + void createEntry(prv::Provider* &provider) override { + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip); + ImGui::TableNextColumn(); + bool open = ImGui::TreeNodeEx(this->getName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx : 0x%08lx", this->getOffset(), this->getOffset() + this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx", this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("%s", this->getTypeName().c_str()); + ImGui::TableNextColumn(); + ImGui::Text("%s", "{ ... }"); + + if (open) { + for (auto &member : this->m_entries) + member->createEntry(provider); + + ImGui::TreePop(); + } + } + + std::optional highlightBytes(size_t offset) override{ + for (auto &entry : this->m_entries) { + if (auto color = entry->highlightBytes(offset); color.has_value()) + return color.value(); + } + + return { }; + } + + std::string getTypeName() override { + return this->m_entries[0]->getTypeName() + "[" + std::to_string(this->m_entries.size()) + "]"; + } + + private: + std::vector m_entries; + }; + + class PatternDataStruct : public PatternData { + public: + PatternDataStruct(u64 offset, size_t size, const std::string &name, const std::string &structName, const std::vector & members, u32 color = 0) + : PatternData(offset, size, name, color), m_structName(structName), m_members(members) { } + + void createEntry(prv::Provider* &provider) override { + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_AlphaPreview); + ImGui::TableNextColumn(); + bool open = ImGui::TreeNodeEx(this->getName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx : 0x%08lx", this->getOffset(), this->getOffset() + this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx", this->getSize()); + ImGui::TableNextColumn(); + ImGui::Text("%s", this->getTypeName().c_str()); + ImGui::TableNextColumn(); + ImGui::Text("%s", "{ ... }"); + + if (open) { + for (auto &member : this->m_members) + member->createEntry(provider); + + ImGui::TreePop(); + } + + } + + std::optional highlightBytes(size_t offset) override{ + for (auto &member : this->m_members) { + if (auto color = member->highlightBytes(offset); color.has_value()) + return color.value(); + } + + return { }; + } + + std::string getTypeName() override { + return "struct " + this->m_structName; + } + + private: + std::string m_structName; + std::vector m_members; + std::vector m_sortedMembers; + }; + + class PatternDataEnum : public PatternData { + public: + PatternDataEnum(u64 offset, size_t size, const std::string &name, const std::string &enumName, std::vector> enumValues, u32 color = 0) + : PatternData(offset, size, name, color), m_enumName(enumName), m_enumValues(enumValues) { } + + void createEntry(prv::Provider* &provider) override { + + } + + std::string getTypeName() override { + return "enum " + this->m_enumName; + } + + private: + std::string m_enumName; + std::vector> m_enumValues; + }; + + +} \ No newline at end of file diff --git a/include/lang/results.hpp b/include/lang/results.hpp index 8ba760b05..705e0836e 100644 --- a/include/lang/results.hpp +++ b/include/lang/results.hpp @@ -9,5 +9,6 @@ namespace hex::lang { constexpr Result ResultPreprocessingError(1, 1); constexpr Result ResultLexicalError(2, 1); constexpr Result ResultParseError(3, 1); + constexpr Result ResultEvaluatorError(4, 1); } \ No newline at end of file diff --git a/include/utils.hpp b/include/utils.hpp index 0e3aa27af..b082197d7 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -3,9 +3,10 @@ #include #include +#include +#include #include #include -#include #include #include "lang/token.hpp" @@ -75,4 +76,16 @@ namespace hex { } + class ScopeExit { + public: + ScopeExit(std::function func) : m_func(func) {} + ~ScopeExit() { if (this->m_func != nullptr) this->m_func(); } + + void release() { + this->m_func = nullptr; + } + + private: + std::function m_func; + }; } \ No newline at end of file diff --git a/include/views/pattern_data.hpp b/include/views/pattern_data.hpp deleted file mode 100644 index 2fdaab5b9..000000000 --- a/include/views/pattern_data.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#pragma once - -#include -#include - -#include "providers/provider.hpp" -#include "utils.hpp" - -#include - -namespace hex { - - namespace { - - std::string makeDisplayable(u8 *data, size_t size) { - std::string result; - for (u8* c = data; c < (data + size); c++) { - if (iscntrl(*c) || *c > 0x7F) - result += " "; - else - result += *c; - } - - return result; - } - - } - - class PatternData { - public: - PatternData(u64 offset, size_t size, const std::string &name, u32 color = 0) - : m_offset(offset), m_size(size), m_color(color), m_name(name) { - constexpr u32 Palette[] = { 0x50b4771f, 0x500e7fff, 0x502ca02c, 0x502827d6, 0x50bd6794, 0x504b568c, 0x50c277e3, 0x507f7f7f, 0x5022bdbc, 0x50cfbe17 }; - - this->m_color = Palette[PatternData::s_paletteOffset++]; - - if (PatternData::s_paletteOffset >= (sizeof(Palette) / sizeof(u32))) - PatternData::s_paletteOffset = 0; - } - virtual ~PatternData() = default; - - [[nodiscard]] u64 getOffset() const { return this->m_offset; } - [[nodiscard]] size_t getSize() const { return this->m_size; } - - [[nodiscard]] u32 getColor() const { return this->m_color; } - [[nodiscard]] const std::string& getName() const { return this->m_name; } - - virtual std::string format(prv::Provider* &provider) = 0; - virtual std::string getTypeName() = 0; - - static void resetPalette() { PatternData::s_paletteOffset = 0; } - - private: - u64 m_offset; - size_t m_size; - - u32 m_color; - std::string m_name; - - static inline u8 s_paletteOffset = 0; - }; - - - class PatternDataUnsigned : public PatternData { - public: - PatternDataUnsigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } - - std::string format(prv::Provider* &provider) override { - u64 data = 0; - provider->read(this->getOffset(), &data, this->getSize()); - - return hex::format("%lu (0x%08lx)", data, data); - } - - std::string getTypeName() override { - switch (this->getSize()) { - case 1: return "u8"; - case 2: return "u16"; - case 4: return "u32"; - case 8: return "u64"; - case 16: return "u128"; - default: return "Unsigned data"; - } - } - }; - - class PatternDataSigned : public PatternData { - public: - PatternDataSigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } - - std::string format(prv::Provider* &provider) override { - u64 data = 0; - provider->read(this->getOffset(), &data, this->getSize()); - - s64 signedData = signedData = hex::signExtend(data, this->getSize(), 64); - - return hex::format("%ld (0x%08lx)", signedData, data); - } - - std::string getTypeName() override { - switch (this->getSize()) { - case 1: return "s8"; - case 2: return "s16"; - case 4: return "s32"; - case 8: return "s64"; - case 16: return "s128"; - default: return "Signed data"; - } - } - }; - - class PatternDataFloat : public PatternData { - public: - PatternDataFloat(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } - - std::string format(prv::Provider* &provider) override { - double formatData = 0; - if (this->getSize() == 4) { - float data = 0; - provider->read(this->getOffset(), &data, 4); - formatData = data; - } else if (this->getSize() == 8) { - double data = 0; - provider->read(this->getOffset(), &data, 8); - formatData = data; - } - - return hex::format("%f (0x%08lx)", formatData, formatData); - } - - std::string getTypeName() override { - switch (this->getSize()) { - case 4: return "float"; - case 8: return "double"; - default: return "Floating point data"; - } - } - }; - - class PatternDataCharacter : public PatternData { - public: - PatternDataCharacter(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } - - std::string format(prv::Provider* &provider) override { - char character; - provider->read(this->getOffset(), &character, 1); - - return hex::format("'%c'", character); - } - - std::string getTypeName() override { - return "Character"; - } - }; - - class PatternDataString : public PatternData { - public: - PatternDataString(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(offset, size, name, color) { } - - std::string format(prv::Provider* &provider) override { - std::vector buffer(this->getSize() + 1, 0x00); - provider->read(this->getOffset(), buffer.data(), this->getSize()); - buffer[this->getSize()] = '\0'; - - return hex::format("\"%s\"", makeDisplayable(buffer.data(), this->getSize()).c_str()); - } - - std::string getTypeName() override { - return "String"; - } - }; - - class PatternDataEnum : public PatternData { - public: - PatternDataEnum(u64 offset, size_t size, const std::string &name, const std::string &enumName, std::vector> enumValues, u32 color = 0) - : PatternData(offset, size, name, color), m_enumName(enumName), m_enumValues(enumValues) { } - - std::string format(prv::Provider* &provider) override { - u64 value = 0; - provider->read(this->getOffset(), &value, this->getSize()); - - for (auto [enumValue, name] : this->m_enumValues) { - if (value == enumValue) - return hex::format("%lu (0x%08lx) : %s::%s", value, value, this->m_enumName.c_str(), name.c_str()); - } - - return hex::format("%lu (0x%08lx) : %s::???", value, value, this->m_enumName.c_str()); - } - - std::string getTypeName() override { - return "enum " + this->m_enumName; - } - - private: - std::string m_enumName; - std::vector> m_enumValues; - }; - - -} \ No newline at end of file diff --git a/include/views/view_help.hpp b/include/views/view_help.hpp index 50e974c74..b6ce52972 100644 --- a/include/views/view_help.hpp +++ b/include/views/view_help.hpp @@ -4,7 +4,7 @@ #include "imgui.h" #include "views/view.hpp" -#include "views/pattern_data.hpp" +#include "lang/pattern_data.hpp" #include #include diff --git a/include/views/view_hexeditor.hpp b/include/views/view_hexeditor.hpp index 027fa6477..fac5466dd 100644 --- a/include/views/view_hexeditor.hpp +++ b/include/views/view_hexeditor.hpp @@ -10,7 +10,7 @@ #include #include -#include "views/pattern_data.hpp" +#include "lang/pattern_data.hpp" namespace hex { @@ -20,7 +20,7 @@ namespace hex { class ViewHexEditor : public View { public: - ViewHexEditor(prv::Provider* &dataProvider, std::vector &patternData); + ViewHexEditor(prv::Provider* &dataProvider, std::vector &patternData); ~ViewHexEditor() override; void createView() override; @@ -32,7 +32,7 @@ namespace hex { imgui_addons::ImGuiFileBrowser m_fileBrowser; prv::Provider* &m_dataProvider; - std::vector &m_patternData; + std::vector &m_patternData; char m_searchStringBuffer[0xFFFF] = { 0 }; char m_searchHexBuffer[0xFFFF] = { 0 }; diff --git a/include/views/view_pattern.hpp b/include/views/view_pattern.hpp index 593617acd..ffd202422 100644 --- a/include/views/view_pattern.hpp +++ b/include/views/view_pattern.hpp @@ -3,7 +3,7 @@ #include "lang/ast_node.hpp" #include "views/view.hpp" -#include "views/pattern_data.hpp" +#include "lang/pattern_data.hpp" #include "providers/provider.hpp" @@ -17,7 +17,7 @@ namespace hex { class ViewPattern : public View { public: - explicit ViewPattern(prv::Provider* &dataProvider, std::vector &patternData); + explicit ViewPattern(prv::Provider* &dataProvider, std::vector &patternData); ~ViewPattern() override; void createMenu() override; @@ -26,20 +26,14 @@ namespace hex { private: char *m_buffer = nullptr; - std::vector &m_patternData; + std::vector &m_patternData; prv::Provider* &m_dataProvider; bool m_windowOpen = true; imgui_addons::ImGuiFileBrowser m_fileBrowser; - - void addPatternData(PatternData *patternData); void clearPatternData(); void parsePattern(char *buffer); - - s32 highlightUsingDecls(std::vector &ast, lang::ASTNodeTypeDecl* currTypeDeclNode, lang::ASTNodeVariableDecl* currVarDec, u64 offset, std::string name); - s32 highlightStruct(std::vector &ast, lang::ASTNodeStruct* currStructNode, u64 offset, std::string name); - s32 highlightEnum(std::vector &ast, lang::ASTNodeEnum* currEnumNode, u64 offset, std::string name); }; } \ No newline at end of file diff --git a/include/views/view_pattern_data.hpp b/include/views/view_pattern_data.hpp index b8359302d..5b839660b 100644 --- a/include/views/view_pattern_data.hpp +++ b/include/views/view_pattern_data.hpp @@ -4,7 +4,7 @@ #include "imgui.h" #include "views/view.hpp" -#include "views/pattern_data.hpp" +#include "lang/pattern_data.hpp" #include #include @@ -16,7 +16,7 @@ namespace hex { class ViewPatternData : public View { public: - ViewPatternData(prv::Provider* &dataProvider, std::vector &patternData); + ViewPatternData(prv::Provider* &dataProvider, std::vector &patternData); ~ViewPatternData() override; void createView() override; @@ -24,8 +24,8 @@ namespace hex { private: prv::Provider* &m_dataProvider; - std::vector &m_patternData; - std::vector m_sortedPatternData; + std::vector &m_patternData; + std::vector m_sortedPatternData; bool m_windowOpen = true; }; diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp new file mode 100644 index 000000000..6698f81f7 --- /dev/null +++ b/source/lang/evaluator.cpp @@ -0,0 +1,248 @@ +#include "lang/evaluator.hpp" + +#include + +namespace hex::lang { + + Evaluator::Evaluator() { + + } + + std::pair Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + std::vector members; + + auto structNode = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); + + if (structNode == nullptr) + return { nullptr, 0 }; + + size_t structSize = 0; + for (const auto &node : structNode->getNodes()) { + const auto &member = static_cast(node); + + const auto typeDeclNode = static_cast(this->m_types[member->getCustomVariableTypeName()]); + if (typeDeclNode == nullptr) + return { nullptr, 0 }; + + if (member->getVariableType() == Token::TypeToken::Type::Signed8Bit && member->getArraySize() > 1) { + const auto &[pattern, size] = this->createStringPattern(member, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } else if (member->getVariableType() == Token::TypeToken::Type::CustomType + && typeDeclNode->getAssignedType() == Token::TypeToken::Type::Signed8Bit + && member->getArraySize() > 1) { + + const auto &[pattern, size] = this->createStringPattern(member, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } + else if (member->getArraySize() > 1) { + const auto &[pattern, size] = this->createArrayPattern(member, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } + else if (member->getVariableType() != Token::TypeToken::Type::CustomType) { + const auto &[pattern, size] = this->createBuiltInTypePattern(member, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } + else { + const auto &[pattern, size] = this->createCustomTypePattern(member, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } + } + + return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), structNode->getName(), members, 0x00FFFFFF), structSize }; + } + + std::pair Evaluator::createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + std::vector> enumValues; + + auto *enumType = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); + + if (enumType == nullptr) + return { nullptr, 0 }; + + size_t size = getTypeSize(enumType->getUnderlyingType()); + + return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues()), size }; + } + + std::pair Evaluator::createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + std::vector entries; + + size_t arraySize = 0; + for (u32 i = 0; i < varDeclNode->getArraySize(); i++) { + ASTNodeVariableDecl *nonArrayVarDeclNode = new ASTNodeVariableDecl(varDeclNode->getVariableType(), "[" + std::to_string(i) + "]", varDeclNode->getCustomVariableTypeName(), varDeclNode->getOffset(), 1); + + if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) { + const auto &[pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arraySize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + entries.push_back(pattern); + arraySize += size; + } else { + const auto &[pattern, size] = this->createCustomTypePattern(nonArrayVarDeclNode, offset + arraySize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + entries.push_back(pattern); + arraySize += size; + } + + delete nonArrayVarDeclNode; + } + + return { new PatternDataArray(offset, arraySize, varDeclNode->getVariableName(), entries, 0x00FFFFFF), arraySize }; + } + + std::pair Evaluator::createStringPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + size_t arraySize = varDeclNode->getArraySize(); + + return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName()), arraySize }; + } + + std::pair Evaluator::createCustomTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + auto &currType = this->m_types[varDeclNode->getCustomVariableTypeName()]; + + if (currType == nullptr) + return { nullptr, 0 }; + + switch (currType->getType()) { + case ASTNode::Type::Struct: + return this->createStructPattern(varDeclNode, offset); + case ASTNode::Type::Enum: + return this->createEnumPattern(varDeclNode, offset); + case ASTNode::Type::TypeDecl: + return this->createBuiltInTypePattern(varDeclNode, offset); + } + + return { nullptr, 0 }; + } + + std::pair Evaluator::createBuiltInTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { + auto type = varDeclNode->getVariableType(); + if (type == Token::TypeToken::Type::CustomType) { + const auto &currType = static_cast(this->m_types[varDeclNode->getCustomVariableTypeName()]); + if (currType == nullptr) + return { nullptr, 0 }; + + type = currType->getAssignedType(); + } + + size_t typeSize = getTypeSize(type); + size_t arraySize = varDeclNode->getArraySize(); + + if (isSigned(type)) { + if (typeSize == 1 && arraySize == 1) + return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName()), 1 }; + else if (arraySize > 1) + return createArrayPattern(varDeclNode, offset); + else + return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + } else if (isUnsigned(varDeclNode->getVariableType())) { + if (arraySize > 1) + return createArrayPattern(varDeclNode, offset); + else + return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + } else if (isFloatingPoint(varDeclNode->getVariableType())) { + if (arraySize > 1) + return createArrayPattern(varDeclNode, offset); + else + return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + } + + return { nullptr, 0 }; + } + + std::pair> Evaluator::evaluate(const std::vector &ast) { + + // Evaluate types + for (const auto &node : ast) { + + switch(node->getType()) { + case ASTNode::Type::Struct: + { + auto *structNode = static_cast(node); + this->m_types.emplace(structNode->getName(), structNode); + } + break; + case ASTNode::Type::Enum: + { + auto *enumNode = static_cast(node); + this->m_types.emplace(enumNode->getName(), enumNode); + } + break; + case ASTNode::Type::TypeDecl: + { + auto *typeDeclNode = static_cast(node); + + if (typeDeclNode->getAssignedType() == Token::TypeToken::Type::CustomType) + this->m_types.emplace(typeDeclNode->getTypeName(), this->m_types[typeDeclNode->getAssignedCustomTypeName()]); + else + this->m_types.emplace(typeDeclNode->getTypeName(), typeDeclNode); + } + break; + case ASTNode::Type::VariableDecl: break; + case ASTNode::Type::Scope: break; + } + } + + // Evaluate variable declarations + + std::vector variables; + for (const auto &node : ast) { + if (node->getType() != ASTNode::Type::VariableDecl) + continue; + + auto *varDeclNode = static_cast(node); + + if (varDeclNode->getVariableType() == Token::TypeToken::Type::Signed8Bit && varDeclNode->getArraySize() > 1) { + const auto &[pattern, _] = createStringPattern(varDeclNode, varDeclNode->getOffset().value()); + variables.push_back(pattern); + } + else if (varDeclNode->getArraySize() > 1) { + const auto &[pattern, _] = this->createArrayPattern(varDeclNode, varDeclNode->getOffset().value()); + variables.push_back(pattern); + + } else if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) { + const auto &[pattern, _] = this->createBuiltInTypePattern(varDeclNode, varDeclNode->getOffset().value()); + variables.push_back(pattern); + } else { + const auto &[pattern, _] = this->createCustomTypePattern(varDeclNode, varDeclNode->getOffset().value()); + variables.push_back(pattern); + } + } + + for (const auto &var : variables) + if (var == nullptr) + return { ResultEvaluatorError, { } }; + + return { ResultSuccess, variables }; + } + +} \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 6f7a598af..554484215 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,6 +1,6 @@ #include "window.hpp" -#include "views/pattern_data.hpp" +#include "lang/pattern_data.hpp" #include "views/view_hexeditor.hpp" #include "views/view_pattern.hpp" #include "views/view_pattern_data.hpp" @@ -18,7 +18,7 @@ int main() { hex::Window window; // Shared Data - std::vector patternData; + std::vector patternData; hex::prv::Provider *dataProvider = nullptr; // Create views diff --git a/source/views/view_hexeditor.cpp b/source/views/view_hexeditor.cpp index 9f16f18bc..4c60c17fc 100644 --- a/source/views/view_hexeditor.cpp +++ b/source/views/view_hexeditor.cpp @@ -7,7 +7,7 @@ namespace hex { - ViewHexEditor::ViewHexEditor(prv::Provider* &dataProvider, std::vector &patternData) + ViewHexEditor::ViewHexEditor(prv::Provider* &dataProvider, std::vector &patternData) : View(), m_dataProvider(dataProvider), m_patternData(patternData) { this->m_memoryEditor.ReadFn = [](const ImU8 *data, size_t off) -> ImU8 { @@ -36,12 +36,12 @@ namespace hex { ViewHexEditor *_this = (ViewHexEditor *) data; for (auto& pattern : _this->m_patternData) { - if (next && off == (pattern->getOffset() + pattern->getSize())) { + if (next && pattern->highlightBytes(off - 1) != pattern->highlightBytes(off)) { return false; } - if (off >= pattern->getOffset() && off < (pattern->getOffset() + pattern->getSize())) { - _this->m_memoryEditor.HighlightColor = pattern->getColor(); + if (auto color = pattern->highlightBytes(off); color.has_value()) { + _this->m_memoryEditor.HighlightColor = color.value(); return true; } } diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index 6e78e00bd..c0c9d9621 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -4,11 +4,12 @@ #include "lang/parser.hpp" #include "lang/lexer.hpp" #include "lang/validator.hpp" +#include "lang/evaluator.hpp" #include "utils.hpp" namespace hex { - ViewPattern::ViewPattern(prv::Provider* &dataProvider, std::vector &patternData) + ViewPattern::ViewPattern(prv::Provider* &dataProvider, std::vector &patternData) : View(), m_dataProvider(dataProvider), m_patternData(patternData) { this->m_buffer = new char[0xFF'FFFF]; @@ -84,16 +85,12 @@ namespace hex { } - void ViewPattern::addPatternData(PatternData *patternData) { - this->m_patternData.push_back(patternData); - } - void ViewPattern::clearPatternData() { for (auto &data : this->m_patternData) delete data; this->m_patternData.clear(); - PatternData::resetPalette(); + lang::PatternData::resetPalette(); } template T> @@ -108,10 +105,11 @@ namespace hex { } void ViewPattern::parsePattern(char *buffer) { - static hex::lang::Preprocessor preprocessor; - static hex::lang::Lexer lexer; - static hex::lang::Parser parser; - static hex::lang::Validator validator; + hex::lang::Preprocessor preprocessor; + hex::lang::Lexer lexer; + hex::lang::Parser parser; + hex::lang::Validator validator; + hex::lang::Evaluator evaluator; this->clearPatternData(); this->postEvent(Events::PatternChanged); @@ -127,275 +125,23 @@ namespace hex { auto [parseResult, ast] = parser.parse(tokens); if (parseResult.failed()) { - for(auto &node : ast) delete node; return; } + hex::ScopeExit deleteAst([&ast]{ for(auto &node : ast) delete node; }); + auto validatorResult = validator.validate(ast); if (!validatorResult) { - for(auto &node : ast) delete node; return; } - for (auto &varNode : findNodes(lang::ASTNode::Type::VariableDecl, ast)) { - if (!varNode->getOffset().has_value()) - continue; - - u64 offset = varNode->getOffset().value(); - if (varNode->getVariableType() != lang::Token::TypeToken::Type::CustomType) { - size_t size = getTypeSize(varNode->getVariableType()) * varNode->getArraySize(); - - if (isUnsigned(varNode->getVariableType())) - this->addPatternData(new PatternDataUnsigned(offset, size, varNode->getVariableName())); - else if (isSigned(varNode->getVariableType())) { - if (getTypeSize(varNode->getVariableType()) == 1 && varNode->getArraySize() == 1) - this->addPatternData(new PatternDataCharacter(offset, size, varNode->getVariableName())); - else if (getTypeSize(varNode->getVariableType()) == 1 && varNode->getArraySize() > 1) - this->addPatternData(new PatternDataString(offset, size, varNode->getVariableName())); - else - this->addPatternData(new PatternDataSigned(offset, size, varNode->getVariableName())); - } - else if (isFloatingPoint(varNode->getVariableType())) - this->addPatternData(new PatternDataFloat(offset, size, varNode->getVariableName())); - } else { - for (auto &structNode : findNodes(lang::ASTNode::Type::Struct, ast)) { - if (varNode->getCustomVariableTypeName() == structNode->getName()) { - for (u32 i = 0; i < varNode->getArraySize(); i++) { - std::string name = varNode->getVariableName(); - if (varNode->getArraySize() > 1) - name += "[" + std::to_string(varNode->getArraySize()) + "]"; - - if (size_t size = this->highlightStruct(ast, structNode, offset, name); size == -1) - this->clearPatternData(); - else - offset += size; - } - } - } - - for (auto &enumNode : findNodes(lang::ASTNode::Type::Enum, ast)) { - if (varNode->getCustomVariableTypeName() == enumNode->getName()) { - for (u32 i = 0; i < varNode->getArraySize(); i++) { - std::string name = varNode->getVariableName(); - if (varNode->getArraySize() > 1) - name += "[" + std::to_string(varNode->getArraySize()) + "]"; - - if (size_t size = this->highlightEnum(ast, enumNode, offset, name); size == -1) - this->clearPatternData(); - else - offset += size; - } - } - } - - for (auto &usingNode : findNodes(lang::ASTNode::Type::TypeDecl, ast)) { - if (varNode->getCustomVariableTypeName() == usingNode->getTypeName()) { - for (u32 i = 0; i < varNode->getArraySize(); i++) { - std::string name = varNode->getVariableName(); - if (varNode->getArraySize() > 1) - name += "[" + std::to_string(varNode->getArraySize()) + "]"; - - if (size_t size = this->highlightUsingDecls(ast, usingNode, varNode, offset, name); size == -1) - this->clearPatternData(); - else - offset += size; - } - } - } - } - + auto [evaluateResult, patternData] = evaluator.evaluate(ast); + if (evaluateResult.failed()) { + return; } + this->m_patternData = patternData; - for(auto &node : ast) delete node; this->postEvent(Events::PatternChanged); } - s32 ViewPattern::highlightUsingDecls(std::vector &ast, lang::ASTNodeTypeDecl* currTypeDeclNode, lang::ASTNodeVariableDecl* currVarDecl, u64 offset, std::string name) { - u64 startOffset = offset; - - if (currTypeDeclNode->getAssignedType() != lang::Token::TypeToken::Type::CustomType) { - size_t size = (static_cast(currTypeDeclNode->getAssignedType()) >> 4); - - if (isUnsigned(currTypeDeclNode->getAssignedType())) - this->addPatternData(new PatternDataUnsigned(offset, size, name)); - else if (isSigned(currTypeDeclNode->getAssignedType())) - this->addPatternData(new PatternDataSigned(offset, size, name)); - else if (isFloatingPoint(currTypeDeclNode->getAssignedType())) - this->addPatternData(new PatternDataFloat(offset, size, name)); - - offset += size; - } else { - bool foundType = false; - for (auto &structNode : findNodes(lang::ASTNode::Type::Struct, ast)) { - if (structNode->getName() == currTypeDeclNode->getAssignedCustomTypeName()) { - for (size_t i = 0; i < currVarDecl->getArraySize(); i++) { - size_t size = this->highlightStruct(ast, structNode, offset, name); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - for (auto &enumNode : findNodes(lang::ASTNode::Type::Enum, ast)) { - if (enumNode->getName() == currTypeDeclNode->getAssignedCustomTypeName()) { - for (size_t i = 0; i < currVarDecl->getArraySize(); i++) { - size_t size = this->highlightEnum(ast, enumNode, offset, name); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - - for (auto &typeDeclNode : findNodes(lang::ASTNode::Type::TypeDecl, ast)) { - if (typeDeclNode->getTypeName() == currTypeDeclNode->getAssignedCustomTypeName()) { - for (size_t i = 0; i < currVarDecl->getArraySize(); i++) { - size_t size = this->highlightUsingDecls(ast, typeDeclNode, currVarDecl, offset, name); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - if (!foundType) - return -1; - } - - return offset - startOffset; - } - - s32 ViewPattern::highlightStruct(std::vector &ast, lang::ASTNodeStruct* currStructNode, u64 offset, std::string name) { - u64 startOffset = offset; - - for (auto &node : currStructNode->getNodes()) { - auto varNode = static_cast(node); - - if (varNode->getVariableType() != lang::Token::TypeToken::Type::CustomType) { - size_t size = (static_cast(varNode->getVariableType()) >> 4); - for (size_t i = 0; i < varNode->getArraySize(); i++) { - std::string memberName = name + "." + varNode->getVariableName(); - if (varNode->getArraySize() > 1) - memberName += "[" + std::to_string(i) + "]"; - - if (isUnsigned(varNode->getVariableType())) - this->addPatternData(new PatternDataUnsigned(offset, size, memberName)); - else if (isSigned(varNode->getVariableType())) { - if (getTypeSize(varNode->getVariableType()) == 1 && varNode->getArraySize() == 1) - this->addPatternData(new PatternDataCharacter(offset, size, memberName)); - else if (getTypeSize(varNode->getVariableType()) == 1 && varNode->getArraySize() > 1) { - this->addPatternData(new PatternDataString(offset, size * varNode->getArraySize(), name + "." + varNode->getVariableName())); - offset += size * varNode->getArraySize(); - break; - } - else - this->addPatternData(new PatternDataSigned(offset, size, memberName)); - } - else if (isFloatingPoint(varNode->getVariableType())) - this->addPatternData(new PatternDataFloat(offset, size, memberName)); - - offset += size; - } - } else { - bool foundType = false; - for (auto &structNode : findNodes(lang::ASTNode::Type::Struct, ast)) { - if (structNode->getName() == varNode->getCustomVariableTypeName()) { - for (size_t i = 0; i < varNode->getArraySize(); i++) { - std::string memberName = name + "." + varNode->getVariableName(); - if (varNode->getArraySize() > 1) - memberName += "[" + std::to_string(i) + "]"; - - size_t size = this->highlightStruct(ast, structNode, offset, memberName); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - for (auto &enumNode : findNodes(lang::ASTNode::Type::Enum, ast)) { - if (enumNode->getName() == varNode->getCustomVariableTypeName()) { - for (size_t i = 0; i < varNode->getArraySize(); i++) { - std::string memberName = name + "." + varNode->getVariableName(); - if (varNode->getArraySize() > 1) - memberName += "[" + std::to_string(i) + "]"; - - size_t size = this->highlightEnum(ast, enumNode, offset, memberName); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - for (auto &typeDeclNode : findNodes(lang::ASTNode::Type::TypeDecl, ast)) { - if (typeDeclNode->getTypeName() == varNode->getCustomVariableTypeName()) { - for (size_t i = 0; i < varNode->getArraySize(); i++) { - std::string memberName = name + "." + varNode->getVariableName(); - if (varNode->getArraySize() > 1) - memberName += "[" + std::to_string(i) + "]"; - - size_t size = this->highlightUsingDecls(ast, typeDeclNode, varNode, offset, memberName); - - if (size == -1) - return -1; - - offset += size; - } - - foundType = true; - break; - } - } - - if (!foundType) - return -1; - } - - } - - return offset - startOffset; - } - - s32 ViewPattern::highlightEnum(std::vector &ast, lang::ASTNodeEnum* currEnumNode, u64 offset, std::string name) { - if (!isUnsigned(currEnumNode->getUnderlyingType())) - return -1; - - s32 size = static_cast(currEnumNode->getUnderlyingType()) >> 4; - - if (size > 8) - return -1; - - this->addPatternData(new PatternDataEnum(offset, size, name, currEnumNode->getName(), currEnumNode->getValues())); - - return size; - } - } \ No newline at end of file diff --git a/source/views/view_pattern_data.cpp b/source/views/view_pattern_data.cpp index 334456a06..e82ccaf79 100644 --- a/source/views/view_pattern_data.cpp +++ b/source/views/view_pattern_data.cpp @@ -1,10 +1,11 @@ #include "views/view_pattern_data.hpp" #include "providers/provider.hpp" +#include "lang/pattern_data.hpp" namespace hex { - ViewPatternData::ViewPatternData(prv::Provider* &dataProvider, std::vector &patternData) + ViewPatternData::ViewPatternData(prv::Provider* &dataProvider, std::vector &patternData) : View(), m_dataProvider(dataProvider), m_patternData(patternData) { this->subscribeEvent(Events::PatternChanged, [this](auto data) { @@ -25,85 +26,10 @@ namespace hex { if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { - if (ImGui::BeginTable("##patterndatatable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg)) { - ImGui::TableSetupColumn("Color", 0, -1, ImGui::GetID("color")); - ImGui::TableSetupColumn("Name", 0, -1, ImGui::GetID("name")); - ImGui::TableSetupColumn("Position", 0, -1, ImGui::GetID("position")); - ImGui::TableSetupColumn("Size", 0, -1, ImGui::GetID("size")); - ImGui::TableSetupColumn("Type", 0, -1, ImGui::GetID("type")); - ImGui::TableSetupColumn("Value", 0, -1, ImGui::GetID("value")); - - auto sortSpecs = ImGui::TableGetSortSpecs(); - - if (sortSpecs->SpecsDirty || this->m_sortedPatternData.empty()) { - this->m_sortedPatternData = this->m_patternData; - - std::sort(this->m_sortedPatternData.begin(), this->m_sortedPatternData.end(), [this, &sortSpecs](PatternData* left, PatternData* right) -> bool { - if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("name")) { - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return left->getName() > right->getName(); - else - return left->getName() < right->getName(); - } - else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("position")) { - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return left->getOffset() > right->getOffset(); - else - return left->getOffset() < right->getOffset(); - } - else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) { - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return left->getSize() > right->getSize(); - else - return left->getSize() < right->getSize(); - } - else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) { - size_t biggerSize = std::max(left->getSize(), right->getSize()); - std::vector leftBuffer(biggerSize, 0x00), rightBuffer(biggerSize, 0x00); - - this->m_dataProvider->read(left->getOffset(), leftBuffer.data(), left->getSize()); - this->m_dataProvider->read(right->getOffset(), rightBuffer.data(), right->getSize()); - - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return leftBuffer > rightBuffer; - else - return leftBuffer < rightBuffer; - } - else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("type")) { - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return left->getTypeName() > right->getTypeName(); - else - return left->getTypeName() < right->getTypeName(); - } - else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("color")) { - if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) - return left->getColor() > right->getColor(); - else - return left->getColor() < right->getColor(); - } - - return false; - }); - - sortSpecs->SpecsDirty = false; - } - - ImGui::TableHeadersRow(); + if (lang::PatternData::beginPatternDataTable(this->m_dataProvider, this->m_patternData, this->m_sortedPatternData)) { u32 rowCount = 0; for (auto& patternData : this->m_sortedPatternData) { - ImGui::TableNextRow(ImGuiTableRowFlags_Headers); - ImGui::TableNextColumn(); - ImGui::ColorButton("color", ImColor(patternData->getColor()), ImGuiColorEditFlags_NoTooltip); - ImGui::TableNextColumn(); - ImGui::Text("%s", patternData->getName().c_str()); - ImGui::TableNextColumn(); - ImGui::Text("0x%08lx : 0x%08lx", patternData->getOffset(), patternData->getOffset() + patternData->getSize()); - ImGui::TableNextColumn(); - ImGui::Text("0x%08lx", patternData->getSize()); - ImGui::TableNextColumn(); - ImGui::Text("%s", patternData->getTypeName().c_str()); - ImGui::TableNextColumn(); - ImGui::Text("%s", patternData->format(this->m_dataProvider).c_str()); + patternData->createEntry(this->m_dataProvider); ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030); rowCount++; }