feat: Replace useless constants view with a constant search option in the Find view

This commit is contained in:
WerWolv 2025-12-02 23:02:44 +01:00
parent da0c1674a6
commit d4df465633
27 changed files with 218 additions and 291 deletions

View File

@ -27,9 +27,10 @@ EXPORT_MODULE namespace hex {
struct FindOccurrence {
Region region;
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
enum class DecodeType : u8 { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
bool selected;
std::string string;
};
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;

View File

@ -109,7 +109,6 @@ add_imhex_plugin(
source/content/views/view_command_palette.cpp
source/content/views/view_settings.cpp
source/content/views/view_data_processor.cpp
source/content/views/view_constants.cpp
source/content/views/view_store.cpp
source/content/views/view_provider_settings.cpp
source/content/views/view_find.cpp
@ -123,6 +122,8 @@ add_imhex_plugin(
source/content/views/fullscreen/view_fullscreen_file_info.cpp
source/content/text_highlighting/pattern_language.cpp
source/content/helpers/constants.cpp
INCLUDES
include

View File

@ -0,0 +1,27 @@
#pragma once
#include <string>
#include <vector>
#include <hex/helpers/binary_pattern.hpp>
namespace hex::plugin::builtin {
struct Constant {
std::string name;
std::string description;
BinaryPattern value;
};
class ConstantGroup {
public:
explicit ConstantGroup(const std::fs::path &path);
[[nodiscard]] const std::string& getName() const { return m_name; }
const std::vector<Constant>& getConstants() const { return m_constants; }
private:
std::string m_name;
std::vector<Constant> m_constants;
};
}

View File

@ -1,38 +0,0 @@
#pragma once
#include <hex/ui/view.hpp>
#include <string>
namespace hex::plugin::builtin {
enum class ConstantType
{
Int10,
Int16BigEndian,
Int16LittleEndian
};
struct Constant {
std::string name, description;
std::string category;
ConstantType type;
std::string value;
};
class ViewConstants : public View::Window {
public:
explicit ViewConstants();
~ViewConstants() override = default;
void drawContent() override;
private:
void reloadConstants();
std::vector<Constant> m_constants;
std::vector<size_t> m_filterIndices;
std::string m_filter;
};
}

View File

@ -46,7 +46,8 @@ namespace hex::plugin::builtin {
Sequence,
Regex,
BinaryPattern,
Value
Value,
Constants
} mode = Mode::Strings;
enum class StringType : int { ASCII = 0, UTF8 = 1, UTF16LE = 2, UTF16BE = 3, ASCII_UTF16LE = 4, ASCII_UTF16BE = 5 };
@ -100,6 +101,10 @@ namespace hex::plugin::builtin {
} type = Type::U8;
} value;
struct Constants {
u32 alignment = 1;
} constants;
} m_searchSettings, m_decodeSettings;
using OccurrenceTree = wolv::container::IntervalTree<Occurrence>;
@ -120,6 +125,7 @@ namespace hex::plugin::builtin {
static std::vector<Occurrence> searchRegex(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Regex &settings);
static std::vector<Occurrence> searchBinaryPattern(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::BinaryPattern &settings);
static std::vector<Occurrence> searchValue(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Value &settings);
static std::vector<Occurrence> searchConstants(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Constants &settings);
void drawContextMenu(Occurrence &target, const std::string &value);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -662,11 +662,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "In View öffnen",
"hex.builtin.view.bookmarks.tooltip.unlock": "Entsperren",
"hex.builtin.view.command_palette.name": "Befehlspalette",
"hex.builtin.view.constants.name": "Konstanten",
"hex.builtin.view.constants.row.category": "Kategorie",
"hex.builtin.view.constants.row.desc": "Beschreibung",
"hex.builtin.view.constants.row.name": "Name",
"hex.builtin.view.constants.row.value": "Wert",
"hex.builtin.view.find.constants": "Konstanten",
"hex.builtin.view.data_inspector.invert": "Invertieren",
"hex.builtin.view.data_inspector.name": "Dateninspektor",
"hex.builtin.view.data_inspector.no_data": "Keine Bytes ausgewählt",

View File

@ -739,11 +739,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Open in new View",
"hex.builtin.view.bookmarks.tooltip.unlock": "Unlock",
"hex.builtin.view.command_palette.name": "Command Palette",
"hex.builtin.view.constants.name": "Constants",
"hex.builtin.view.constants.row.category": "Category",
"hex.builtin.view.constants.row.desc": "Description",
"hex.builtin.view.constants.row.name": "Name",
"hex.builtin.view.constants.row.value": "Value",
"hex.builtin.view.find.constants": "Constants",
"hex.builtin.view.data_inspector.menu.copy": "Copy Value",
"hex.builtin.view.data_inspector.menu.edit": "Edit Value",
"hex.builtin.view.data_inspector.execution_error": "Custom row evaluation error",
@ -770,6 +766,7 @@
"hex.builtin.view.find.context.replace": "Replace",
"hex.builtin.view.find.context.replace.ascii": "ASCII",
"hex.builtin.view.find.context.replace.hex": "Hex",
"hex.builtin.view.find.constants": "Constants",
"hex.builtin.view.find.demangled": "Demangled",
"hex.builtin.view.find.name": "Find",
"hex.builtin.view.replace.name": "Replace",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Abrir en nueva vista",
"hex.builtin.view.bookmarks.tooltip.unlock": "Desbloquear",
"hex.builtin.view.command_palette.name": "Paleta de Comandos",
"hex.builtin.view.constants.name": "Constantes",
"hex.builtin.view.constants.row.category": "Categoría",
"hex.builtin.view.constants.row.desc": "Descripción",
"hex.builtin.view.constants.row.name": "Nombre",
"hex.builtin.view.constants.row.value": "Valor",
"hex.builtin.view.find.constants": "Constantes",
"hex.builtin.view.data_inspector.invert": "Invertir",
"hex.builtin.view.data_inspector.name": "Inspector de Datos",
"hex.builtin.view.data_inspector.no_data": "No se han seleccionado bytes",

View File

@ -712,11 +712,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Ouvrir dans une nouvelle vue",
"hex.builtin.view.bookmarks.tooltip.unlock": "Déverrouiller",
"hex.builtin.view.command_palette.name": "Palette de commandes",
"hex.builtin.view.constants.name": "Constantes",
"hex.builtin.view.constants.row.category": "Catégorie",
"hex.builtin.view.constants.row.desc": "Description",
"hex.builtin.view.constants.row.name": "Nom",
"hex.builtin.view.constants.row.value": "Valeur",
"hex.builtin.view.find.constants": "Constantes",
"hex.builtin.view.data_inspector.menu.copy": "Copier la valeur",
"hex.builtin.view.data_inspector.menu.edit": "Modifier la valeur",
"hex.builtin.view.data_inspector.execution_error": "Erreur d'évaluation de ligne personnalisée",

View File

@ -656,11 +656,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Megnyitás új nézetben",
"hex.builtin.view.bookmarks.tooltip.unlock": "Feloldás",
"hex.builtin.view.command_palette.name": "Parancspaletta",
"hex.builtin.view.constants.name": "Konstansok",
"hex.builtin.view.constants.row.category": "Kategória",
"hex.builtin.view.constants.row.desc": "Leírás",
"hex.builtin.view.constants.row.name": "Név",
"hex.builtin.view.constants.row.value": "Érték",
"hex.builtin.view.find.constants": "Konstansok",
"hex.builtin.view.data_inspector.invert": "Megfordít",
"hex.builtin.view.data_inspector.name": "Adatértelmező",
"hex.builtin.view.data_inspector.no_data": "Nincs kijelölt bájt",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "",
"hex.builtin.view.bookmarks.tooltip.unlock": "",
"hex.builtin.view.command_palette.name": "Tavola dei Comandi",
"hex.builtin.view.constants.name": "Costanti",
"hex.builtin.view.constants.row.category": "Categoria",
"hex.builtin.view.constants.row.desc": "Descrizione",
"hex.builtin.view.constants.row.name": "Nome",
"hex.builtin.view.constants.row.value": "Valore",
"hex.builtin.view.find.constants": "Costanti",
"hex.builtin.view.data_inspector.invert": "",
"hex.builtin.view.data_inspector.name": "Ispezione Dati",
"hex.builtin.view.data_inspector.no_data": "Nessun byte selezionato",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "",
"hex.builtin.view.bookmarks.tooltip.unlock": "",
"hex.builtin.view.command_palette.name": "コマンドパレット",
"hex.builtin.view.constants.name": "定数",
"hex.builtin.view.constants.row.category": "カテゴリ",
"hex.builtin.view.constants.row.desc": "記述",
"hex.builtin.view.constants.row.name": "名前",
"hex.builtin.view.constants.row.value": "値",
"hex.builtin.view.find.constants": "定数",
"hex.builtin.view.data_inspector.invert": "反転",
"hex.builtin.view.data_inspector.name": "データインスペクタ",
"hex.builtin.view.data_inspector.no_data": "範囲が選択されていません",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "새 보기에서 열기",
"hex.builtin.view.bookmarks.tooltip.unlock": "잠금 해제",
"hex.builtin.view.command_palette.name": "명령 팔레트",
"hex.builtin.view.constants.name": "상수",
"hex.builtin.view.constants.row.category": "종류",
"hex.builtin.view.constants.row.desc": "설명",
"hex.builtin.view.constants.row.name": "이름",
"hex.builtin.view.constants.row.value": "값",
"hex.builtin.view.find.constants": "상수",
"hex.builtin.view.data_inspector.invert": "반전",
"hex.builtin.view.data_inspector.name": "데이터 변환기",
"hex.builtin.view.data_inspector.no_data": "선택된 바이트가 없습니다",

View File

@ -714,11 +714,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Otwórz w nowym widoku",
"hex.builtin.view.bookmarks.tooltip.unlock": "Odblokuj",
"hex.builtin.view.command_palette.name": "Paleta poleceń",
"hex.builtin.view.constants.name": "Stałe",
"hex.builtin.view.constants.row.category": "Kategoria",
"hex.builtin.view.constants.row.desc": "Opis",
"hex.builtin.view.constants.row.name": "Nazwa",
"hex.builtin.view.constants.row.value": "Wartość",
"hex.builtin.view.find.constants": "Stałe",
"hex.builtin.view.data_inspector.menu.copy": "Kopiuj wartość",
"hex.builtin.view.data_inspector.menu.edit": "Edytuj wartość",
"hex.builtin.view.data_inspector.execution_error": "Błąd ewaluacji niestandardowego wiersza",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "",
"hex.builtin.view.bookmarks.tooltip.unlock": "",
"hex.builtin.view.command_palette.name": "Paleta de Comandos",
"hex.builtin.view.constants.name": "Constantes",
"hex.builtin.view.constants.row.category": "Categoria",
"hex.builtin.view.constants.row.desc": "Descrição",
"hex.builtin.view.constants.row.name": "Nome",
"hex.builtin.view.constants.row.value": "Valor",
"hex.builtin.view.find.constants": "Constantes",
"hex.builtin.view.data_inspector.invert": "Inverter",
"hex.builtin.view.data_inspector.name": "Inspecionador de Dados",
"hex.builtin.view.data_inspector.no_data": "Nenhum Byte Selecionado",

View File

@ -690,11 +690,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Открыть в другом пространстве",
"hex.builtin.view.bookmarks.tooltip.unlock": "Разблокировать",
"hex.builtin.view.command_palette.name": "Палитра комманд",
"hex.builtin.view.constants.name": "Константы",
"hex.builtin.view.constants.row.category": "Категория",
"hex.builtin.view.constants.row.desc": "Описание",
"hex.builtin.view.constants.row.name": "Имя",
"hex.builtin.view.constants.row.value": "Значение",
"hex.builtin.view.find.constants": "Константы",
"hex.builtin.view.data_inspector.execution_error": "Ошибка обработки пользовательского ряда",
"hex.builtin.view.data_inspector.invert": "Инвертировать",
"hex.builtin.view.data_inspector.name": "Анализатор данных",

View File

@ -712,11 +712,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "Відкрити у новому вікні",
"hex.builtin.view.bookmarks.tooltip.unlock": "Розблокувати",
"hex.builtin.view.command_palette.name": "Палітра команд",
"hex.builtin.view.constants.name": "Константи",
"hex.builtin.view.constants.row.category": "Категорія",
"hex.builtin.view.constants.row.desc": "Опис",
"hex.builtin.view.constants.row.name": "Ім'я",
"hex.builtin.view.constants.row.value": "Значення",
"hex.builtin.view.find.constants": "Константи",
"hex.builtin.view.data_inspector.menu.copy": "Копіювати значення",
"hex.builtin.view.data_inspector.execution_error": "Помилка обробки користувацького рядка",
"hex.builtin.view.data_inspector.invert": "Інвертувати",

View File

@ -716,11 +716,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "在新窗口打开",
"hex.builtin.view.bookmarks.tooltip.unlock": "解锁",
"hex.builtin.view.command_palette.name": "命令栏",
"hex.builtin.view.constants.name": "常量",
"hex.builtin.view.constants.row.category": "分类",
"hex.builtin.view.constants.row.desc": "描述",
"hex.builtin.view.constants.row.name": "名称",
"hex.builtin.view.constants.row.value": "值",
"hex.builtin.view.find.constants": "常量",
"hex.builtin.view.data_inspector.menu.copy": "复制值",
"hex.builtin.view.data_inspector.menu.edit": "编辑值",
"hex.builtin.view.data_inspector.execution_error": "自定义行计算错误",

View File

@ -658,11 +658,7 @@
"hex.builtin.view.bookmarks.tooltip.open_in_view": "",
"hex.builtin.view.bookmarks.tooltip.unlock": "解鎖",
"hex.builtin.view.command_palette.name": "命令選擇區",
"hex.builtin.view.constants.name": "常數",
"hex.builtin.view.constants.row.category": "類別",
"hex.builtin.view.constants.row.desc": "說明",
"hex.builtin.view.constants.row.name": "名稱",
"hex.builtin.view.constants.row.value": "數值",
"hex.builtin.view.find.constants": "常數",
"hex.builtin.view.data_inspector.invert": "反轉",
"hex.builtin.view.data_inspector.name": "資料檢查器",
"hex.builtin.view.data_inspector.no_data": "未選取位元組",

View File

@ -122,11 +122,6 @@ Pos=214,201
Size=600,350
Collapsed=0
[Window][###hex.builtin.view.constants.name]
Pos=419,-124
Size=652,660
Collapsed=0
[Window][###hex.disassembler.view.disassembler.name]
Pos=1004,-204
Size=1336,1320
@ -146,7 +141,6 @@ DockSpace ID=0x81A8BB71 Window=0xF9B0A590 Pos=161,350 Size=2560,1427 Split
[ImHex][General]
hex.builtin.view.bookmarks.name=0
hex.builtin.view.command_palette.name=0
hex.builtin.view.constants.name=0
hex.builtin.view.data_inspector.name=1
hex.builtin.view.data_processor.name=0
hex.diffing.view.diff.name=0

View File

@ -122,11 +122,6 @@ Pos=214,201
Size=600,350
Collapsed=0
[Window][###hex.builtin.view.constants.name]
Pos=419,-124
Size=652,660
Collapsed=0
[Window][###hex.disassembler.view.disassembler.name]
Pos=1004,-204
Size=1336,1320
@ -147,7 +142,6 @@ DockSpace ID=0x81A8BB71 Window=0xF9B0A590 Pos=161,350 Size=2560,1427 Split
hex.builtin.view.achievements.name=0
hex.builtin.view.bookmarks.name=0
hex.builtin.view.command_palette.name=0
hex.builtin.view.constants.name=0
hex.builtin.view.data_inspector.name=0
hex.builtin.view.data_processor.name=0
hex.diffing.view.diff.name=0

View File

@ -0,0 +1,37 @@
#include <content/helpers/constants.hpp>
#include <nlohmann/json.hpp>
#include <wolv/io/file.hpp>
#include <wolv/utils/string.hpp>
namespace hex::plugin::builtin {
ConstantGroup::ConstantGroup(const std::fs::path &path) {
if (!wolv::io::fs::exists(path))
throw std::runtime_error("Path does not exist");
if (path.extension() != ".json")
throw std::runtime_error("Invalid constants file extension");
try {
auto fileData = wolv::io::File(path, wolv::io::File::Mode::Read).readString();
auto content = nlohmann::json::parse(fileData);
m_name = content.at("name").get<std::string>();
const auto values = content.at("values");
for (const auto &value : values) {
Constant constant = {};
constant.name = value.at("name").get<std::string>();
if (value.contains("desc"))
constant.description = value.at("desc").get<std::string>();
constant.value = BinaryPattern(value.at("value").get<std::string>());
m_constants.push_back(constant);
}
} catch (...) {
throw std::runtime_error("Failed to parse constants file " + wolv::util::toUTF8String(path));
}
}
}

View File

@ -10,7 +10,6 @@
#include "content/views/view_command_palette.hpp"
#include "content/views/view_settings.hpp"
#include "content/views/view_data_processor.hpp"
#include "content/views/view_constants.hpp"
#include "content/views/view_store.hpp"
#include "content/views/view_provider_settings.hpp"
#include "content/views/view_find.hpp"
@ -37,7 +36,6 @@ namespace hex::plugin::builtin {
ContentRegistry::Views::add<ViewAbout>();
ContentRegistry::Views::add<ViewSettings>();
ContentRegistry::Views::add<ViewDataProcessor>();
//ContentRegistry::Views::add<ViewConstants>();
ContentRegistry::Views::add<ViewStore>();
ContentRegistry::Views::add<ViewProviderSettings>();
ContentRegistry::Views::add<ViewFind>();

View File

@ -1,152 +0,0 @@
#include "content/views/view_constants.hpp"
#include <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/string.hpp>
#include <wolv/io/file.hpp>
#include <filesystem>
#include <nlohmann/json.hpp>
#include <fonts/vscode_icons.hpp>
namespace hex::plugin::builtin {
ViewConstants::ViewConstants() : View::Window("hex.builtin.view.constants.name", ICON_VS_SYMBOL_CONSTANT) {
this->reloadConstants();
}
void ViewConstants::reloadConstants() {
m_constants.clear();
m_filterIndices.clear();
for (const auto &path : paths::Constants.read()) {
if (!wolv::io::fs::exists(path)) continue;
std::error_code error;
for (auto &file : std::fs::directory_iterator(path, error)) {
if (!file.is_regular_file()) continue;
if (file.path().extension() != ".json") continue;
if (file.path().filename().u8string().starts_with('_')) continue;
try {
auto fileData = wolv::io::File(file.path(), wolv::io::File::Mode::Read).readString();
auto content = nlohmann::json::parse(fileData);
for (auto value : content.at("values")) {
Constant constant;
constant.category = content.at("name").get<std::string>();
constant.name = value.at("name").get<std::string>();
if (value.contains("desc"))
constant.description = value.at("desc").get<std::string>();
constant.value = value.at("value").get<std::string>();
auto type = value.at("type");
if (type == "int10")
constant.type = ConstantType::Int10;
else if (type == "int16be")
constant.type = ConstantType::Int16BigEndian;
else if (type == "int16le")
constant.type = ConstantType::Int16LittleEndian;
else
throw std::runtime_error("Invalid type");
m_filterIndices.push_back(m_constants.size());
m_constants.push_back(constant);
}
} catch (...) {
log::error("Failed to parse constants file {}", wolv::util::toUTF8String(file.path()));
}
}
}
}
void ViewConstants::drawContent() {
ImGui::PushItemWidth(-1);
if (ImGuiExt::InputTextIcon("##search", ICON_VS_FILTER, m_filter)) {
m_filterIndices.clear();
// Filter the constants according to the entered value
for (u64 i = 0; i < m_constants.size(); i++) {
auto &constant = m_constants[i];
if (hex::containsIgnoreCase(constant.name, m_filter) ||
hex::containsIgnoreCase(constant.category, m_filter) ||
hex::containsIgnoreCase(constant.description, m_filter) ||
hex::containsIgnoreCase(constant.value, m_filter))
m_filterIndices.push_back(i);
}
}
ImGui::PopItemWidth();
if (ImGui::BeginTable("##strings", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.builtin.view.constants.row.category"_lang, 0, -1, ImGui::GetID("category"));
ImGui::TableSetupColumn("hex.builtin.view.constants.row.name"_lang, 0, -1, ImGui::GetID("name"));
ImGui::TableSetupColumn("hex.builtin.view.constants.row.desc"_lang, 0, -1, ImGui::GetID("desc"));
ImGui::TableSetupColumn("hex.builtin.view.constants.row.value"_lang, 0, -1, ImGui::GetID("value"));
auto sortSpecs = ImGui::TableGetSortSpecs();
// Handle table sorting
if (sortSpecs->SpecsDirty) {
std::sort(m_constants.begin(), m_constants.end(), [&sortSpecs](const Constant &left, const 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(m_filterIndices.size());
// Draw the constants table
while (clipper.Step()) {
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto &constant = m_constants[m_filterIndices[i]];
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted(constant.category.c_str());
ImGui::TableNextColumn();
ImGui::TextUnformatted(constant.name.c_str());
ImGui::TableNextColumn();
ImGui::TextUnformatted(constant.description.c_str());
ImGui::TableNextColumn();
ImGui::TextUnformatted(constant.value.c_str());
}
}
clipper.End();
ImGui::EndTable();
}
}
}

View File

@ -17,6 +17,10 @@
#include <boost/regex.hpp>
#include <content/helpers/constants.hpp>
#include <hex/helpers/default_paths.hpp>
#include <toasts/toast_notification.hpp>
namespace hex::plugin::builtin {
ViewFind::ViewFind() : View::Window("hex.builtin.view.find.name", ICON_VS_SEARCH) {
@ -55,8 +59,8 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn();
{
auto region = occurrence.value.region;
const auto value = this->decodeValue(ImHexApi::Provider::get(), occurrence.value, 256);
auto region = occurrence.value->region;
const auto value = this->decodeValue(ImHexApi::Provider::get(), *occurrence.value, 256);
ImGui::ColorButton("##color", ImColor(HighlightColor()), ImGuiColorEditFlags_AlphaOpaque);
ImGui::SameLine(0, 10);
@ -291,7 +295,7 @@ namespace hex::plugin::builtin {
if (!validChar || startAddress + countedCharacters == endAddress) {
if (countedCharacters >= settings.minLength) {
if (!settings.nullTermination || byte == 0x00) {
results.push_back(Occurrence { Region { startAddress, size_t(countedCharacters) }, decodeType, endian, false });
results.push_back(Occurrence { Region { startAddress, size_t(countedCharacters) }, endian, decodeType, false, {} });
}
}
@ -379,7 +383,7 @@ namespace hex::plugin::builtin {
auto address = occurrence.getAddress();
reader.seek(address + 1);
results.push_back(Occurrence{ Region { address, bytes.size() }, decodeType, endian, false });
results.push_back(Occurrence{ Region { address, bytes.size() }, endian, decodeType, false, {} });
progress = address - searchRegion.getStartAddress();
}
@ -440,7 +444,7 @@ namespace hex::plugin::builtin {
if (matchedBytes == settings.pattern.getSize()) {
auto occurrenceAddress = it.getAddress() - (patternSize - 1);
results.push_back(Occurrence { Region { occurrenceAddress, patternSize }, Occurrence::DecodeType::Binary, std::endian::native, false });
results.push_back(Occurrence { Region { occurrenceAddress, patternSize }, std::endian::native, Occurrence::DecodeType::Binary, false, {} });
it.setAddress(occurrenceAddress);
matchedBytes = 0;
}
@ -466,7 +470,7 @@ namespace hex::plugin::builtin {
}
if (match)
results.push_back(Occurrence { Region { address, patternSize }, Occurrence::DecodeType::Binary, std::endian::native, false });
results.push_back(Occurrence { Region { address, patternSize }, std::endian::native, Occurrence::DecodeType::Binary, false, {} });
}
}
@ -550,7 +554,96 @@ namespace hex::plugin::builtin {
}
}();
results.push_back(Occurrence { Region { address, size }, decodeType, settings.endian, false });
results.push_back(Occurrence { Region { address, size }, settings.endian, decodeType, false, {} });
}
}
return results;
}
std::vector<ViewFind::Occurrence> ViewFind::searchConstants(Task &task, prv::Provider* provider, Region searchRegion, const SearchSettings::Constants &settings) {
std::vector<Occurrence> results;
std::vector<ConstantGroup> constantGroups;
for (const auto &path : paths::Constants.read()) {
for (const auto &entry : std::fs::directory_iterator(path)) {
try {
constantGroups.emplace_back(entry.path());
} catch (const std::exception &e) {
ui::ToastError::open(fmt::format("Failed to load constant group from {}: {}", wolv::util::toUTF8String(entry.path()), e.what()));
}
}
}
auto reader = prv::ProviderReader(provider);
reader.seek(searchRegion.getStartAddress());
reader.setEndAddress(searchRegion.getEndAddress());
u64 constantCount = 0;
for (const auto &group : constantGroups) {
constantCount += group.getConstants().size();
}
task.setMaxValue(constantCount * searchRegion.getSize());
u64 progress = 0;
for (const auto &group : constantGroups) {
for (const auto &constant : group.getConstants()) {
const auto &pattern = constant.value;
const size_t patternSize = pattern.getSize();
if (settings.alignment == 1) {
u32 matchedBytes = 0;
for (auto it = reader.begin(); it < reader.end(); it += 1) {
auto byte = *it;
task.update(progress + it.getAddress());
if (pattern.matchesByte(byte, matchedBytes)) {
matchedBytes++;
if (matchedBytes == pattern.getSize()) {
auto occurrenceAddress = it.getAddress() - (patternSize - 1);
results.push_back(Occurrence {
Region { occurrenceAddress, patternSize },
std::endian::native,
Occurrence::DecodeType::ASCII,
false,
fmt::format("[{}] {}", group.getName(), constant.name)
});
it.setAddress(occurrenceAddress);
matchedBytes = 0;
}
} else {
if (matchedBytes > 0)
it -= matchedBytes;
matchedBytes = 0;
}
}
} else {
std::vector<u8> data(patternSize);
for (u64 address = searchRegion.getStartAddress(); address < searchRegion.getEndAddress(); address += settings.alignment) {
reader.read(address, data.data(), data.size());
task.update(address);
bool match = true;
for (u32 i = 0; i < patternSize; i++) {
if (!pattern.matchesByte(data[i], i)) {
match = false;
break;
}
}
if (match)
results.push_back(Occurrence {
Region { address, patternSize },
std::endian::native,
Occurrence::DecodeType::ASCII,
false,
fmt::format("[] {}", group.getName(), constant.name)
});
}
}
progress += searchRegion.getSize();
}
}
@ -592,9 +685,12 @@ namespace hex::plugin::builtin {
case Value:
m_foundOccurrences.get(provider) = searchValue(task, provider, searchRegion, settings.value);
break;
case Constants:
m_foundOccurrences.get(provider) = searchConstants(task, provider, searchRegion, settings.constants);
break;
}
m_sortedOccurrences.get(provider) = m_foundOccurrences.get(provider);
m_sortedOccurrences.get(provider).clear();
m_lastSelectedOccurrence = nullptr;
for (const auto &occurrence : m_foundOccurrences.get(provider))
@ -636,16 +732,16 @@ namespace hex::plugin::builtin {
result += hex::encodeByteString({ bytes[i] });
break;
case Unsigned:
result += formatBytes<u64>(bytes, occurrence.endian);
result = formatBytes<u64>(bytes, occurrence.endian);
break;
case Signed:
result += formatBytes<i64>(bytes, occurrence.endian);
result = formatBytes<i64>(bytes, occurrence.endian);
break;
case Float:
result += formatBytes<float>(bytes, occurrence.endian);
result = formatBytes<float>(bytes, occurrence.endian);
break;
case Double:
result += formatBytes<double>(bytes, occurrence.endian);
result = formatBytes<double>(bytes, occurrence.endian);
break;
}
}
@ -653,6 +749,9 @@ namespace hex::plugin::builtin {
case BinaryPattern:
result = hex::encodeByteString(bytes);
break;
case Constants:
result = occurrence.string;
break;
}
if (occurrence.region.getSize() > maxBytes)
@ -958,6 +1057,16 @@ namespace hex::plugin::builtin {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("hex.builtin.view.find.constants"_lang)) {
auto &settings = m_searchSettings.constants;
mode = SearchSettings::Mode::Constants;
constexpr static u32 min = 1, max = 0x1000;
ImGui::SliderScalar("hex.builtin.view.find.binary_pattern.alignment"_lang, ImGuiDataType_U32, &settings.alignment, &min, &max);
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
@ -1075,6 +1184,11 @@ namespace hex::plugin::builtin {
auto sortSpecs = ImGui::TableGetSortSpecs();
if (m_sortedOccurrences->empty() && !m_foundOccurrences->empty()) {
currOccurrences = *m_foundOccurrences;
sortSpecs->SpecsDirty = true;
}
if (sortSpecs->SpecsDirty) {
std::sort(currOccurrences.begin(), currOccurrences.end(), [this, &sortSpecs, provider](const Occurrence &left, const Occurrence &right) -> bool {
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("offset")) {