Added proper error messages to data processor
This commit is contained in:
parent
fe7ae9450b
commit
5eb289f1fe
@ -32,6 +32,8 @@ namespace hex {
|
||||
int m_rightClickedId = -1;
|
||||
ImVec2 m_rightClickedCoords;
|
||||
|
||||
std::optional<dp::Node::NodeError> m_currNodeError;
|
||||
|
||||
void eraseLink(u32 id);
|
||||
void eraseNodes(const std::vector<int> &ids);
|
||||
void processNodes();
|
||||
|
@ -127,18 +127,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_value.reset();
|
||||
auto input = this->getIntegerOnInput(0);
|
||||
|
||||
if (!input.has_value()) {
|
||||
this->m_value.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_value = input.value();
|
||||
this->m_value = input;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<u64> m_value = 0;
|
||||
std::optional<u64> m_value;
|
||||
};
|
||||
|
||||
class NodeDisplayFloat : public dp::Node {
|
||||
@ -155,18 +151,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_value.reset();
|
||||
auto input = this->getFloatOnInput(0);
|
||||
|
||||
if (!input.has_value()) {
|
||||
this->m_value.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_value = input.value();
|
||||
this->m_value = input;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<float> m_value = 0;
|
||||
std::optional<float> m_value;
|
||||
};
|
||||
|
||||
|
||||
@ -177,10 +169,7 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getBufferOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> output = input.value();
|
||||
std::vector<u8> output = input;
|
||||
for (auto &byte : output)
|
||||
byte = ~byte;
|
||||
|
||||
@ -196,13 +185,10 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getBufferOnInput(0);
|
||||
auto inputB = this->getBufferOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> output(std::min(inputA->size(), inputB->size()), 0x00);
|
||||
std::vector<u8> output(std::min(inputA.size(), inputB.size()), 0x00);
|
||||
|
||||
for (u32 i = 0; i < output.size(); i++)
|
||||
output[i] = inputA.value()[i] & inputB.value()[i];
|
||||
output[i] = inputA[i] & inputB[i];
|
||||
|
||||
this->setBufferOnOutput(2, output);
|
||||
}
|
||||
@ -216,13 +202,10 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getBufferOnInput(0);
|
||||
auto inputB = this->getBufferOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> output(std::min(inputA->size(), inputB->size()), 0x00);
|
||||
std::vector<u8> output(std::min(inputA.size(), inputB.size()), 0x00);
|
||||
|
||||
for (u32 i = 0; i < output.size(); i++)
|
||||
output[i] = inputA.value()[i] | inputB.value()[i];
|
||||
output[i] = inputA[i] | inputB[i];
|
||||
|
||||
this->setBufferOnOutput(2, output);
|
||||
}
|
||||
@ -236,13 +219,10 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getBufferOnInput(0);
|
||||
auto inputB = this->getBufferOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> output(std::min(inputA->size(), inputB->size()), 0x00);
|
||||
std::vector<u8> output(std::min(inputA.size(), inputB.size()), 0x00);
|
||||
|
||||
for (u32 i = 0; i < output.size(); i++)
|
||||
output[i] = inputA.value()[i] ^ inputB.value()[i];
|
||||
output[i] = inputA[i] ^ inputB[i];
|
||||
|
||||
this->setBufferOnOutput(2, output);
|
||||
}
|
||||
@ -259,13 +239,10 @@ namespace hex::plugin::builtin {
|
||||
auto address = this->getIntegerOnInput(0);
|
||||
auto size = this->getIntegerOnInput(1);
|
||||
|
||||
if (!address.has_value() || !size.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> data;
|
||||
data.resize(size.value());
|
||||
data.resize(size);
|
||||
|
||||
SharedData::currentProvider->readRaw(address.value(), data.data(), size.value());
|
||||
SharedData::currentProvider->readRaw(address, data.data(), size);
|
||||
|
||||
this->setBufferOnOutput(2, data);
|
||||
}
|
||||
@ -279,10 +256,7 @@ namespace hex::plugin::builtin {
|
||||
auto address = this->getIntegerOnInput(0);
|
||||
auto data = this->getBufferOnInput(1);
|
||||
|
||||
if (!address.has_value() || !data.has_value())
|
||||
return;
|
||||
|
||||
this->setOverlayData(address.value(), data.value());
|
||||
this->setOverlayData(address, data);
|
||||
}
|
||||
};
|
||||
|
||||
@ -293,11 +267,8 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getIntegerOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
std::vector<u8> output(sizeof(u64), 0x00);
|
||||
std::memcpy(output.data(), &input.value(), sizeof(u64));
|
||||
std::memcpy(output.data(), &input, sizeof(u64));
|
||||
|
||||
this->setBufferOnOutput(1, output);
|
||||
}
|
||||
@ -310,11 +281,8 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getBufferOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
u64 output;
|
||||
std::memcpy(&output, input->data(), sizeof(u64));
|
||||
std::memcpy(&output, input.data(), sizeof(u64));
|
||||
|
||||
this->setIntegerOnOutput(1, output);
|
||||
}
|
||||
@ -332,13 +300,10 @@ namespace hex::plugin::builtin {
|
||||
auto trueData = this->getBufferOnInput(1);
|
||||
auto falseData = this->getBufferOnInput(2);
|
||||
|
||||
if (!cond.has_value() || !trueData.has_value() || !falseData.has_value())
|
||||
return;
|
||||
|
||||
if (cond.value() != 0)
|
||||
this->setBufferOnOutput(3, trueData.value());
|
||||
if (cond != 0)
|
||||
this->setBufferOnOutput(3, trueData);
|
||||
else
|
||||
this->setBufferOnOutput(3, falseData.value());
|
||||
this->setBufferOnOutput(3, falseData);
|
||||
|
||||
}
|
||||
};
|
||||
@ -353,10 +318,7 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getIntegerOnInput(0);
|
||||
auto inputB = this->getIntegerOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(2, inputA.value() == inputB.value());
|
||||
this->setIntegerOnOutput(2, inputA == inputB);
|
||||
}
|
||||
};
|
||||
|
||||
@ -368,10 +330,7 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getIntegerOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(1, !input.value());
|
||||
this->setIntegerOnOutput(1, !input);
|
||||
}
|
||||
};
|
||||
|
||||
@ -385,10 +344,7 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getIntegerOnInput(0);
|
||||
auto inputB = this->getIntegerOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(2, inputA.value() > inputB.value());
|
||||
this->setIntegerOnOutput(2, inputA > inputB);
|
||||
}
|
||||
};
|
||||
|
||||
@ -402,10 +358,7 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getIntegerOnInput(0);
|
||||
auto inputB = this->getIntegerOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(2, inputA.value() < inputB.value());
|
||||
this->setIntegerOnOutput(2, inputA < inputB);
|
||||
}
|
||||
};
|
||||
|
||||
@ -419,10 +372,7 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getIntegerOnInput(0);
|
||||
auto inputB = this->getIntegerOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(2, inputA.value() && inputB.value());
|
||||
this->setIntegerOnOutput(2, inputA && inputB);
|
||||
}
|
||||
};
|
||||
|
||||
@ -436,10 +386,7 @@ namespace hex::plugin::builtin {
|
||||
auto inputA = this->getIntegerOnInput(0);
|
||||
auto inputB = this->getIntegerOnInput(1);
|
||||
|
||||
if (!inputA.has_value() || !inputB.has_value())
|
||||
return;
|
||||
|
||||
this->setIntegerOnOutput(2, inputA.value() || inputB.value());
|
||||
this->setIntegerOnOutput(2, inputA || inputB);
|
||||
}
|
||||
};
|
||||
|
||||
@ -464,18 +411,18 @@ namespace hex::plugin::builtin {
|
||||
auto nonce = this->getBufferOnInput(2);
|
||||
auto input = this->getBufferOnInput(3);
|
||||
|
||||
if (!key.has_value() || !iv.has_value() || !nonce.has_value() || !input.has_value())
|
||||
return;
|
||||
if (key.empty())
|
||||
throwNodeError("Key cannot be empty");
|
||||
|
||||
if (key->empty() || input->empty())
|
||||
return;
|
||||
if (input.empty())
|
||||
throwNodeError("Input cannot be empty");
|
||||
|
||||
std::array<u8, 8> ivData = { 0 }, nonceData = { 0 };
|
||||
|
||||
std::copy(iv->begin(), iv->end(), ivData.begin());
|
||||
std::copy(nonce->begin(), nonce->end(), nonceData.begin());
|
||||
std::copy(iv.begin(), iv.end(), ivData.begin());
|
||||
std::copy(nonce.begin(), nonce.end(), nonceData.begin());
|
||||
|
||||
auto output = crypt::aesDecrypt(static_cast<crypt::AESMode>(this->m_mode), static_cast<crypt::KeyLength>(this->m_keyLength), key.value(), nonceData, ivData, input.value());
|
||||
auto output = crypt::aesDecrypt(static_cast<crypt::AESMode>(this->m_mode), static_cast<crypt::KeyLength>(this->m_keyLength), key, nonceData, ivData, input);
|
||||
|
||||
this->setBufferOnOutput(4, output);
|
||||
}
|
||||
@ -494,10 +441,7 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getBufferOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
auto output = crypt::decode64(input.value());
|
||||
auto output = crypt::decode64(input);
|
||||
|
||||
this->setBufferOnOutput(1, output);
|
||||
}
|
||||
@ -512,19 +456,16 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
auto input = this->getBufferOnInput(0);
|
||||
|
||||
if (!input.has_value())
|
||||
return;
|
||||
|
||||
if (input->size() % 2 != 0)
|
||||
return;
|
||||
if (input.size() % 2 != 0)
|
||||
throwNodeError("Can't decode odd number of hex characters");
|
||||
|
||||
std::vector<u8> output;
|
||||
for (u32 i = 0; i < input->size(); i += 2) {
|
||||
char c1 = tolower(input->at(i));
|
||||
char c2 = tolower(input->at(i + 1));
|
||||
for (u32 i = 0; i < input.size(); i += 2) {
|
||||
char c1 = tolower(input[i]);
|
||||
char c2 = tolower(input[i + 1]);
|
||||
|
||||
if (!std::isxdigit(c1) || !isxdigit(c2))
|
||||
return;
|
||||
throwNodeError("Can't decode non-hexadecimal character");
|
||||
|
||||
u8 value;
|
||||
if (std::isdigit(c1))
|
||||
|
@ -36,7 +36,7 @@ namespace hex::dp {
|
||||
|
||||
[[nodiscard]] Node* getParentNode() { return this->m_parentNode; }
|
||||
|
||||
[[nodiscard]] std::vector<u8>& getOutputData() { return this->m_outputData; }
|
||||
[[nodiscard]] std::optional<std::vector<u8>>& getOutputData() { return this->m_outputData; }
|
||||
private:
|
||||
u32 m_id;
|
||||
IOType m_ioType;
|
||||
@ -45,7 +45,7 @@ namespace hex::dp {
|
||||
std::map<u32, Attribute*> m_connectedAttributes;
|
||||
Node *m_parentNode;
|
||||
|
||||
std::vector<u8> m_outputData;
|
||||
std::optional<std::vector<u8>> m_outputData;
|
||||
|
||||
friend class Node;
|
||||
void setParentNode(Node *node) { this->m_parentNode = node; }
|
||||
|
@ -23,6 +23,14 @@ namespace hex::dp {
|
||||
|
||||
virtual void drawNode() { }
|
||||
virtual void process() = 0;
|
||||
|
||||
using NodeError = std::pair<Node*, std::string>;
|
||||
|
||||
void resetOutputData() {
|
||||
for (auto &attribute : this->m_attributes)
|
||||
attribute.getOutputData().reset();
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_id;
|
||||
std::string m_title;
|
||||
@ -43,49 +51,71 @@ namespace hex::dp {
|
||||
|
||||
protected:
|
||||
|
||||
std::optional<std::vector<u8>> getBufferOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
if (attribute == nullptr || attribute->getType() != Attribute::Type::Buffer)
|
||||
return { };
|
||||
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
||||
return outputData;
|
||||
[[noreturn]] void throwNodeError(std::string_view message) {
|
||||
throw NodeError(this, message);
|
||||
}
|
||||
|
||||
std::optional<u64> getIntegerOnInput(u32 index) {
|
||||
std::vector<u8> getBufferOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
if (attribute == nullptr || attribute->getType() != Attribute::Type::Integer)
|
||||
return { };
|
||||
if (attribute == nullptr)
|
||||
throwNodeError(hex::format("Nothing connected to input '%s'", this->m_attributes[index].getName().data()));
|
||||
|
||||
if (attribute->getType() != Attribute::Type::Buffer)
|
||||
throwNodeError("Tried to read buffer from non-buffer attribute");
|
||||
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
||||
if (outputData.empty() || outputData.size() < sizeof(u64))
|
||||
return { };
|
||||
else
|
||||
return *reinterpret_cast<u64*>(outputData.data());
|
||||
if (!outputData.has_value())
|
||||
throw std::runtime_error("No data available at connected attribute");
|
||||
|
||||
return outputData.value();
|
||||
}
|
||||
|
||||
std::optional<float> getFloatOnInput(u32 index) {
|
||||
u64 getIntegerOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
if (attribute == nullptr || attribute->getType() != Attribute::Type::Float)
|
||||
return { };
|
||||
if (attribute == nullptr)
|
||||
throwNodeError(hex::format("Nothing connected to input '%s'", this->m_attributes[index].getName().data()));
|
||||
|
||||
if (attribute->getType() != Attribute::Type::Integer)
|
||||
throwNodeError("Tried to read integer from non-integer attribute");
|
||||
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
||||
if (outputData.empty() || outputData.size() < sizeof(float))
|
||||
return { };
|
||||
else
|
||||
return *reinterpret_cast<float*>(outputData.data());
|
||||
if (!outputData.has_value())
|
||||
throw std::runtime_error("No data available at connected attribute");
|
||||
|
||||
if (outputData->size() < sizeof(u64))
|
||||
throw std::runtime_error("Not enough data provided for integer");
|
||||
|
||||
return *reinterpret_cast<u64*>(outputData->data());
|
||||
}
|
||||
|
||||
float getFloatOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
if (attribute == nullptr)
|
||||
throwNodeError(hex::format("Nothing connected to input '%s'", this->m_attributes[index].getName().data()));
|
||||
|
||||
if (attribute->getType() != Attribute::Type::Float)
|
||||
throwNodeError("Tried to read float from non-float attribute");
|
||||
|
||||
attribute->getParentNode()->process();
|
||||
|
||||
auto &outputData = attribute->getOutputData();
|
||||
|
||||
if (!outputData.has_value())
|
||||
throw std::runtime_error("No data available at connected attribute");
|
||||
|
||||
if (outputData->size() < sizeof(float))
|
||||
throw std::runtime_error("Not enough data provided for float");
|
||||
|
||||
return *reinterpret_cast<float*>(outputData->data());
|
||||
}
|
||||
|
||||
void setBufferOnOutput(u32 index, std::vector<u8> data) {
|
||||
|
@ -17,7 +17,7 @@ namespace hex::prv {
|
||||
constexpr static size_t PageSize = 0x1000'0000;
|
||||
|
||||
Provider();
|
||||
virtual ~Provider() = default;
|
||||
virtual ~Provider();
|
||||
|
||||
virtual bool isAvailable() = 0;
|
||||
virtual bool isReadable() = 0;
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
@ -14,6 +13,11 @@ namespace hex::prv {
|
||||
this->m_patches.emplace_back();
|
||||
}
|
||||
|
||||
Provider::~Provider() {
|
||||
for (auto &overlay : this->m_overlays)
|
||||
this->deleteOverlay(overlay);
|
||||
}
|
||||
|
||||
void Provider::read(u64 offset, void *buffer, size_t size) {
|
||||
this->readRaw(offset, buffer, size);
|
||||
}
|
||||
|
@ -35,6 +35,13 @@ namespace hex {
|
||||
|
||||
imnodes::GetStyle().flags = imnodes::StyleFlags(imnodes::StyleFlags_NodeOutline | imnodes::StyleFlags_GridLines);
|
||||
});
|
||||
|
||||
View::subscribeEvent(Events::FileLoaded, [this](auto) {
|
||||
for (auto &node : this->m_nodes) {
|
||||
node->setCurrentOverlay(nullptr);
|
||||
}
|
||||
this->m_dataOverlays.clear();
|
||||
});
|
||||
}
|
||||
|
||||
ViewDataProcessor::~ViewDataProcessor() {
|
||||
@ -103,11 +110,20 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
u32 overlayIndex = 0;
|
||||
for (auto &endNode : this->m_endNodes) {
|
||||
(void)endNode->process();
|
||||
overlayIndex++;
|
||||
this->m_currNodeError.reset();
|
||||
|
||||
try {
|
||||
for (auto &endNode : this->m_endNodes) {
|
||||
endNode->resetOutputData();
|
||||
endNode->process();
|
||||
}
|
||||
} catch (dp::Node::NodeError &e) {
|
||||
this->m_currNodeError = e;
|
||||
} catch (std::runtime_error &e) {
|
||||
printf("Node implementation bug! %s\n", e.what());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ViewDataProcessor::drawContent() {
|
||||
@ -197,9 +213,25 @@ namespace hex {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
{
|
||||
int nodeId;
|
||||
if (imnodes::IsNodeHovered(&nodeId) && this->m_currNodeError.has_value() && this->m_currNodeError->first->getID() == nodeId) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted("Error");
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted(this->m_currNodeError->second.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
imnodes::BeginNodeEditor();
|
||||
|
||||
for (auto& node : this->m_nodes) {
|
||||
const bool hasError = this->m_currNodeError.has_value() && this->m_currNodeError->first == node;
|
||||
|
||||
if (hasError)
|
||||
imnodes::PushColorStyle(imnodes::ColorStyle_NodeOutline, 0xFF0000FF);
|
||||
|
||||
imnodes::BeginNode(node->getID());
|
||||
|
||||
imnodes::BeginNodeTitleBar();
|
||||
@ -229,6 +261,9 @@ namespace hex {
|
||||
}
|
||||
|
||||
imnodes::EndNode();
|
||||
|
||||
if (hasError)
|
||||
imnodes::PopColorStyle();
|
||||
}
|
||||
|
||||
for (const auto &link : this->m_links)
|
||||
|
Loading…
x
Reference in New Issue
Block a user