patterns: Allow [[format]] attribute to work with custom types
This commit is contained in:
parent
5af9af1e5a
commit
b9034523b5
@ -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 {
|
||||||
|
@ -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; }
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user