mirror of https://github.com/WerWolv/ImHex.git
patterns: Added button to abort evaluation
This commit is contained in:
parent
3e30f75e7b
commit
6d8b7bef09
|
@ -61,7 +61,8 @@ namespace ImGui {
|
|||
void InfoTooltip(const char *text);
|
||||
|
||||
bool TitleBarButton(const char* label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color);
|
||||
bool IconButton(const char* symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
|
|
|
@ -401,7 +401,7 @@ namespace ImGui {
|
|||
return pressed;
|
||||
}
|
||||
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color, ImVec2 size_arg) {
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
@ -415,7 +415,7 @@ namespace ImGui {
|
|||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
|
||||
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
ImVec2 size = CalcItemSize(ImVec2(1, 1) * ImGui::GetCurrentWindow()->MenuBarHeight(), label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect bb(pos, pos + size);
|
||||
ItemSize(size, style.FramePadding.y);
|
||||
|
@ -443,4 +443,46 @@ namespace ImGui {
|
|||
return pressed;
|
||||
}
|
||||
|
||||
bool IconButton(const char* symbol, ImVec4 color, ImVec2 size_arg) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
color.w = 1.0F;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(symbol);
|
||||
const ImVec2 label_size = CalcTextSize(symbol, NULL, true);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
|
||||
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect bb(pos, pos + size);
|
||||
ItemSize(size, style.FramePadding.y);
|
||||
if (!ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, color);
|
||||
|
||||
// Render
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
RenderNavHighlight(bb, id);
|
||||
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
||||
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
PopStyleColor();
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return pressed;
|
||||
}
|
||||
|
||||
}
|
|
@ -26,19 +26,17 @@ namespace hex::plugin::builtin {
|
|||
|
||||
void addToolbarItems() {
|
||||
ContentRegistry::Interface::addToolbarItem([] {
|
||||
const static auto buttonSize = ImVec2(ImGui::GetCurrentWindow()->MenuBarHeight(), ImGui::GetCurrentWindow()->MenuBarHeight());
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
// Undo
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_DISCARD, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_DISCARD, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->undo();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->canUndo());
|
||||
|
||||
// Redo
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_REDO, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_REDO, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->redo();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->canRedo());
|
||||
|
||||
|
@ -46,11 +44,11 @@ namespace hex::plugin::builtin {
|
|||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
|
||||
// Create new file
|
||||
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray)))
|
||||
EventManager::post<RequestOpenWindow>("Create File");
|
||||
|
||||
// Open file
|
||||
if (ImGui::ToolBarButton(ICON_VS_FOLDER_OPENED, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBrown), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_FOLDER_OPENED, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBrown)))
|
||||
EventManager::post<RequestOpenWindow>("Open File");
|
||||
|
||||
|
||||
|
@ -58,13 +56,13 @@ namespace hex::plugin::builtin {
|
|||
|
||||
// Save file
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->save();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->isWritable() || !provider->isSavable());
|
||||
|
||||
// Save file as
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
hex::openFileBrowser("hex.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [&provider](auto path) {
|
||||
provider->saveAs(path);
|
||||
});
|
||||
|
@ -76,7 +74,7 @@ namespace hex::plugin::builtin {
|
|||
|
||||
// Create bookmark
|
||||
ImGui::Disabled([] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_BOOKMARK, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen), buttonSize)) {
|
||||
if (ImGui::ToolBarButton(ICON_VS_BOOKMARK, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen))) {
|
||||
Region region = { 0 };
|
||||
EventManager::post<QuerySelection>(region);
|
||||
|
||||
|
|
|
@ -516,7 +516,10 @@ namespace hex::pl {
|
|||
|
||||
FunctionResult execute(Evaluator *evaluator) override {
|
||||
|
||||
u64 loopIterations = 0;
|
||||
while (evaluateCondition(evaluator)) {
|
||||
evaluator->handleAbort();
|
||||
|
||||
auto variables = *evaluator->getScope(0).scope;
|
||||
u32 startVariableCount = variables.size();
|
||||
ON_SCOPE_EXIT {
|
||||
|
@ -538,6 +541,12 @@ namespace hex::pl {
|
|||
return { true, result };
|
||||
}
|
||||
}
|
||||
|
||||
loopIterations++;
|
||||
if (loopIterations >= evaluator->getLoopLimit())
|
||||
LogConsole::abortEvaluation(hex::format("loop iterations exceeded limit of {}", evaluator->getLoopLimit()), this);
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
|
||||
return { false, { } };
|
||||
|
@ -807,6 +816,7 @@ namespace hex::pl {
|
|||
while (whileStatement->evaluateCondition(evaluator)) {
|
||||
entryCount++;
|
||||
evaluator->dataOffset() += templatePattern->getSize();
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -829,6 +839,7 @@ namespace hex::pl {
|
|||
}
|
||||
|
||||
if (reachedEnd) break;
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -901,6 +912,8 @@ namespace hex::pl {
|
|||
entries.push_back(pattern);
|
||||
|
||||
size += pattern->getSize();
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
} else if (auto whileStatement = dynamic_cast<ASTNodeWhileStatement*>(sizeNode)) {
|
||||
while (whileStatement->evaluateCondition(evaluator)) {
|
||||
|
@ -917,6 +930,8 @@ namespace hex::pl {
|
|||
|
||||
entryCount++;
|
||||
size += pattern->getSize();
|
||||
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -951,6 +966,7 @@ namespace hex::pl {
|
|||
}
|
||||
|
||||
if (reachedEnd) break;
|
||||
evaluator->handleAbort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1380,6 +1396,10 @@ namespace hex::pl {
|
|||
|
||||
std::visit(overloaded {
|
||||
[&](std::string &assignmentValue) { },
|
||||
[&](s128 assignmentValue) {
|
||||
std::memcpy(&value, &assignmentValue, pattern->getSize());
|
||||
value = hex::signExtend(pattern->getSize() * 8, value);
|
||||
},
|
||||
[&](auto &&assignmentValue) { std::memcpy(&value, &assignmentValue, pattern->getSize()); }
|
||||
}, literal);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
@ -31,8 +32,10 @@ namespace hex::pl {
|
|||
|
||||
struct Scope { PatternData *parent; std::vector<PatternData*>* scope; };
|
||||
void pushScope(PatternData *parent, std::vector<PatternData*> &scope) {
|
||||
if (this->m_scopes.size() > this->m_evalDepth)
|
||||
LogConsole::abortEvaluation(hex::format("recursion limit of {} reached", this->m_evalDepth));
|
||||
if (this->m_scopes.size() > this->getEvaluationDepth())
|
||||
LogConsole::abortEvaluation(hex::format("evaluation depth exceeded set limit of {}", this->getEvaluationDepth()));
|
||||
|
||||
this->handleAbort();
|
||||
|
||||
this->m_scopes.push_back({ parent, &scope });
|
||||
}
|
||||
|
@ -70,38 +73,47 @@ namespace hex::pl {
|
|||
return this->m_defaultEndian;
|
||||
}
|
||||
|
||||
void setEvaluationDepth(u32 evalDepth) {
|
||||
void setEvaluationDepth(u64 evalDepth) {
|
||||
this->m_evalDepth = evalDepth;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getEvaluationDepth() const {
|
||||
u64 getEvaluationDepth() const {
|
||||
return this->m_evalDepth;
|
||||
}
|
||||
|
||||
void setArrayLimit(u32 arrayLimit) {
|
||||
void setArrayLimit(u64 arrayLimit) {
|
||||
this->m_arrayLimit = arrayLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getArrayLimit() const {
|
||||
u64 getArrayLimit() const {
|
||||
return this->m_arrayLimit;
|
||||
}
|
||||
|
||||
void setPatternLimit(u32 limit) {
|
||||
void setPatternLimit(u64 limit) {
|
||||
this->m_patternLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getPatternLimit() {
|
||||
u64 getPatternLimit() {
|
||||
return this->m_patternLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getPatternCount() {
|
||||
u64 getPatternCount() {
|
||||
return this->m_currPatternCount;
|
||||
}
|
||||
|
||||
void setLoopLimit(u64 limit) {
|
||||
this->m_loopLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getLoopLimit() {
|
||||
return this->m_loopLimit;
|
||||
}
|
||||
|
||||
u64& dataOffset() { return this->m_currOffset; }
|
||||
|
||||
bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) {
|
||||
|
@ -123,6 +135,15 @@ namespace hex::pl {
|
|||
void createVariable(const std::string &name, ASTNode *type, const std::optional<Token::Literal> &value = std::nullopt);
|
||||
void setVariable(const std::string &name, const Token::Literal& value);
|
||||
|
||||
void abort() {
|
||||
this->m_aborted = true;
|
||||
}
|
||||
|
||||
void handleAbort() {
|
||||
if (this->m_aborted)
|
||||
LogConsole::abortEvaluation("evaluation aborted by user");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void patternCreated();
|
||||
|
@ -134,11 +155,14 @@ namespace hex::pl {
|
|||
LogConsole m_console;
|
||||
|
||||
std::endian m_defaultEndian = std::endian::native;
|
||||
u32 m_evalDepth;
|
||||
u32 m_arrayLimit;
|
||||
u32 m_patternLimit;
|
||||
u64 m_evalDepth;
|
||||
u64 m_arrayLimit;
|
||||
u64 m_patternLimit;
|
||||
u64 m_loopLimit;
|
||||
|
||||
u32 m_currPatternCount;
|
||||
u64 m_currPatternCount;
|
||||
|
||||
std::atomic<bool> m_aborted;
|
||||
|
||||
std::vector<Scope> m_scopes;
|
||||
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> m_customFunctions;
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace hex::pl {
|
|||
std::optional<std::vector<PatternData*>> executeString(prv::Provider *provider, const std::string &string);
|
||||
std::optional<std::vector<PatternData*>> executeFile(prv::Provider *provider, const std::string &path);
|
||||
|
||||
void abort();
|
||||
|
||||
const std::vector<std::pair<LogConsole::Level, std::string>>& getConsoleLog();
|
||||
const std::optional<std::pair<u32, std::string>>& getError();
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ namespace hex::pl {
|
|||
this->m_stack.clear();
|
||||
this->m_customFunctions.clear();
|
||||
this->m_scopes.clear();
|
||||
this->m_aborted = false;
|
||||
|
||||
this->dataOffset() = 0x00;
|
||||
this->m_currPatternCount = 0;
|
||||
|
|
|
@ -67,6 +67,16 @@ namespace hex::pl {
|
|||
return true;
|
||||
});
|
||||
|
||||
this->m_preprocessor->addPragmaHandler("loop_limit", [this](const std::string &value) {
|
||||
auto limit = strtol(value.c_str(), nullptr, 0);
|
||||
|
||||
if (limit <= 0)
|
||||
return false;
|
||||
|
||||
this->m_evaluator->setLoopLimit(limit);
|
||||
return true;
|
||||
});
|
||||
|
||||
this->m_preprocessor->addPragmaHandler("base_address", [](const std::string &value) {
|
||||
auto baseAddress = strtoull(value.c_str(), nullptr, 0);
|
||||
|
||||
|
@ -93,6 +103,7 @@ namespace hex::pl {
|
|||
this->m_evaluator->setEvaluationDepth(32);
|
||||
this->m_evaluator->setArrayLimit(0x1000);
|
||||
this->m_evaluator->setPatternLimit(0x2000);
|
||||
this->m_evaluator->setLoopLimit(0x1000);
|
||||
|
||||
for (auto &node : this->m_currAST)
|
||||
delete node;
|
||||
|
@ -133,6 +144,10 @@ namespace hex::pl {
|
|||
return this->executeString(provider, file.readString());
|
||||
}
|
||||
|
||||
void PatternLanguage::abort() {
|
||||
this->m_evaluator->abort();
|
||||
}
|
||||
|
||||
|
||||
const std::vector<std::pair<LogConsole::Level, std::string>>& PatternLanguage::getConsoleLog() {
|
||||
return this->m_evaluator->getConsole().getLog();
|
||||
|
|
|
@ -245,16 +245,18 @@ namespace hex {
|
|||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
ImGui::Disabled([this] {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(ImColor(0x20, 0x85, 0x20)));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
|
||||
|
||||
if (ImGui::ArrowButton("evaluate", ImGuiDir_Right))
|
||||
if (this->m_evaluatorRunning) {
|
||||
if (ImGui::IconButton(ICON_VS_DEBUG_STOP, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed)))
|
||||
this->m_patternLanguageRuntime->abort();
|
||||
} else {
|
||||
if (ImGui::IconButton(ICON_VS_DEBUG_START, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)))
|
||||
this->parsePattern(this->m_textEditor.GetText().data());
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}, this->m_evaluatorRunning);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (this->m_evaluatorRunning)
|
||||
|
|
Loading…
Reference in New Issue