diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index 67b273941..50d508e69 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -1505,69 +1505,37 @@ namespace hex::pl { auto pattern = this->createPatterns(evaluator).front(); ON_SCOPE_EXIT { delete pattern; }; - auto readValue = [&evaluator](auto &value, PatternData *pattern) { - if (pattern->isLocal()) { - auto &literal = evaluator->getStack()[pattern->getOffset()]; - - std::visit(overloaded { - [&](std::string &assignmentValue) { }, - [&](PatternData *assignmentValue) { }, - [&](auto &&assignmentValue) { value = assignmentValue; } - }, literal); - } - else - evaluator->getProvider()->read(pattern->getOffset(), &value, pattern->getSize()); - - value = hex::changeEndianess(value, pattern->getSize(), pattern->getEndian()); - }; - - auto readString = [&evaluator](std::string &value, PatternData *pattern) { - if (pattern->isLocal()) { - auto &literal = evaluator->getStack()[pattern->getOffset()]; - - std::visit(overloaded { - [&](std::string &assignmentValue) { value = assignmentValue; }, - [&](auto &&assignmentValue) { } - }, literal); - } - else { - value.resize(pattern->getSize()); - evaluator->getProvider()->read(pattern->getOffset(), value.data(), value.size()); - value.erase(std::find(value.begin(), value.end(), '\0'), value.end()); - } - }; - Token::Literal literal; if (dynamic_cast(pattern) || dynamic_cast(pattern)) { u128 value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = value; } else if (dynamic_cast(pattern)) { s128 value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); value = hex::signExtend(pattern->getSize() * 8, value); literal = value; } else if (dynamic_cast(pattern)) { if (pattern->getSize() == sizeof(u16)) { u16 value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = double(float16ToFloat32(value)); } else if (pattern->getSize() == sizeof(float)) { float value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = double(value); } else if (pattern->getSize() == sizeof(double)) { double value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = value; } else LogConsole::abortEvaluation("invalid floating point type access", this); } else if (dynamic_cast(pattern)) { char value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = value; } else if (dynamic_cast(pattern)) { bool value = false; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = value; } else if (dynamic_cast(pattern)) { std::string value; @@ -1582,7 +1550,7 @@ namespace hex::pl { if (!dynamic_cast(assignmentValue) && !dynamic_cast(assignmentValue)) LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); - readString(value, assignmentValue); + readVariable(evaluator, value, assignmentValue); }, [&, this](auto &&assignmentValue) { LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); } }, literal); @@ -1596,7 +1564,7 @@ namespace hex::pl { literal = value; } else if (auto bitfieldFieldPattern = dynamic_cast(pattern)) { u64 value = 0; - readValue(value, pattern); + readVariable(evaluator, value, pattern); literal = u128(hex::extract(bitfieldFieldPattern->getBitOffset() + (bitfieldFieldPattern->getBitSize() - 1), bitfieldFieldPattern->getBitOffset(), value)); } else { literal = pattern->clone(); @@ -1718,8 +1686,13 @@ namespace hex::pl { } PatternData *indexPattern; - if (currPattern->isLocal()) - indexPattern = std::get(evaluator->getStack()[currPattern->getOffset()]); + if (currPattern->isLocal()) { + auto stackLiteral = evaluator->getStack()[currPattern->getOffset()]; + if (auto stackPattern = std::get_if(&stackLiteral); stackPattern != nullptr) + indexPattern = *stackPattern; + else + return { currPattern }; + } else indexPattern = currPattern; @@ -1744,6 +1717,34 @@ namespace hex::pl { private: Path m_path; + + void readVariable(Evaluator *evaluator, auto &value, PatternData *variablePattern) const { + constexpr bool isString = std::same_as, std::string>; + + if (variablePattern->isLocal()) { + auto &literal = evaluator->getStack()[variablePattern->getOffset()]; + + std::visit(overloaded { + [&](std::string &assignmentValue) { + if constexpr (isString) value = assignmentValue; + }, + [&](PatternData *assignmentValue) { readVariable(evaluator, value, assignmentValue); }, + [&](auto &&assignmentValue) { value = assignmentValue; } + }, literal); + } + else { + if constexpr (isString) { + value.resize(variablePattern->getSize()); + evaluator->getProvider()->read(variablePattern->getOffset(), value.data(), value.size()); + value.erase(std::find(value.begin(), value.end(), '\0'), value.end()); + } else { + evaluator->getProvider()->read(variablePattern->getOffset(), &value, variablePattern->getSize()); + } + } + + if constexpr (!isString) + value = hex::changeEndianess(value, variablePattern->getSize(), variablePattern->getEndian()); + } }; class ASTNodeScopeResolution : public ASTNode { diff --git a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp index 888638026..43f713ae2 100644 --- a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp @@ -7,9 +7,11 @@ #include #include + #include #include +#include namespace hex::prv { class Provider; } diff --git a/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp b/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp index 8ab78ffc3..9173ba942 100644 --- a/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp +++ b/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp @@ -258,6 +258,28 @@ namespace hex::pl { this->m_local == other.m_local; } + [[nodiscard]] + std::string formatDisplayValue(const std::string &value, const Token::Literal &literal) const { + if (!this->m_formatterFunction.has_value()) + return value; + else { + try { + auto result = this->m_formatterFunction->func(this->getEvaluator(), { literal }); + + if (result.has_value()) { + if (auto displayValue = std::get_if(&result.value()); displayValue != nullptr) + return *displayValue; + else + return "???"; + } else { + return "???"; + } + } catch (LogConsole::EvaluateError &error) { + return "Error: " + error.second; + } + } + } + protected: void createDefaultEntry(const std::string &value, const Token::Literal &literal) const { ImGui::TableNextRow(); @@ -278,19 +300,7 @@ namespace hex::pl { ImGui::TableNextColumn(); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName()); ImGui::TableNextColumn(); - - if (!this->m_formatterFunction.has_value()) - ImGui::TextUnformatted(value.c_str()); - else { - auto result = this->m_formatterFunction->func(this->getEvaluator(), { literal }); - - if (result.has_value()) { - if (auto displayValue = std::get_if(&result.value()); displayValue != nullptr) - ImGui::TextUnformatted(displayValue->c_str()); - } else { - ImGui::TextUnformatted("???"); - } - } + ImGui::TextFormatted("{}", formatDisplayValue(value, literal)); } void drawCommentTooltip() const { @@ -378,7 +388,7 @@ namespace hex::pl { ImGui::TableNextColumn(); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName()); ImGui::TableNextColumn(); - ImGui::TextFormatted("*(0x{0:X})", data); + ImGui::TextFormatted("{}", formatDisplayValue(hex::format("*(0x{0:X})", data), u128(data))); if (open) { this->m_pointedAt->createEntry(provider); @@ -809,7 +819,7 @@ namespace hex::pl { ImGui::TextUnformatted("]"); ImGui::TableNextColumn(); - ImGui::TextUnformatted("{ ... }"); + ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this)); } if (open) { @@ -929,7 +939,7 @@ namespace hex::pl { ImGui::TextUnformatted("]"); ImGui::TableNextColumn(); - ImGui::TextUnformatted("{ ... }"); + ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this)); } if (open) { @@ -1072,7 +1082,7 @@ namespace hex::pl { ImGui::TableNextColumn(); ImGui::TextColored(ImColor(0xFFD69C56), "struct"); ImGui::SameLine(); ImGui::TextUnformatted(this->getTypeName().c_str()); ImGui::TableNextColumn(); - ImGui::TextUnformatted("{ ... }"); + ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this)); } if (open) { @@ -1218,7 +1228,7 @@ namespace hex::pl { ImGui::TextColored(ImColor(0xFFD69C56), "union"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str()); ImGui::TableNextColumn(); - ImGui::TextUnformatted("{ ... }"); + ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this)); } if (open) { @@ -1372,7 +1382,7 @@ namespace hex::pl { ImGui::TableNextColumn(); ImGui::TextColored(ImColor(0xFFD69C56), "enum"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str()); ImGui::TableNextColumn(); - ImGui::TextFormatted("{} (0x{:0{}X})", valueString.c_str(), value, this->getSize() * 2); + ImGui::TextFormatted("{}", this->formatDisplayValue(hex::format("{} (0x{:0{}X})", valueString.c_str(), value, this->getSize() * 2), this)); } [[nodiscard]] std::string getFormattedName() const override { @@ -1448,7 +1458,7 @@ namespace hex::pl { u8 numBytes = (this->m_bitSize / 8) + 1; u64 extractedValue = hex::extract(this->m_bitOffset + (this->m_bitSize - 1), this->m_bitOffset, value); - ImGui::TextFormatted("{0} (0x{1:X})", extractedValue, extractedValue); + ImGui::TextFormatted("{}", this->formatDisplayValue(hex::format("{0} (0x{1:X})", extractedValue, extractedValue), this)); } } @@ -1525,7 +1535,7 @@ namespace hex::pl { valueString += hex::format("{0:02X} ", i); valueString += "}"; - ImGui::TextUnformatted(valueString.c_str()); + ImGui::TextFormatted("{}", this->formatDisplayValue(valueString, this)); } if (open) { diff --git a/plugins/libimhex/source/pattern_language/evaluator.cpp b/plugins/libimhex/source/pattern_language/evaluator.cpp index 7b9dd638a..dc5c9cae2 100644 --- a/plugins/libimhex/source/pattern_language/evaluator.cpp +++ b/plugins/libimhex/source/pattern_language/evaluator.cpp @@ -102,7 +102,7 @@ namespace hex::pl { LogConsole::abortEvaluation(hex::format("cannot cast type '{}' to type '{}'", value->getTypeName(), pattern->getTypeName())); }, [&](auto &&value) -> Token::Literal { - if (dynamic_cast(pattern)) + if (dynamic_cast(pattern) || dynamic_cast(pattern)) return u128(value); else if (dynamic_cast(pattern)) return s128(value); @@ -113,7 +113,7 @@ namespace hex::pl { else if (dynamic_cast(pattern)) return double(value); else - LogConsole::abortEvaluation(hex::format("cannot cast type 'string' to type '{}'", pattern->getTypeName())); + LogConsole::abortEvaluation(hex::format("cannot cast integer literal to type '{}'", pattern->getTypeName())); } }, value);