1
0
mirror of synced 2024-11-28 09:30:51 +01:00

patterns: Allow [[format]] attribute to work with custom types

This commit is contained in:
WerWolv 2022-01-11 19:35:28 +01:00
parent 5af9af1e5a
commit b9034523b5
4 changed files with 79 additions and 66 deletions

View File

@ -1505,69 +1505,37 @@ namespace hex::pl {
auto pattern = this->createPatterns(evaluator).front(); auto pattern = this->createPatterns(evaluator).front();
ON_SCOPE_EXIT { delete pattern; }; 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; Token::Literal literal;
if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern)) { if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern)) {
u128 value = 0; u128 value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = value; literal = value;
} else if (dynamic_cast<PatternDataSigned*>(pattern)) { } else if (dynamic_cast<PatternDataSigned*>(pattern)) {
s128 value = 0; s128 value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
value = hex::signExtend(pattern->getSize() * 8, value); value = hex::signExtend(pattern->getSize() * 8, value);
literal = value; literal = value;
} else if (dynamic_cast<PatternDataFloat*>(pattern)) { } else if (dynamic_cast<PatternDataFloat*>(pattern)) {
if (pattern->getSize() == sizeof(u16)) { if (pattern->getSize() == sizeof(u16)) {
u16 value = 0; u16 value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = double(float16ToFloat32(value)); literal = double(float16ToFloat32(value));
} else if (pattern->getSize() == sizeof(float)) { } else if (pattern->getSize() == sizeof(float)) {
float value = 0; float value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = double(value); literal = double(value);
} else if (pattern->getSize() == sizeof(double)) { } else if (pattern->getSize() == sizeof(double)) {
double value = 0; double value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = value; literal = value;
} else LogConsole::abortEvaluation("invalid floating point type access", this); } else LogConsole::abortEvaluation("invalid floating point type access", this);
} else if (dynamic_cast<PatternDataCharacter*>(pattern)) { } else if (dynamic_cast<PatternDataCharacter*>(pattern)) {
char value = 0; char value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = value; literal = value;
} else if (dynamic_cast<PatternDataBoolean*>(pattern)) { } else if (dynamic_cast<PatternDataBoolean*>(pattern)) {
bool value = false; bool value = false;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = value; literal = value;
} else if (dynamic_cast<PatternDataString*>(pattern)) { } else if (dynamic_cast<PatternDataString*>(pattern)) {
std::string value; std::string value;
@ -1582,7 +1550,7 @@ namespace hex::pl {
if (!dynamic_cast<PatternDataString*>(assignmentValue) && !dynamic_cast<PatternDataCharacter*>(assignmentValue)) if (!dynamic_cast<PatternDataString*>(assignmentValue) && !dynamic_cast<PatternDataCharacter*>(assignmentValue))
LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); 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); } [&, this](auto &&assignmentValue) { LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); }
}, literal); }, literal);
@ -1596,7 +1564,7 @@ namespace hex::pl {
literal = value; literal = value;
} else if (auto bitfieldFieldPattern = dynamic_cast<PatternDataBitfieldField*>(pattern)) { } else if (auto bitfieldFieldPattern = dynamic_cast<PatternDataBitfieldField*>(pattern)) {
u64 value = 0; u64 value = 0;
readValue(value, pattern); readVariable(evaluator, value, pattern);
literal = u128(hex::extract(bitfieldFieldPattern->getBitOffset() + (bitfieldFieldPattern->getBitSize() - 1), bitfieldFieldPattern->getBitOffset(), value)); literal = u128(hex::extract(bitfieldFieldPattern->getBitOffset() + (bitfieldFieldPattern->getBitSize() - 1), bitfieldFieldPattern->getBitOffset(), value));
} else { } else {
literal = pattern->clone(); literal = pattern->clone();
@ -1718,8 +1686,13 @@ namespace hex::pl {
} }
PatternData *indexPattern; PatternData *indexPattern;
if (currPattern->isLocal()) if (currPattern->isLocal()) {
indexPattern = std::get<PatternData*>(evaluator->getStack()[currPattern->getOffset()]); auto stackLiteral = evaluator->getStack()[currPattern->getOffset()];
if (auto stackPattern = std::get_if<PatternData*>(&stackLiteral); stackPattern != nullptr)
indexPattern = *stackPattern;
else
return { currPattern };
}
else else
indexPattern = currPattern; indexPattern = currPattern;
@ -1744,6 +1717,34 @@ namespace hex::pl {
private: private:
Path m_path; Path m_path;
void readVariable(Evaluator *evaluator, auto &value, PatternData *variablePattern) const {
constexpr bool isString = std::same_as<std::remove_cvref_t<decltype(value)>, 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 { class ASTNodeScopeResolution : public ASTNode {

View File

@ -7,9 +7,11 @@
#include <vector> #include <vector>
#include <hex/pattern_language/log_console.hpp> #include <hex/pattern_language/log_console.hpp>
#include <hex/api/content_registry.hpp> #include <hex/api/content_registry.hpp>
#include <hex/helpers/fmt.hpp> #include <hex/helpers/fmt.hpp>
#include <hex/helpers/concepts.hpp>
namespace hex::prv { class Provider; } namespace hex::prv { class Provider; }

View File

@ -258,6 +258,28 @@ namespace hex::pl {
this->m_local == other.m_local; 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<std::string>(&result.value()); displayValue != nullptr)
return *displayValue;
else
return "???";
} else {
return "???";
}
} catch (LogConsole::EvaluateError &error) {
return "Error: " + error.second;
}
}
}
protected: protected:
void createDefaultEntry(const std::string &value, const Token::Literal &literal) const { void createDefaultEntry(const std::string &value, const Token::Literal &literal) const {
ImGui::TableNextRow(); ImGui::TableNextRow();
@ -278,19 +300,7 @@ namespace hex::pl {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName()); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormatted("{}", formatDisplayValue(value, literal));
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<std::string>(&result.value()); displayValue != nullptr)
ImGui::TextUnformatted(displayValue->c_str());
} else {
ImGui::TextUnformatted("???");
}
}
} }
void drawCommentTooltip() const { void drawCommentTooltip() const {
@ -378,7 +388,7 @@ namespace hex::pl {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName()); ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormatted("*(0x{0:X})", data); ImGui::TextFormatted("{}", formatDisplayValue(hex::format("*(0x{0:X})", data), u128(data)));
if (open) { if (open) {
this->m_pointedAt->createEntry(provider); this->m_pointedAt->createEntry(provider);
@ -809,7 +819,7 @@ namespace hex::pl {
ImGui::TextUnformatted("]"); ImGui::TextUnformatted("]");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }"); ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
} }
if (open) { if (open) {
@ -929,7 +939,7 @@ namespace hex::pl {
ImGui::TextUnformatted("]"); ImGui::TextUnformatted("]");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }"); ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
} }
if (open) { if (open) {
@ -1072,7 +1082,7 @@ namespace hex::pl {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextColored(ImColor(0xFFD69C56), "struct"); ImGui::SameLine(); ImGui::TextUnformatted(this->getTypeName().c_str()); ImGui::TextColored(ImColor(0xFFD69C56), "struct"); ImGui::SameLine(); ImGui::TextUnformatted(this->getTypeName().c_str());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }"); ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
} }
if (open) { if (open) {
@ -1218,7 +1228,7 @@ namespace hex::pl {
ImGui::TextColored(ImColor(0xFFD69C56), "union"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str()); ImGui::TextColored(ImColor(0xFFD69C56), "union"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }"); ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
} }
if (open) { if (open) {
@ -1372,7 +1382,7 @@ namespace hex::pl {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextColored(ImColor(0xFFD69C56), "enum"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str()); ImGui::TextColored(ImColor(0xFFD69C56), "enum"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str());
ImGui::TableNextColumn(); 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 { [[nodiscard]] std::string getFormattedName() const override {
@ -1448,7 +1458,7 @@ namespace hex::pl {
u8 numBytes = (this->m_bitSize / 8) + 1; u8 numBytes = (this->m_bitSize / 8) + 1;
u64 extractedValue = hex::extract(this->m_bitOffset + (this->m_bitSize - 1), this->m_bitOffset, value); 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 += hex::format("{0:02X} ", i);
valueString += "}"; valueString += "}";
ImGui::TextUnformatted(valueString.c_str()); ImGui::TextFormatted("{}", this->formatDisplayValue(valueString, this));
} }
if (open) { if (open) {

View File

@ -102,7 +102,7 @@ namespace hex::pl {
LogConsole::abortEvaluation(hex::format("cannot cast type '{}' to type '{}'", value->getTypeName(), pattern->getTypeName())); LogConsole::abortEvaluation(hex::format("cannot cast type '{}' to type '{}'", value->getTypeName(), pattern->getTypeName()));
}, },
[&](auto &&value) -> Token::Literal { [&](auto &&value) -> Token::Literal {
if (dynamic_cast<PatternDataUnsigned*>(pattern)) if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern))
return u128(value); return u128(value);
else if (dynamic_cast<PatternDataSigned*>(pattern)) else if (dynamic_cast<PatternDataSigned*>(pattern))
return s128(value); return s128(value);
@ -113,7 +113,7 @@ namespace hex::pl {
else if (dynamic_cast<PatternDataFloat*>(pattern)) else if (dynamic_cast<PatternDataFloat*>(pattern))
return double(value); return double(value);
else 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); }, value);