Added proper error messages to data processor

This commit is contained in:
WerWolv 2021-02-04 01:14:05 +01:00
parent fe7ae9450b
commit 5eb289f1fe
7 changed files with 145 additions and 133 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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