From 372908ba9d6caf5127c68462c1781ccfd0c77191 Mon Sep 17 00:00:00 2001 From: qdlmcfresh Date: Thu, 25 Nov 2021 08:46:42 +0100 Subject: [PATCH] add regex filter in string view (#345) * Filter by regex in string view * Dont recompile the regex for every string, display error message * localization * Use data->Buf for pattern creation / searching The filter string seems to get updated after the callback finished. Therefore the search string was always 1 character behind the actual string in the textfield when calling find() / creating the regex. --- include/views/view_strings.hpp | 2 ++ plugins/builtin/source/lang/de_DE.cpp | 1 + plugins/builtin/source/lang/en_US.cpp | 1 + source/views/view_strings.cpp | 24 +++++++++++++++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/views/view_strings.hpp b/include/views/view_strings.hpp index c3f436ae0..a5e3a6545 100644 --- a/include/views/view_strings.hpp +++ b/include/views/view_strings.hpp @@ -24,6 +24,8 @@ namespace hex { private: bool m_searching = false; + bool m_regex = false; + bool m_pattern_parsed = false; std::vector m_foundStrings; std::vector m_filterIndices; diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index cea6fb026..84d4defe4 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -284,6 +284,7 @@ namespace hex::plugin::builtin { { "hex.view.strings.min_length", "Minimallänge" }, { "hex.view.strings.filter", "Filter" }, { "hex.view.strings.extract", "Extrahieren" }, + { "hex.view.strings.regex_error", "Ungültiges Regex" }, { "hex.view.strings.searching", "Suchen..." }, { "hex.view.strings.offset", "Offset" }, { "hex.view.strings.size", "Grösse" }, diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 1216b06c4..24b6a55da 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -287,6 +287,7 @@ namespace hex::plugin::builtin { { "hex.view.strings.min_length", "Minimum length" }, { "hex.view.strings.filter", "Filter" }, { "hex.view.strings.extract", "Extract" }, + { "hex.view.strings.regex_error", "Invalid regex" }, { "hex.view.strings.searching", "Searching..." }, { "hex.view.strings.offset", "Offset" }, { "hex.view.strings.size", "Size" }, diff --git a/source/views/view_strings.cpp b/source/views/view_strings.cpp index b035c2550..f28ec7897 100644 --- a/source/views/view_strings.cpp +++ b/source/views/view_strings.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -99,18 +100,35 @@ namespace hex { if (ImGui::InputInt("hex.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0)) this->m_foundStrings.clear(); + ImGui::Checkbox("Regex", &this->m_regex); + ImGui::InputText("hex.view.strings.filter"_lang, 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(); + std::regex pattern; + if (view.m_regex) { + try { + pattern = std::regex(data->Buf); + view.m_pattern_parsed = true; + } catch (std::regex_error &e) { + view.m_pattern_parsed = false; + } + } for (u64 i = 0; i < view.m_foundStrings.size(); i++) { - if (readString(view.m_foundStrings[i]).find(data->Buf) != std::string::npos) + if(view.m_regex){ + if(view.m_pattern_parsed && std::regex_search(readString(view.m_foundStrings[i]), pattern)) + view.m_filterIndices.push_back(i); + } + else if(readString(view.m_foundStrings[i]).find(data->Buf) != std::string::npos) { view.m_filterIndices.push_back(i); + } } - return 0; }, this); + if(this->m_regex && !this->m_pattern_parsed){ + ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "hex.view.strings.regex_error"_lang); + } if (ImGui::Button("hex.view.strings.extract"_lang)) this->searchStrings();