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();
|
||||
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<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern)) {
|
||||
u128 value = 0;
|
||||
readValue(value, pattern);
|
||||
readVariable(evaluator, value, pattern);
|
||||
literal = value;
|
||||
} else if (dynamic_cast<PatternDataSigned*>(pattern)) {
|
||||
s128 value = 0;
|
||||
readValue(value, pattern);
|
||||
readVariable(evaluator, value, pattern);
|
||||
value = hex::signExtend(pattern->getSize() * 8, value);
|
||||
literal = value;
|
||||
} else if (dynamic_cast<PatternDataFloat*>(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<PatternDataCharacter*>(pattern)) {
|
||||
char value = 0;
|
||||
readValue(value, pattern);
|
||||
readVariable(evaluator, value, pattern);
|
||||
literal = value;
|
||||
} else if (dynamic_cast<PatternDataBoolean*>(pattern)) {
|
||||
bool value = false;
|
||||
readValue(value, pattern);
|
||||
readVariable(evaluator, value, pattern);
|
||||
literal = value;
|
||||
} else if (dynamic_cast<PatternDataString*>(pattern)) {
|
||||
std::string value;
|
||||
@ -1582,7 +1550,7 @@ namespace hex::pl {
|
||||
if (!dynamic_cast<PatternDataString*>(assignmentValue) && !dynamic_cast<PatternDataCharacter*>(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<PatternDataBitfieldField*>(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<PatternData*>(evaluator->getStack()[currPattern->getOffset()]);
|
||||
if (currPattern->isLocal()) {
|
||||
auto stackLiteral = evaluator->getStack()[currPattern->getOffset()];
|
||||
if (auto stackPattern = std::get_if<PatternData*>(&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::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 {
|
||||
|
@ -7,9 +7,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include <hex/pattern_language/log_console.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
|
@ -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<std::string>(&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<std::string>(&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) {
|
||||
|
@ -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<PatternDataUnsigned*>(pattern))
|
||||
if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern))
|
||||
return u128(value);
|
||||
else if (dynamic_cast<PatternDataSigned*>(pattern))
|
||||
return s128(value);
|
||||
@ -113,7 +113,7 @@ namespace hex::pl {
|
||||
else if (dynamic_cast<PatternDataFloat*>(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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user