patterns: Add optimization for arrays of statically sized types
This commit is contained in:
parent
6879cf765f
commit
ee7c6a91a7
@ -4,7 +4,6 @@
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/views/view.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/views/view.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
@ -13,6 +12,7 @@
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
namespace lang { class PatternData; }
|
||||
|
||||
class ViewPatternData : public View {
|
||||
public:
|
||||
|
@ -82,6 +82,8 @@ namespace hex::lang {
|
||||
PatternData* evaluateType(ASTNodeTypeDecl *node);
|
||||
PatternData* evaluateVariable(ASTNodeVariableDecl *node);
|
||||
PatternData* evaluateArray(ASTNodeArrayVariableDecl *node);
|
||||
PatternData* evaluateStaticArray(ASTNodeArrayVariableDecl *node);
|
||||
PatternData* evaluateDynamicArray(ASTNodeArrayVariableDecl *node);
|
||||
PatternData* evaluatePointer(ASTNodePointerVariableDecl *node);
|
||||
};
|
||||
|
||||
|
@ -55,12 +55,15 @@ namespace hex::lang {
|
||||
if (SharedData::patternPaletteOffset >= (sizeof(Palette) / sizeof(u32)))
|
||||
SharedData::patternPaletteOffset = 0;
|
||||
}
|
||||
|
||||
PatternData(const PatternData &other) = default;
|
||||
|
||||
virtual ~PatternData() = default;
|
||||
|
||||
virtual PatternData* clone() = 0;
|
||||
|
||||
[[nodiscard]] u64 getOffset() const { return this->m_offset; }
|
||||
void setOffset(u64 offset) { this->m_offset = offset; }
|
||||
virtual void setOffset(u64 offset) { this->m_offset = offset; }
|
||||
|
||||
[[nodiscard]] size_t getSize() const { return this->m_size; }
|
||||
void setSize(size_t size) { this->m_size = size; }
|
||||
@ -104,6 +107,10 @@ namespace hex::lang {
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
virtual void clearHighlightedAddresses() {
|
||||
this->m_highlightedAddresses.clear();
|
||||
}
|
||||
|
||||
virtual void sort(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider) { }
|
||||
|
||||
static bool sortPatternDataTable(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider, lang::PatternData* left, lang::PatternData* right) {
|
||||
@ -253,7 +260,7 @@ namespace hex::lang {
|
||||
: PatternData(offset, size, color), m_pointedAt(nullptr) {
|
||||
}
|
||||
|
||||
PatternDataPointer(const PatternDataPointer &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
PatternDataPointer(const PatternDataPointer &other) : PatternData(other) {
|
||||
this->m_pointedAt = other.m_pointedAt->clone();
|
||||
}
|
||||
|
||||
@ -577,13 +584,13 @@ namespace hex::lang {
|
||||
}
|
||||
};
|
||||
|
||||
class PatternDataArray : public PatternData {
|
||||
class PatternDataDynamicArray : public PatternData {
|
||||
public:
|
||||
PatternDataArray(u64 offset, size_t size, u32 color = 0)
|
||||
PatternDataDynamicArray(u64 offset, size_t size, u32 color = 0)
|
||||
: PatternData(offset, size, color) {
|
||||
}
|
||||
|
||||
PatternDataArray(const PatternDataArray &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
PatternDataDynamicArray(const PatternDataDynamicArray &other) : PatternData(other) {
|
||||
std::vector<PatternData*> entries;
|
||||
for (const auto &entry : other.m_entries)
|
||||
entries.push_back(entry->clone());
|
||||
@ -591,13 +598,21 @@ namespace hex::lang {
|
||||
this->setEntries(entries);
|
||||
}
|
||||
|
||||
~PatternDataArray() override {
|
||||
~PatternDataDynamicArray() override {
|
||||
for (const auto &entry : this->m_entries)
|
||||
delete entry;
|
||||
}
|
||||
|
||||
PatternData* clone() override {
|
||||
return new PatternDataArray(*this);
|
||||
return new PatternDataDynamicArray(*this);
|
||||
}
|
||||
|
||||
void setOffset(u64 offset) override {
|
||||
for (auto &entry : this->m_entries) {
|
||||
entry->setOffset(offset + (entry->getOffset() - this->getOffset()));
|
||||
}
|
||||
|
||||
PatternData::setOffset(offset);
|
||||
}
|
||||
|
||||
void createEntry(prv::Provider* &provider) override {
|
||||
@ -654,6 +669,12 @@ namespace hex::lang {
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
void clearHighlightedAddresses() override {
|
||||
for (auto &entry : this->m_entries)
|
||||
entry->clearHighlightedAddresses();
|
||||
PatternData::clearHighlightedAddresses();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getFormattedName() const override {
|
||||
return this->m_entries[0]->getTypeName() + "[" + std::to_string(this->m_entries.size()) + "]";
|
||||
}
|
||||
@ -675,14 +696,137 @@ namespace hex::lang {
|
||||
std::vector<PatternData*> m_entries;
|
||||
};
|
||||
|
||||
class PatternDataStaticArray : public PatternData {
|
||||
public:
|
||||
PatternDataStaticArray(u64 offset, size_t size, u32 color = 0)
|
||||
: PatternData(offset, size, color) {
|
||||
}
|
||||
|
||||
PatternDataStaticArray(const PatternDataStaticArray &other) : PatternData(other) {
|
||||
this->setEntries(other.getTemplate()->clone(), other.getEntryCount());
|
||||
}
|
||||
|
||||
~PatternDataStaticArray() override {
|
||||
delete this->m_template;
|
||||
}
|
||||
|
||||
PatternData* clone() override {
|
||||
return new PatternDataStaticArray(*this);
|
||||
}
|
||||
|
||||
void createEntry(prv::Provider* &provider) override {
|
||||
if (this->getEntryCount() == 0)
|
||||
return;
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
bool open = ImGui::TreeNodeEx(this->getVariableName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_AllowItemOverlap);
|
||||
this->drawCommentTooltip();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("0x%08llX : 0x%08llX", this->getOffset(), this->getOffset() + this->getSize() - 1);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("0x%04llX", this->getSize());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextColored(ImColor(0xFF9BC64D), "%s", this->m_template->getTypeName().c_str());
|
||||
ImGui::SameLine(0, 0);
|
||||
|
||||
ImGui::TextUnformatted("[");
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::TextColored(ImColor(0xFF00FF00), "%llu", this->m_entryCount);
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::TextUnformatted("]");
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", "{ ... }");
|
||||
|
||||
if (open) {
|
||||
auto entry = this->m_template->clone();
|
||||
for (u64 index = 0; index < this->m_entryCount; index++) {
|
||||
entry->setVariableName(hex::format("[{0}]", index));
|
||||
entry->setOffset(this->getOffset() + index * this->m_template->getSize());
|
||||
entry->draw(provider);
|
||||
}
|
||||
delete entry;
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<u32> highlightBytes(size_t offset) override{
|
||||
auto entry = this->m_template->clone();
|
||||
|
||||
for (u64 address = this->getOffset(); address < this->getOffset() + this->getSize(); address += this->m_template->getSize()) {
|
||||
entry->setOffset(address);
|
||||
if (auto color = entry->highlightBytes(offset); color.has_value())
|
||||
return color.value();
|
||||
}
|
||||
|
||||
delete entry;
|
||||
|
||||
return { };
|
||||
}
|
||||
|
||||
std::map<u64, u32> getHighlightedAddresses() override {
|
||||
if (this->m_highlightedAddresses.empty()) {
|
||||
auto entry = this->m_template->clone();
|
||||
|
||||
for (u64 address = this->getOffset(); address < this->getOffset() + this->getSize(); address += this->m_template->getSize()) {
|
||||
entry->setOffset(address);
|
||||
entry->clearHighlightedAddresses();
|
||||
this->m_highlightedAddresses.merge(entry->getHighlightedAddresses());
|
||||
}
|
||||
|
||||
delete entry;
|
||||
}
|
||||
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
void clearHighlightedAddresses() override {
|
||||
this->m_template->clearHighlightedAddresses();
|
||||
PatternData::clearHighlightedAddresses();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getFormattedName() const override {
|
||||
return this->m_template->getTypeName() + "[" + std::to_string(this->m_entryCount) + "]";
|
||||
}
|
||||
|
||||
[[nodiscard]] PatternData* getTemplate() const {
|
||||
return this->m_template;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t getEntryCount() const {
|
||||
return this->m_entryCount;
|
||||
}
|
||||
|
||||
void setEntryCount(size_t count) {
|
||||
this->m_entryCount = count;
|
||||
}
|
||||
|
||||
void setEntries(PatternData* templ, size_t count) {
|
||||
this->m_template = templ;
|
||||
this->m_entryCount = count;
|
||||
|
||||
this->m_template->setColor(this->getColor());
|
||||
this->m_template->setParent(this);
|
||||
}
|
||||
|
||||
private:
|
||||
PatternData *m_template;
|
||||
size_t m_entryCount;
|
||||
};
|
||||
|
||||
class PatternDataStruct : public PatternData {
|
||||
public:
|
||||
PatternDataStruct(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color){
|
||||
}
|
||||
|
||||
PatternDataStruct(const PatternDataStruct &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
PatternDataStruct(const PatternDataStruct &other) : PatternData(other) {
|
||||
for (const auto &member : other.m_members)
|
||||
this->m_members.push_back(member->clone());
|
||||
this->m_sortedMembers = this->m_members;
|
||||
}
|
||||
|
||||
~PatternDataStruct() override {
|
||||
@ -694,6 +838,14 @@ namespace hex::lang {
|
||||
return new PatternDataStruct(*this);
|
||||
}
|
||||
|
||||
void setOffset(u64 offset) override {
|
||||
for (auto &member : this->m_members) {
|
||||
member->setOffset(offset + (member->getOffset() - this->getOffset()));
|
||||
}
|
||||
|
||||
PatternData::setOffset(offset);
|
||||
}
|
||||
|
||||
void createEntry(prv::Provider* &provider) override {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
@ -737,6 +889,12 @@ namespace hex::lang {
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
void clearHighlightedAddresses() override {
|
||||
for (auto &member : this->m_members)
|
||||
member->clearHighlightedAddresses();
|
||||
PatternData::clearHighlightedAddresses();
|
||||
}
|
||||
|
||||
void sort(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider) override {
|
||||
this->m_sortedMembers = this->m_members;
|
||||
|
||||
@ -780,9 +938,10 @@ namespace hex::lang {
|
||||
|
||||
}
|
||||
|
||||
PatternDataUnion(const PatternDataUnion &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
PatternDataUnion(const PatternDataUnion &other) : PatternData(other) {
|
||||
for (const auto &member : other.m_members)
|
||||
this->m_members.push_back(member->clone());
|
||||
this->m_sortedMembers = this->m_members;
|
||||
}
|
||||
|
||||
~PatternDataUnion() override {
|
||||
@ -794,6 +953,14 @@ namespace hex::lang {
|
||||
return new PatternDataUnion(*this);
|
||||
}
|
||||
|
||||
void setOffset(u64 offset) override {
|
||||
for (auto &member : this->m_members) {
|
||||
member->setOffset(offset + (member->getOffset() - this->getOffset()));
|
||||
}
|
||||
|
||||
PatternData::setOffset(offset);
|
||||
}
|
||||
|
||||
void createEntry(prv::Provider* &provider) override {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
@ -838,6 +1005,12 @@ namespace hex::lang {
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
void clearHighlightedAddresses() override {
|
||||
for (auto &member : this->m_members)
|
||||
member->clearHighlightedAddresses();
|
||||
PatternData::clearHighlightedAddresses();
|
||||
}
|
||||
|
||||
void sort(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider) override {
|
||||
this->m_sortedMembers = this->m_members;
|
||||
|
||||
|
@ -61,8 +61,12 @@ namespace hex::lang {
|
||||
else if (auto bitfieldPattern = dynamic_cast<PatternDataBitfield*>(currPattern); bitfieldPattern != nullptr) {
|
||||
currMembers = bitfieldPattern->getFields();
|
||||
}
|
||||
else if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
||||
currMembers = arrayPattern->getEntries();
|
||||
else if (auto dynamicArrayPattern = dynamic_cast<PatternDataDynamicArray*>(currPattern); dynamicArrayPattern != nullptr) {
|
||||
currMembers = dynamicArrayPattern->getEntries();
|
||||
continue;
|
||||
}
|
||||
else if (auto staticArrayPattern = dynamic_cast<PatternDataStaticArray*>(currPattern); staticArrayPattern != nullptr) {
|
||||
currMembers = { staticArrayPattern->getTemplate() };
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -84,15 +88,30 @@ namespace hex::lang {
|
||||
ON_SCOPE_EXIT { delete arrayIndexNode; };
|
||||
|
||||
if (currPattern != nullptr) {
|
||||
if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
||||
if (auto dynamicArrayPattern = dynamic_cast<PatternDataDynamicArray*>(currPattern); dynamicArrayPattern != nullptr) {
|
||||
std::visit([this](auto &&arrayIndex) {
|
||||
if (std::is_floating_point_v<decltype(arrayIndex)>)
|
||||
this->getConsole().abortEvaluation("cannot use float to index into array");
|
||||
}, arrayIndexNode->getValue());
|
||||
|
||||
std::visit([&](auto &&arrayIndex){
|
||||
if (arrayIndex >= 0 && arrayIndex < arrayPattern->getEntries().size())
|
||||
currPattern = arrayPattern->getEntries()[arrayIndex];
|
||||
if (arrayIndex >= 0 && arrayIndex < dynamicArrayPattern->getEntries().size())
|
||||
currPattern = dynamicArrayPattern->getEntries()[arrayIndex];
|
||||
else
|
||||
this->getConsole().abortEvaluation(hex::format("tried to access out of bounds index {} of '{}'", arrayIndex, currPattern->getVariableName()));
|
||||
}, arrayIndexNode->getValue());
|
||||
|
||||
} else if (auto staticArrayPattern = dynamic_cast<PatternDataStaticArray*>(currPattern); staticArrayPattern != nullptr) {
|
||||
std::visit([this](auto &&arrayIndex) {
|
||||
if (std::is_floating_point_v<decltype(arrayIndex)>)
|
||||
this->getConsole().abortEvaluation("cannot use float to index into array");
|
||||
}, arrayIndexNode->getValue());
|
||||
|
||||
std::visit([&](auto &&arrayIndex){
|
||||
if (arrayIndex >= 0 && arrayIndex < staticArrayPattern->getEntryCount()) {
|
||||
currPattern = staticArrayPattern->getTemplate();
|
||||
currPattern->setOffset(staticArrayPattern->getOffset() + arrayIndex * staticArrayPattern->getSize());
|
||||
}
|
||||
else
|
||||
this->getConsole().abortEvaluation(hex::format("tried to access out of bounds index {} of '{}'", arrayIndex, currPattern->getVariableName()));
|
||||
}, arrayIndexNode->getValue());
|
||||
@ -960,7 +979,6 @@ namespace hex::lang {
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateArray(ASTNodeArrayVariableDecl *node) {
|
||||
|
||||
// Evaluate placement of array
|
||||
if (auto offset = dynamic_cast<ASTNodeNumericExpression*>(node->getPlacementOffset()); offset != nullptr) {
|
||||
auto valueNode = evaluateMathematicalExpression(offset);
|
||||
@ -982,6 +1000,112 @@ namespace hex::lang {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
auto type = static_cast<ASTNodeTypeDecl*>(node->getType())->getType();
|
||||
|
||||
if (dynamic_cast<ASTNodeBuiltinType*>(type) != nullptr)
|
||||
return this->evaluateStaticArray(node);
|
||||
|
||||
auto attributes = dynamic_cast<Attributable*>(type)->getAttributes();
|
||||
|
||||
bool isStaticType = std::any_of(attributes.begin(), attributes.end(), [](ASTNodeAttribute *attribute) {
|
||||
return attribute->getAttribute() == "static" && !attribute->getValue().has_value();
|
||||
});
|
||||
|
||||
if (isStaticType)
|
||||
return this->evaluateStaticArray(node);
|
||||
else
|
||||
return this->evaluateDynamicArray(node);
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateStaticArray(ASTNodeArrayVariableDecl *node) {
|
||||
std::optional<u32> color;
|
||||
|
||||
size_t arraySize = 0;
|
||||
|
||||
auto startOffset = this->m_currOffset;
|
||||
PatternData *templatePattern;
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr)
|
||||
templatePattern = this->evaluateType(typeDecl);
|
||||
else if (auto builtinTypeDecl = dynamic_cast<ASTNodeBuiltinType*>(node->getType()); builtinTypeDecl != nullptr)
|
||||
templatePattern = this->evaluateBuiltinType(builtinTypeDecl);
|
||||
else
|
||||
this->getConsole().abortEvaluation("ASTNodeVariableDecl had an invalid type. This is a bug!");
|
||||
|
||||
auto entrySize = this->m_currOffset - startOffset;
|
||||
|
||||
ON_SCOPE_EXIT { delete templatePattern; };
|
||||
|
||||
auto sizeNode = node->getSize();
|
||||
if (auto numericExpression = dynamic_cast<ASTNodeNumericExpression*>(sizeNode); numericExpression != nullptr) {
|
||||
// Parse explicit size of array
|
||||
auto valueNode = this->evaluateMathematicalExpression(numericExpression);
|
||||
ON_SCOPE_EXIT { delete valueNode; };
|
||||
|
||||
arraySize = std::visit([this] (auto &&value) {
|
||||
using Type = std::remove_cvref_t<decltype(value)>;
|
||||
if constexpr (std::is_floating_point_v<Type>)
|
||||
this->getConsole().abortEvaluation("bitfield entry size must be an integer value");
|
||||
return static_cast<u64>(value);
|
||||
}, valueNode->getValue());
|
||||
} else if (auto whileLoopExpression = dynamic_cast<ASTNodeWhileStatement*>(sizeNode); whileLoopExpression != nullptr) {
|
||||
// Parse while loop based size of array
|
||||
auto conditionNode = this->evaluateMathematicalExpression(static_cast<ASTNodeNumericExpression*>(whileLoopExpression->getCondition()));
|
||||
ON_SCOPE_EXIT { delete conditionNode; };
|
||||
|
||||
while (std::visit([](auto &&value) { return value != 0; }, conditionNode->getValue())) {
|
||||
arraySize++;
|
||||
|
||||
delete conditionNode;
|
||||
conditionNode = this->evaluateMathematicalExpression(static_cast<ASTNodeNumericExpression*>(whileLoopExpression->getCondition()));
|
||||
}
|
||||
} else {
|
||||
// Parse unsized array
|
||||
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr) {
|
||||
if (auto builtinType = dynamic_cast<ASTNodeBuiltinType*>(typeDecl->getType()); builtinType != nullptr) {
|
||||
std::vector<u8> bytes(Token::getTypeSize(builtinType->getType()), 0x00);
|
||||
u64 offset = startOffset;
|
||||
|
||||
do {
|
||||
this->m_provider->read(offset, bytes.data(), bytes.size());
|
||||
offset += bytes.size();
|
||||
arraySize++;
|
||||
} while (!std::all_of(bytes.begin(), bytes.end(), [](u8 byte){ return byte == 0x00; }) && offset < this->m_provider->getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr) {
|
||||
if (auto builtinType = dynamic_cast<ASTNodeBuiltinType *>(typeDecl->getType()); builtinType != nullptr) {
|
||||
if (builtinType->getType() == Token::ValueType::Padding)
|
||||
return new PatternDataPadding(startOffset, entrySize * arraySize);
|
||||
}
|
||||
}
|
||||
|
||||
PatternData *pattern;
|
||||
if (dynamic_cast<PatternDataCharacter*>(templatePattern) != nullptr)
|
||||
pattern = new PatternDataString(startOffset, entrySize * arraySize, color.value_or(0));
|
||||
else if (dynamic_cast<PatternDataCharacter16*>(templatePattern) != nullptr)
|
||||
pattern = new PatternDataString16(startOffset, entrySize * arraySize, color.value_or(0));
|
||||
else {
|
||||
auto arrayPattern = new PatternDataStaticArray(startOffset, entrySize * arraySize, color.value_or(0));
|
||||
arrayPattern->setTypeName(templatePattern->getTypeName());
|
||||
arrayPattern->setEntries(templatePattern->clone(), arraySize);
|
||||
|
||||
pattern = arrayPattern;
|
||||
}
|
||||
|
||||
pattern->setVariableName(node->getName().data());
|
||||
pattern->setEndian(this->getCurrentEndian());
|
||||
|
||||
this->m_currOffset = startOffset + entrySize * arraySize;
|
||||
|
||||
return this->evaluateAttributes(node, pattern);
|
||||
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateDynamicArray(ASTNodeArrayVariableDecl *node) {
|
||||
auto startOffset = this->m_currOffset;
|
||||
|
||||
std::vector<PatternData*> entries;
|
||||
@ -991,8 +1115,6 @@ namespace hex::lang {
|
||||
PatternData *entry;
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr)
|
||||
entry = this->evaluateType(typeDecl);
|
||||
else if (auto builtinTypeDecl = dynamic_cast<ASTNodeBuiltinType*>(node->getType()); builtinTypeDecl != nullptr)
|
||||
entry = this->evaluateBuiltinType(builtinTypeDecl);
|
||||
else
|
||||
this->getConsole().abortEvaluation("ASTNodeVariableDecl had an invalid type. This is a bug!");
|
||||
|
||||
@ -1042,23 +1164,6 @@ namespace hex::lang {
|
||||
delete conditionNode;
|
||||
conditionNode = this->evaluateMathematicalExpression(static_cast<ASTNodeNumericExpression*>(whileLoopExpression->getCondition()));
|
||||
}
|
||||
} else {
|
||||
// Parse unsized array
|
||||
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr) {
|
||||
if (auto builtinType = dynamic_cast<ASTNodeBuiltinType*>(typeDecl->getType()); builtinType != nullptr) {
|
||||
std::vector<u8> bytes(Token::getTypeSize(builtinType->getType()), 0x00);
|
||||
u64 offset = startOffset;
|
||||
|
||||
u64 index = 0;
|
||||
do {
|
||||
this->m_provider->read(offset, bytes.data(), bytes.size());
|
||||
offset += bytes.size();
|
||||
addEntry(index);
|
||||
index++;
|
||||
} while (!std::all_of(bytes.begin(), bytes.end(), [](u8 byte){ return byte == 0x00; }) && offset < this->m_provider->getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto deleteEntries = SCOPE_GUARD {
|
||||
@ -1066,31 +1171,13 @@ namespace hex::lang {
|
||||
delete entry;
|
||||
};
|
||||
|
||||
if (auto typeDecl = dynamic_cast<ASTNodeTypeDecl*>(node->getType()); typeDecl != nullptr) {
|
||||
if (auto builtinType = dynamic_cast<ASTNodeBuiltinType *>(typeDecl->getType()); builtinType != nullptr) {
|
||||
if (builtinType->getType() == Token::ValueType::Padding)
|
||||
return new PatternDataPadding(startOffset, this->m_currOffset - startOffset);
|
||||
}
|
||||
}
|
||||
if (node->getSize() == nullptr)
|
||||
this->getConsole().abortEvaluation("no bounds provided for array");
|
||||
auto pattern = new PatternDataDynamicArray(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
|
||||
|
||||
PatternData *pattern;
|
||||
if (entries.empty())
|
||||
pattern = new PatternDataPadding(startOffset, 0);
|
||||
else if (dynamic_cast<PatternDataCharacter*>(entries[0]) != nullptr)
|
||||
pattern = new PatternDataString(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
|
||||
else if (dynamic_cast<PatternDataCharacter16*>(entries[0]) != nullptr)
|
||||
pattern = new PatternDataString16(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
|
||||
else {
|
||||
if (node->getSize() == nullptr)
|
||||
this->getConsole().abortEvaluation("no bounds provided for array");
|
||||
auto arrayPattern = new PatternDataArray(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
|
||||
|
||||
arrayPattern->setEntries(entries);
|
||||
deleteEntries.release();
|
||||
|
||||
pattern = arrayPattern;
|
||||
}
|
||||
deleteEntries.release();
|
||||
|
||||
pattern->setEntries(entries);
|
||||
pattern->setVariableName(node->getName().data());
|
||||
pattern->setEndian(this->getCurrentEndian());
|
||||
|
||||
|
@ -7,12 +7,13 @@
|
||||
#include <hex/lang/parser.hpp>
|
||||
#include <hex/lang/validator.hpp>
|
||||
#include <hex/lang/evaluator.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace hex::lang {
|
||||
|
||||
class PatternData;
|
||||
|
||||
PatternLanguage::PatternLanguage() {
|
||||
this->m_preprocessor = new Preprocessor();
|
||||
this->m_lexer = new Lexer();
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include <fontawesome_font.h>
|
||||
#include <codicons_font.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "views/view_command_palette.hpp"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace hex {
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include <imgui_imhex_extensions.h>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
ViewHelp::ViewHelp() : View("hex.view.help.about.name") {
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "views/view_hexeditor.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
|
||||
#include "providers/file_provider.hpp"
|
||||
#include "helpers/patches.hpp"
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <hex/lang/preprocessor.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <hex/helpers/literals.hpp>
|
||||
|
Loading…
x
Reference in New Issue
Block a user