2023-01-08 16:06:26 +01:00
|
|
|
#include <content/views/view_pattern_data.hpp>
|
2020-11-10 21:31:04 +01:00
|
|
|
|
2023-01-08 16:06:26 +01:00
|
|
|
#include <hex/api/content_registry.hpp>
|
2021-01-13 17:28:27 +01:00
|
|
|
#include <hex/providers/provider.hpp>
|
2022-02-27 23:25:39 +01:00
|
|
|
|
2022-04-17 16:57:30 +02:00
|
|
|
#include <pl/patterns/pattern.hpp>
|
2023-05-13 11:12:38 +02:00
|
|
|
#include <wolv/utils/lock.hpp>
|
2020-11-11 10:47:02 +01:00
|
|
|
|
2021-12-07 22:47:41 +01:00
|
|
|
namespace hex::plugin::builtin {
|
2020-11-10 21:31:04 +01:00
|
|
|
|
2023-11-21 13:47:50 +01:00
|
|
|
ViewPatternData::ViewPatternData() : View::Window("hex.builtin.view.pattern_data.name") {
|
2023-10-04 12:00:32 +02:00
|
|
|
this->m_patternDrawer = std::make_unique<ui::PatternDrawer>();
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Handle tree style setting changes
|
2023-11-10 20:47:08 +01:00
|
|
|
EventManager::subscribe<EventSettingsChanged>(this, [this] {
|
2023-03-21 15:33:43 +01:00
|
|
|
auto patternStyle = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_tree_style", 0);
|
2023-11-10 20:47:08 +01:00
|
|
|
this->m_patternDrawer->setTreeStyle(patternStyle);
|
2023-11-25 13:42:51 +01:00
|
|
|
|
|
|
|
auto rowColoring = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_data_row_bg", false);
|
|
|
|
this->m_patternDrawer->enableRowColoring(rowColoring);
|
2023-01-08 16:06:26 +01:00
|
|
|
});
|
2023-01-24 23:27:15 +01:00
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Reset the pattern drawer when the provider changes
|
2023-01-24 23:27:15 +01:00
|
|
|
EventManager::subscribe<EventProviderChanged>(this, [this](auto, auto) {
|
2023-10-04 12:00:32 +02:00
|
|
|
this->m_patternDrawer->reset();
|
2023-01-24 23:27:15 +01:00
|
|
|
});
|
2023-02-17 14:53:15 +01:00
|
|
|
|
feat: Added hex::group attribute and various fixes (#1302)
As discussed (many times) on Discord, does the same as the new favorite
tag, but instead allows you to add multiple groups.
Initially, this would cause some insane issues with draw/reset
(apparantly) fighting eachother in the pattern drawer. After a lot of
trial and error, I decided to rewrite the flow that is responsible for
calling reset. Now evaluating patterns is the one to decide when the
reset happens, not the core "game"-loop.
To make sure that draw and reset can never happen at the same time, the
mutex originally used for the favorites has been repurposed. Due to the
restructuring, the mutex in the favorite-task is no longer needed, as
that will only ever kick-off after reset is called and if there are
actually patterns, which can never line up to be accessed on different
threads at the same time.
Last but not least, I noticed that hard crashes could result in your
config file getting overridden. I added a check to prevent that.
Last I issue I can see is that if you use an excessive amount of
favorites/groups, a crash can still happen, but it only happens when you
close the program (occasionally, but unpredictable). Before, this would
happen if you ran the evaluation a second time. I boiled the cause of
the crash down to these lines of code in evaluator.cpp >
patternDestroyed:
```cpp
if (pattern->isPatternLocal()) {
if (auto it = this->m_patternLocalStorage.find(pattern->getHeapAddress()); it != this->m_patternLocalStorage.end()) {
auto &[key, data] = *it;
data.referenceCount--;
if (data.referenceCount == 0)
this->m_patternLocalStorage.erase(it);
} else if (!this->m_evaluated) {
err::E0001.throwError(fmt::format("Double free of variable named '{}'.", pattern->getVariableName()));
}
}
```
Specifically, trying to access the `*it` is the reason for the crash
(this was also the cause of the crashes before my fixes, but then during
evaluation).
I'm suspecting the root cause is somewhere in the `.clone` methods of
the patterns. I'd say that for now a crash when closing the program is
more acceptable than during evaluation (which can even happen if you use
favorites).
2023-09-16 13:09:59 +02:00
|
|
|
EventManager::subscribe<EventPatternEvaluating>(this, [this]{
|
2023-10-04 12:00:32 +02:00
|
|
|
this->m_patternDrawer->reset();
|
feat: Added hex::group attribute and various fixes (#1302)
As discussed (many times) on Discord, does the same as the new favorite
tag, but instead allows you to add multiple groups.
Initially, this would cause some insane issues with draw/reset
(apparantly) fighting eachother in the pattern drawer. After a lot of
trial and error, I decided to rewrite the flow that is responsible for
calling reset. Now evaluating patterns is the one to decide when the
reset happens, not the core "game"-loop.
To make sure that draw and reset can never happen at the same time, the
mutex originally used for the favorites has been repurposed. Due to the
restructuring, the mutex in the favorite-task is no longer needed, as
that will only ever kick-off after reset is called and if there are
actually patterns, which can never line up to be accessed on different
threads at the same time.
Last but not least, I noticed that hard crashes could result in your
config file getting overridden. I added a check to prevent that.
Last I issue I can see is that if you use an excessive amount of
favorites/groups, a crash can still happen, but it only happens when you
close the program (occasionally, but unpredictable). Before, this would
happen if you ran the evaluation a second time. I boiled the cause of
the crash down to these lines of code in evaluator.cpp >
patternDestroyed:
```cpp
if (pattern->isPatternLocal()) {
if (auto it = this->m_patternLocalStorage.find(pattern->getHeapAddress()); it != this->m_patternLocalStorage.end()) {
auto &[key, data] = *it;
data.referenceCount--;
if (data.referenceCount == 0)
this->m_patternLocalStorage.erase(it);
} else if (!this->m_evaluated) {
err::E0001.throwError(fmt::format("Double free of variable named '{}'.", pattern->getVariableName()));
}
}
```
Specifically, trying to access the `*it` is the reason for the crash
(this was also the cause of the crashes before my fixes, but then during
evaluation).
I'm suspecting the root cause is somewhere in the `.clone` methods of
the patterns. I'd say that for now a crash when closing the program is
more acceptable than during evaluation (which can even happen if you use
favorites).
2023-09-16 13:09:59 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
EventManager::subscribe<EventPatternExecuted>(this, [this](auto){
|
2023-10-04 12:00:32 +02:00
|
|
|
this->m_patternDrawer->reset();
|
feat: Added hex::group attribute and various fixes (#1302)
As discussed (many times) on Discord, does the same as the new favorite
tag, but instead allows you to add multiple groups.
Initially, this would cause some insane issues with draw/reset
(apparantly) fighting eachother in the pattern drawer. After a lot of
trial and error, I decided to rewrite the flow that is responsible for
calling reset. Now evaluating patterns is the one to decide when the
reset happens, not the core "game"-loop.
To make sure that draw and reset can never happen at the same time, the
mutex originally used for the favorites has been repurposed. Due to the
restructuring, the mutex in the favorite-task is no longer needed, as
that will only ever kick-off after reset is called and if there are
actually patterns, which can never line up to be accessed on different
threads at the same time.
Last but not least, I noticed that hard crashes could result in your
config file getting overridden. I added a check to prevent that.
Last I issue I can see is that if you use an excessive amount of
favorites/groups, a crash can still happen, but it only happens when you
close the program (occasionally, but unpredictable). Before, this would
happen if you ran the evaluation a second time. I boiled the cause of
the crash down to these lines of code in evaluator.cpp >
patternDestroyed:
```cpp
if (pattern->isPatternLocal()) {
if (auto it = this->m_patternLocalStorage.find(pattern->getHeapAddress()); it != this->m_patternLocalStorage.end()) {
auto &[key, data] = *it;
data.referenceCount--;
if (data.referenceCount == 0)
this->m_patternLocalStorage.erase(it);
} else if (!this->m_evaluated) {
err::E0001.throwError(fmt::format("Double free of variable named '{}'.", pattern->getVariableName()));
}
}
```
Specifically, trying to access the `*it` is the reason for the crash
(this was also the cause of the crashes before my fixes, but then during
evaluation).
I'm suspecting the root cause is somewhere in the `.clone` methods of
the patterns. I'd say that for now a crash when closing the program is
more acceptable than during evaluation (which can even happen if you use
favorites).
2023-09-16 13:09:59 +02:00
|
|
|
});
|
|
|
|
|
2023-08-29 12:14:12 +02:00
|
|
|
// Handle jumping to a pattern's location when it is clicked
|
2023-10-04 12:00:32 +02:00
|
|
|
this->m_patternDrawer->setSelectionCallback([](Region region){ ImHexApi::HexEditor::setSelection(region); });
|
2020-11-10 21:31:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ViewPatternData::~ViewPatternData() {
|
2023-01-24 23:27:15 +01:00
|
|
|
EventManager::unsubscribe<EventSettingsChanged>(this);
|
|
|
|
EventManager::unsubscribe<EventProviderChanged>(this);
|
feat: Added hex::group attribute and various fixes (#1302)
As discussed (many times) on Discord, does the same as the new favorite
tag, but instead allows you to add multiple groups.
Initially, this would cause some insane issues with draw/reset
(apparantly) fighting eachother in the pattern drawer. After a lot of
trial and error, I decided to rewrite the flow that is responsible for
calling reset. Now evaluating patterns is the one to decide when the
reset happens, not the core "game"-loop.
To make sure that draw and reset can never happen at the same time, the
mutex originally used for the favorites has been repurposed. Due to the
restructuring, the mutex in the favorite-task is no longer needed, as
that will only ever kick-off after reset is called and if there are
actually patterns, which can never line up to be accessed on different
threads at the same time.
Last but not least, I noticed that hard crashes could result in your
config file getting overridden. I added a check to prevent that.
Last I issue I can see is that if you use an excessive amount of
favorites/groups, a crash can still happen, but it only happens when you
close the program (occasionally, but unpredictable). Before, this would
happen if you ran the evaluation a second time. I boiled the cause of
the crash down to these lines of code in evaluator.cpp >
patternDestroyed:
```cpp
if (pattern->isPatternLocal()) {
if (auto it = this->m_patternLocalStorage.find(pattern->getHeapAddress()); it != this->m_patternLocalStorage.end()) {
auto &[key, data] = *it;
data.referenceCount--;
if (data.referenceCount == 0)
this->m_patternLocalStorage.erase(it);
} else if (!this->m_evaluated) {
err::E0001.throwError(fmt::format("Double free of variable named '{}'.", pattern->getVariableName()));
}
}
```
Specifically, trying to access the `*it` is the reason for the crash
(this was also the cause of the crashes before my fixes, but then during
evaluation).
I'm suspecting the root cause is somewhere in the `.clone` methods of
the patterns. I'd say that for now a crash when closing the program is
more acceptable than during evaluation (which can even happen if you use
favorites).
2023-09-16 13:09:59 +02:00
|
|
|
EventManager::unsubscribe<EventPatternEvaluating>(this);
|
|
|
|
EventManager::unsubscribe<EventPatternExecuted>(this);
|
2020-11-10 21:31:04 +01:00
|
|
|
}
|
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
void ViewPatternData::drawContent() {
|
2023-11-21 13:47:50 +01:00
|
|
|
// Draw the pattern tree if the provider is valid
|
|
|
|
if (ImHexApi::Provider::isValid()) {
|
|
|
|
// Make sure the runtime has finished evaluating and produced valid patterns
|
|
|
|
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
2023-11-28 10:21:54 +01:00
|
|
|
|
|
|
|
const auto height = std::max(ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().FramePadding.y * 2, ImGui::GetTextLineHeightWithSpacing() * 5);
|
2023-11-21 13:47:50 +01:00
|
|
|
if (!runtime.arePatternsValid()) {
|
2023-11-28 10:21:54 +01:00
|
|
|
this->m_patternDrawer->draw({ }, nullptr, height);
|
2023-11-21 13:47:50 +01:00
|
|
|
} else {
|
|
|
|
// If the runtime has finished evaluating, draw the patterns
|
|
|
|
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
2023-11-28 10:21:54 +01:00
|
|
|
this->m_patternDrawer->draw(runtime.getPatterns(), &runtime, height);
|
2023-04-17 17:02:10 +02:00
|
|
|
}
|
2020-11-10 21:31:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-19 23:01:57 +02:00
|
|
|
}
|