From ccac2e497d41156715b8f3a17703ede2447dfd88 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 9 Sep 2021 12:58:44 +0200 Subject: [PATCH] sys: Finish implementing constants view and its store --- include/views/view_constants.hpp | 4 +- include/views/view_store.hpp | 2 +- plugins/builtin/source/lang/de_DE.cpp | 11 ++- plugins/builtin/source/lang/en_US.cpp | 9 +- plugins/builtin/source/lang/it_IT.cpp | 10 ++- .../libimhex/include/hex/helpers/utils.hpp | 15 ++++ source/views/view_constants.cpp | 84 ++++++++++++++----- source/views/view_store.cpp | 9 +- 8 files changed, 111 insertions(+), 33 deletions(-) diff --git a/include/views/view_constants.hpp b/include/views/view_constants.hpp index 8505aab93..fdf4edaa2 100644 --- a/include/views/view_constants.hpp +++ b/include/views/view_constants.hpp @@ -32,8 +32,8 @@ namespace hex { void reloadConstants(); std::vector m_constants; - std::vector m_filteredConstants; - std::string m_search; + std::vector m_filterIndices; + std::string m_filter; }; } \ No newline at end of file diff --git a/include/views/view_store.hpp b/include/views/view_store.hpp index cb23ea401..e9e2b2b1f 100644 --- a/include/views/view_store.hpp +++ b/include/views/view_store.hpp @@ -40,7 +40,7 @@ namespace hex { std::future> m_apiRequest; std::future> m_download; - std::vector m_patterns, m_magics, m_includes; + std::vector m_patterns, m_includes, m_magics, m_constants; void drawStore(); diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index 3dac51e63..fdf55d387 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -296,18 +296,23 @@ namespace hex::plugin::builtin { { "hex.view.yara.no_rules", "Keine Yara Regeln gefunden. Platziere sie in ImHex's 'yara' Ordner" }, { "hex.view.constants.name", "Konstanten" }, + { "hex.view.constants.row.category", "Kategorie" }, + { "hex.view.constants.row.name", "Name" }, + { "hex.view.constants.row.desc", "Beschreibung" }, + { "hex.view.constants.row.value", "Wert" }, { "hex.view.store.name", "Content Store" }, - { "hex.view.store.desc", "Downloade extra Content von ImHex's online Datenbank" }, + { "hex.view.store.desc", "Downloade zusätzlichen Content von ImHex's online Datenbank" }, { "hex.view.store.reload", "Neu laden" }, - { "hex.view.store.table.name", "Name" }, - { "hex.view.store.table.description", "Beschreibung" }, + { "hex.view.store.row.name", "Name" }, + { "hex.view.store.row.description", "Beschreibung" }, { "hex.view.store.download", "Download" }, { "hex.view.store.update", "Update" }, { "hex.view.store.remove", "Entfernen" }, { "hex.view.store.tab.patterns", "Patterns" }, { "hex.view.store.tab.libraries", "Libraries" }, { "hex.view.store.tab.magics", "Magic Files" }, + { "hex.view.store.tab.constants", "Konstanten" }, { "hex.view.store.loading", "Store inhalt wird geladen..." }, /* Builtin plugin features */ diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 258d54326..7dd67ead5 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -296,18 +296,23 @@ namespace hex::plugin::builtin { { "hex.view.yara.no_rules", "No YARA rules found. Put them in ImHex's 'yara' folder" }, { "hex.view.constants.name", "Constants" }, + { "hex.view.constants.row.category", "Category" }, + { "hex.view.constants.row.name", "Name" }, + { "hex.view.constants.row.desc", "Description" }, + { "hex.view.constants.row.value", "Value" }, { "hex.view.store.name", "Content Store" }, { "hex.view.store.desc", "Download new content from ImHex's online database" }, { "hex.view.store.reload", "Reload" }, - { "hex.view.store.table.name", "Name" }, - { "hex.view.store.table.description", "Description" }, + { "hex.view.store.row.name", "Name" }, + { "hex.view.store.row.description", "Description" }, { "hex.view.store.download", "Download" }, { "hex.view.store.update", "Update" }, { "hex.view.store.remove", "Remove" }, { "hex.view.store.tab.patterns", "Patterns" }, { "hex.view.store.tab.libraries", "Libraries" }, { "hex.view.store.tab.magics", "Magic Files" }, + { "hex.view.store.tab.constants", "Constants" }, { "hex.view.store.loading", "Loading store content..." }, diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index ee98d0a44..385fc5768 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -295,18 +295,22 @@ namespace hex::plugin::builtin { { "hex.view.yara.no_rules", "Nessuna regola di YARA. Aggiungile in nella cartella 'yara' di 'ImHex'" }, // { "hex.view.constants.name", "Constants" }, - + //{ "hex.view.constants.row.category", "Category" }, + //{ "hex.view.constants.row.name", "Name" }, + //{ "hex.view.constants.row.desc", "Description" }, + //{ "hex.view.constants.row.value", "Value" }, //{ "hex.view.store.name", "Content Store" }, // { "hex.view.store.desc", "Download new content from ImHex's online database" }, // { "hex.view.store.reload", "Reload" }, - // { "hex.view.store.table.name", "Name" }, - // { "hex.view.store.table.description", "Description" }, + // { "hex.view.store.row.name", "Name" }, + // { "hex.view.store.row.description", "Description" }, // { "hex.view.store.download", "Download" }, // { "hex.view.store.update", "Update" }, // { "hex.view.store.remove", "Remove" }, // { "hex.view.store.tab.patterns", "Patterns" }, // { "hex.view.store.tab.libraries", "Libraries" }, // { "hex.view.store.tab.magics", "Magic Files" }, + // { "hex.view.store.tab.constants", "Constants" }, // { "hex.view.store.loading", "Loading store content..." }, diff --git a/plugins/libimhex/include/hex/helpers/utils.hpp b/plugins/libimhex/include/hex/helpers/utils.hpp index d4d4f4261..aa8383055 100644 --- a/plugins/libimhex/include/hex/helpers/utils.hpp +++ b/plugins/libimhex/include/hex/helpers/utils.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -158,6 +159,20 @@ namespace hex { float float16ToFloat32(u16 float16); + inline bool equalsIgnoreCase(const std::string &left, const std::string &right) { + return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) { + return tolower(a) == tolower(b); + }); + } + + inline bool containsIgnoreCase(const std::string &a, const std::string &b) { + auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) { + return std::toupper(ch1) == std::toupper(ch2); + }); + + return iter != a.end(); + } + namespace scope_guard { #define SCOPE_GUARD ::hex::scope_guard::ScopeGuardOnExit() + [&]() diff --git a/source/views/view_constants.cpp b/source/views/view_constants.cpp index 0ce122117..4e0f2a681 100644 --- a/source/views/view_constants.cpp +++ b/source/views/view_constants.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -11,7 +12,9 @@ namespace hex { ViewConstants::ViewConstants() : View("hex.view.constants.name") { this->reloadConstants(); - this->m_search.resize(0xFFF, 0x00); + + this->m_filter.reserve(0xFFFF); + std::memset(this->m_filter.data(), 0x00, this->m_filter.capacity()); } ViewConstants::~ViewConstants() { @@ -20,6 +23,7 @@ namespace hex { void ViewConstants::reloadConstants() { this->m_constants.clear(); + this->m_filterIndices.clear(); for (auto &path : hex::getPath(ImHexPath::Constants)) { if (!std::filesystem::exists(path)) continue; @@ -49,14 +53,13 @@ namespace hex { else throw std::runtime_error("Invalid type"); + this->m_filterIndices.push_back(this->m_constants.size()); this->m_constants.push_back(constant); } } catch (...) { - log::info("Error"); + log::error("Failed to parse constants file {}", file.path().string()); continue; } - - } } } @@ -64,39 +67,82 @@ namespace hex { void ViewConstants::drawContent() { if (ImGui::Begin(View::toWindowName("hex.view.constants.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { - if (ImGui::InputText("##search", this->m_search.data(), this->m_search.size())) { - this->m_filteredConstants.clear(); - for (auto &constant : this->m_constants) { - if (constant.value.starts_with(this->m_search.c_str()) || constant.name.starts_with(this->m_search.c_str()) || constant.description.starts_with(this->m_search.c_str())) - this->m_filteredConstants.push_back(&constant); + ImGui::InputText("##search", this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) { + auto &view = *static_cast(data->UserData); + view.m_filter.resize(data->BufTextLen); + + view.m_filterIndices.clear(); + for (u64 i = 0; i < view.m_constants.size(); i++) { + auto &constant = view.m_constants[i]; + if (hex::containsIgnoreCase(constant.name, data->Buf) || + hex::containsIgnoreCase(constant.category, data->Buf) || + hex::containsIgnoreCase(constant.description, data->Buf) || + hex::containsIgnoreCase(constant.value, data->Buf)) + view.m_filterIndices.push_back(i); } - } + + return 0; + }, this); if (ImGui::BeginTable("##strings", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) { ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("hex.view.constants.category"_lang, 0, -1, ImGui::GetID("category")); - ImGui::TableSetupColumn("hex.view.constants.name"_lang, 0, -1, ImGui::GetID("name")); - ImGui::TableSetupColumn("hex.view.constants.desc"_lang, 0, -1, ImGui::GetID("desc")); - ImGui::TableSetupColumn("hex.view.constants.value"_lang, 0, -1, ImGui::GetID("value")); + ImGui::TableSetupColumn("hex.view.constants.row.category"_lang, 0, -1, ImGui::GetID("category")); + ImGui::TableSetupColumn("hex.view.constants.row.name"_lang, 0, -1, ImGui::GetID("name")); + ImGui::TableSetupColumn("hex.view.constants.row.desc"_lang, 0, -1, ImGui::GetID("desc")); + ImGui::TableSetupColumn("hex.view.constants.row.value"_lang, 0, -1, ImGui::GetID("value")); + + auto sortSpecs = ImGui::TableGetSortSpecs(); + + if (sortSpecs->SpecsDirty) { + std::sort(this->m_constants.begin(), this->m_constants.end(), + [&sortSpecs](Constant &left, Constant &right) -> bool { + if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("category")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.category > right.category; + else + return left.category < right.category; + } else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("name")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.name > right.name; + else + return left.name < right.name; + } else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("desc")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.description > right.description; + else + return left.description < right.description; + } else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("value")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.value > right.value; + else + return left.value < right.value; + } + + return false; + }); + + sortSpecs->SpecsDirty = false; + } ImGui::TableHeadersRow(); ImGuiListClipper clipper; - clipper.Begin(this->m_filteredConstants.size()); + clipper.Begin(this->m_filterIndices.size()); while (clipper.Step()) { for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + auto &constant = this->m_constants[this->m_filterIndices[i]]; ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("%s", this->m_filteredConstants[i]->category.c_str()); + ImGui::Text("%s", constant.category.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s", this->m_filteredConstants[i]->name.c_str()); + ImGui::Text("%s", constant.name.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s", this->m_filteredConstants[i]->description.c_str()); + ImGui::Text("%s", constant.description.c_str()); ImGui::TableNextColumn(); - ImGui::Text("%s", this->m_filteredConstants[i]->value.c_str()); + ImGui::Text("%s", constant.value.c_str()); } } clipper.End(); diff --git a/source/views/view_store.cpp b/source/views/view_store.cpp index a85edcf61..07d05b936 100644 --- a/source/views/view_store.cpp +++ b/source/views/view_store.cpp @@ -38,8 +38,8 @@ namespace hex { if (ImGui::BeginTabItem(title)) { if (ImGui::BeginTable("##pattern_language", 3, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_RowBg)) { ImGui::TableSetupScrollFreeze(0, 1); - ImGui::TableSetupColumn("hex.view.store.table.name"_lang, ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("hex.view.store.table.description"_lang, ImGuiTableColumnFlags_None); + ImGui::TableSetupColumn("hex.view.store.row.name"_lang, ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("hex.view.store.row.description"_lang, ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); ImGui::TableHeadersRow(); @@ -108,6 +108,7 @@ namespace hex { drawTab("hex.view.store.tab.magics"_lang, ImHexPath::Magic, this->m_magics, []{ magic::compile(); }); + drawTab("hex.view.store.tab.constants"_lang, ImHexPath::Constants, this->m_constants, []{}); ImGui::EndTabBar(); } @@ -139,7 +140,7 @@ namespace hex { StoreEntry storeEntry = { entry["name"], entry["desc"], entry["file"], entry["url"], entry["hash"], false, false, false }; // Check if file is installed already or has an update available - for (auto folder : hex::getPath(pathType)) { + for (const auto &folder : hex::getPath(pathType)) { auto path = folder / fs::path(storeEntry.fileName); @@ -167,6 +168,8 @@ namespace hex { parseStoreEntries(json, "patterns", ImHexPath::Patterns, this->m_patterns); parseStoreEntries(json, "includes", ImHexPath::PatternsInclude, this->m_includes); parseStoreEntries(json, "magic", ImHexPath::Magic, this->m_magics); + parseStoreEntries(json, "constants", ImHexPath::Constants, this->m_constants); + } this->m_apiRequest = { };