1
0
mirror of synced 2024-12-01 02:37:18 +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();
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 {

View File

@ -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; }

View File

@ -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) {

View File

@ -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);