1
0
mirror of synced 2024-09-23 19:18:24 +02:00

feat: Added Experiments

This commit is contained in:
WerWolv 2023-11-10 14:48:26 +01:00
parent 4fc2fb7a6f
commit 3aacf0f1fb
4 changed files with 150 additions and 79 deletions

View File

@ -65,4 +65,5 @@ readability-*,
-readability-redundant-access-specifiers,
-readability-function-cognitive-complexity,
-readability-identifier-naming,
-readability-qualified-auto'
*-include-cleaner,
-readability-qualified-auto'

View File

@ -11,9 +11,7 @@
#include <map>
#include <span>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
@ -184,7 +182,7 @@ namespace hex {
[[nodiscard]] ImColor getColor() const;
private:
std::array<float, 4> m_value;
std::array<float, 4> m_value{};
};
class DropDown : public Widget {
public:
@ -316,8 +314,8 @@ namespace hex {
DisplayCallback displayCallback;
};
std::vector<impl::Entry> &getEntries();
std::vector<impl::Handler> &getHandlers();
std::vector<Entry> &getEntries();
std::vector<Handler> &getHandlers();
}
@ -340,7 +338,6 @@ namespace hex {
* @brief Adds a new command handler to the command palette
* @param type The type of the command
* @param command The command to add
* @param unlocalizedDescription The description of the command
* @param queryCallback The callback that will be called when the command palette wants to load the name and callback items
* @param displayCallback The callback that will be called when the command is displayed in the command palette
*/
@ -376,7 +373,7 @@ namespace hex {
std::map<std::string, Visualizer> &getVisualizers();
std::map<std::string, Visualizer> &getInlineVisualizers();
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
std::vector<impl::FunctionDefinition> &getFunctions();
std::vector<FunctionDefinition> &getFunctions();
}
@ -429,19 +426,19 @@ namespace hex {
* @brief Adds a new visualizer to the pattern language
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
* @param name The name of the visualizer
* @param func The function callback
* @param function The function callback
* @param parameterCount The amount of parameters the function takes
*/
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, pl::api::FunctionParameterCount parameterCount);
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount);
/**
* @brief Adds a new inline visualizer to the pattern language
* @note Inline visualizers are extensions to the [[hex::inline_visualize]] attribute, used to visualize data
* @param name The name of the visualizer
* @param func The function callback
* @param function The function callback
* @param parameterCount The amount of parameters the function takes
*/
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, pl::api::FunctionParameterCount parameterCount);
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount);
}
@ -487,7 +484,7 @@ namespace hex {
bool detached;
};
std::vector<impl::Entry> &getEntries();
std::vector<Entry> &getEntries();
}
@ -519,11 +516,11 @@ namespace hex {
std::string unlocalizedName;
size_t requiredSize;
size_t maxSize;
impl::GeneratorFunction generatorFunction;
std::optional<impl::EditingFunction> editingFunction;
GeneratorFunction generatorFunction;
std::optional<EditingFunction> editingFunction;
};
std::vector<impl::Entry> &getEntries();
std::vector<Entry> &getEntries();
}
@ -562,7 +559,7 @@ namespace hex {
void add(const Entry &entry);
std::vector<impl::Entry> &getEntries();
std::vector<Entry> &getEntries();
}
@ -647,14 +644,14 @@ namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$";
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems();
std::multimap<u32, impl::MenuItem> &getMenuItems();
std::multimap<u32, MainMenuItem> &getMainMenuItems();
std::multimap<u32, MenuItem> &getMenuItems();
std::vector<impl::DrawCallback> &getWelcomeScreenEntries();
std::vector<impl::DrawCallback> &getFooterItems();
std::vector<impl::DrawCallback> &getToolbarItems();
std::vector<impl::SidebarItem> &getSidebarItems();
std::vector<impl::TitleBarButton> &getTitleBarButtons();
std::vector<DrawCallback> &getWelcomeScreenEntries();
std::vector<DrawCallback> &getFooterItems();
std::vector<DrawCallback> &getToolbarItems();
std::vector<SidebarItem> &getSidebarItems();
std::vector<TitleBarButton> &getTitleBarButtons();
}
@ -682,7 +679,6 @@ namespace hex {
* @param priority The priority of the entry. Lower values are displayed first
* @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the shortcut will work globally
*/
void addMenuItemSubMenu(std::vector<std::string> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback = []{ return true; });
@ -745,16 +741,16 @@ namespace hex {
* @tparam T The provider type that extends hex::prv::Provider
* @param addToList Whether to display the provider in the Other Providers list in the welcome screen and File menu
*/
template<std::derived_from<hex::prv::Provider> T>
template<std::derived_from<prv::Provider> T>
void add(bool addToList = true) {
auto typeName = T().getTypeName();
(void)EventManager::subscribe<RequestCreateProvider>([expectedName = typeName](const std::string &name, bool skipLoadInterface, bool selectProvider, hex::prv::Provider **provider) {
(void)EventManager::subscribe<RequestCreateProvider>([expectedName = typeName](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
if (name != expectedName) return;
prv::Provider *newProvider = new T();
hex::ImHexApi::Provider::add(newProvider, skipLoadInterface, selectProvider);
ImHexApi::Provider::add(newProvider, skipLoadInterface, selectProvider);
if (provider != nullptr)
*provider = newProvider;
@ -777,7 +773,7 @@ namespace hex {
Callback callback;
};
std::vector<impl::Entry> &getEntries();
std::vector<Entry> &getEntries();
}
@ -802,7 +798,7 @@ namespace hex {
Callback callback;
};
std::vector<impl::Entry> &getEntries();
std::vector<Entry> &getEntries();
}
@ -858,7 +854,6 @@ namespace hex {
/**
* @brief Adds a new cell data visualizer
* @tparam T The data visualizer type that extends hex::DataVisualizer
* @param unlocalizedName The unlocalized name of the data visualizer
* @param args The arguments to pass to the constructor of the data visualizer
*/
template<std::derived_from<DataVisualizer> T, typename... Args>
@ -955,6 +950,7 @@ namespace hex {
}
/* Background Service Registry. Allows adding new background services */
namespace BackgroundServices {
namespace impl {
@ -972,6 +968,7 @@ namespace hex {
void registerService(const std::string &unlocalizedName, const impl::Callback &callback);
}
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
namespace CommunicationInterface {
namespace impl {
@ -983,6 +980,25 @@ namespace hex {
void registerNetworkEndpoint(const std::string &endpoint, const impl::NetworkCallback &callback);
}
/* Experiments Registry. Allows adding new experiments */
namespace Experiments {
namespace impl {
struct Experiment {
std::string unlocalizedName, unlocalizedDescription;
bool enabled;
};
std::map<std::string, Experiment> &getExperiments();
}
void addExperiment(const std::string &experimentName, const std::string &unlocalizedName, const std::string &unlocalizedDescription = "");
void enableExperiement(const std::string &experimentName, bool enabled);
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName);
}
}
}

View File

@ -132,18 +132,19 @@ namespace hex {
}
std::vector<Category> &getSettings() {
static std::vector<impl::Category> categories;
static std::vector<Category> categories;
return categories;
}
Widgets::Widget* add(const std::string &unlocalizedCategory, const std::string &unlocalizedSubCategory, const std::string &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget) {
auto category = impl::insertOrGetEntry(impl::getSettings(), unlocalizedCategory);
auto subCategory = impl::insertOrGetEntry(category->subCategories, unlocalizedSubCategory);
auto entry = impl::insertOrGetEntry(subCategory->entries, unlocalizedName);
const auto category = insertOrGetEntry(getSettings(), unlocalizedCategory);
const auto subCategory = insertOrGetEntry(category->subCategories, unlocalizedSubCategory);
const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
entry->widget = std::move(widget);
entry->widget->load(getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
entry->widget->onChanged();
return entry->widget.get();
}
@ -151,7 +152,7 @@ namespace hex {
}
void setCategoryDescription(const std::string &unlocalizedCategory, const std::string &unlocalizedDescription) {
auto category = impl::insertOrGetEntry(impl::getSettings(), unlocalizedCategory);
const auto category = insertOrGetEntry(impl::getSettings(), unlocalizedCategory);
category->unlocalizedDescription = unlocalizedDescription;
}
@ -247,9 +248,9 @@ namespace hex {
}
nlohmann::json ColorPicker::store() {
ImColor color(this->m_value[0], this->m_value[1], this->m_value[2], this->m_value[3]);
const ImColor color(this->m_value[0], this->m_value[1], this->m_value[2], this->m_value[3]);
return ImU32(color);
return static_cast<ImU32>(color);
}
ImColor ColorPicker::getColor() const {
@ -259,7 +260,7 @@ namespace hex {
bool DropDown::draw(const std::string &name) {
const char *preview = "";
if (size_t(this->m_value) < this->m_items.size())
if (static_cast<size_t>(this->m_value) < this->m_items.size())
preview = this->m_items[this->m_value].c_str();
bool changed = false;
@ -267,7 +268,7 @@ namespace hex {
int index = 0;
for (const auto &item : this->m_items) {
bool selected = (index == this->m_value);
const bool selected = index == this->m_value;
if (ImGui::Selectable(LangEntry(item), selected)) {
this->m_value = index;
@ -310,7 +311,7 @@ namespace hex {
nlohmann::json DropDown::store() {
if (this->m_value == -1)
return this->m_defaultItem;
if (size_t(this->m_value) >= this->m_items.size())
if (static_cast<size_t>(this->m_value) >= this->m_items.size())
return this->m_defaultItem;
return this->m_settingsValues[this->m_value];
@ -382,13 +383,13 @@ namespace hex {
void add(Type type, const std::string &command, const std::string &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
log::debug("Registered new command palette command: {}", command);
impl::getEntries().push_back(ContentRegistry::CommandPaletteCommands::impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
impl::getEntries().push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
}
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
log::debug("Registered new command palette command handler: {}", command);
impl::getHandlers().push_back(ContentRegistry::CommandPaletteCommands::impl::Handler { type, command, queryCallback, displayCallback });
impl::getHandlers().push_back(impl::Handler { type, command, queryCallback, displayCallback });
}
namespace impl {
@ -451,11 +452,11 @@ namespace hex {
runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns));
for (const auto &func : impl::getFunctions()) {
if (func.dangerous)
runtime.addDangerousFunction(func.ns, func.name, func.parameterCount, func.callback);
for (const auto &[ns, name, paramCount, callback, dangerous] : impl::getFunctions()) {
if (dangerous)
runtime.addDangerousFunction(ns, name, paramCount, callback);
else
runtime.addFunction(func.ns, func.name, func.parameterCount, func.callback);
runtime.addFunction(ns, name, paramCount, callback);
}
for (const auto &[name, callback] : impl::getPragmas()) {
@ -506,14 +507,14 @@ namespace hex {
namespace impl {
std::map<std::string, impl::Visualizer> &getVisualizers() {
static std::map<std::string, impl::Visualizer> visualizers;
std::map<std::string, Visualizer> &getVisualizers() {
static std::map<std::string, Visualizer> visualizers;
return visualizers;
}
std::map<std::string, impl::Visualizer> &getInlineVisualizers() {
static std::map<std::string, impl::Visualizer> visualizers;
std::map<std::string, Visualizer> &getInlineVisualizers() {
static std::map<std::string, Visualizer> visualizers;
return visualizers;
}
@ -524,8 +525,8 @@ namespace hex {
return pragmas;
}
std::vector<impl::FunctionDefinition> &getFunctions() {
static std::vector<impl::FunctionDefinition> functions;
std::vector<FunctionDefinition> &getFunctions() {
static std::vector<FunctionDefinition> functions;
return functions;
}
@ -551,7 +552,7 @@ namespace hex {
void impl::add(std::unique_ptr<View> &&view) {
log::debug("Registered new view: {}", view->getUnlocalizedName());
impl::getEntries().insert({ view->getUnlocalizedName(), std::move(view) });
getEntries().insert({ view->getUnlocalizedName(), std::move(view) });
}
View* getViewByName(const std::string &unlocalizedName) {
@ -601,8 +602,8 @@ namespace hex {
namespace impl {
std::vector<impl::Entry> &getEntries() {
static std::vector<impl::Entry> entries;
std::vector<Entry> &getEntries() {
static std::vector<Entry> entries;
return entries;
}
@ -614,7 +615,7 @@ namespace hex {
namespace ContentRegistry::DataProcessorNode {
void impl::add(const impl::Entry &entry) {
void impl::add(const Entry &entry) {
log::debug("Registered new data processor node type: [{}]: {}", entry.category, entry.name);
getEntries().push_back(entry);
@ -626,8 +627,8 @@ namespace hex {
namespace impl {
std::vector<impl::Entry> &getEntries() {
static std::vector<impl::Entry> nodes;
std::vector<Entry> &getEntries() {
static std::vector<Entry> nodes;
return nodes;
}
@ -757,39 +758,39 @@ namespace hex {
namespace impl {
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems() {
static std::multimap<u32, impl::MainMenuItem> items;
std::multimap<u32, MainMenuItem> &getMainMenuItems() {
static std::multimap<u32, MainMenuItem> items;
return items;
}
std::multimap<u32, impl::MenuItem> &getMenuItems() {
static std::multimap<u32, impl::MenuItem> items;
std::multimap<u32, MenuItem> &getMenuItems() {
static std::multimap<u32, MenuItem> items;
return items;
}
std::vector<impl::DrawCallback> &getWelcomeScreenEntries() {
static std::vector<impl::DrawCallback> entries;
std::vector<DrawCallback> &getWelcomeScreenEntries() {
static std::vector<DrawCallback> entries;
return entries;
}
std::vector<impl::DrawCallback> &getFooterItems() {
static std::vector<impl::DrawCallback> items;
std::vector<DrawCallback> &getFooterItems() {
static std::vector<DrawCallback> items;
return items;
}
std::vector<impl::DrawCallback> &getToolbarItems() {
static std::vector<impl::DrawCallback> items;
std::vector<DrawCallback> &getToolbarItems() {
static std::vector<DrawCallback> items;
return items;
}
std::vector<impl::SidebarItem> &getSidebarItems() {
static std::vector<impl::SidebarItem> items;
std::vector<SidebarItem> &getSidebarItems() {
static std::vector<SidebarItem> items;
return items;
}
std::vector<impl::TitleBarButton> &getTitleBarButtons() {
static std::vector<impl::TitleBarButton> buttons;
std::vector<TitleBarButton> &getTitleBarButtons() {
static std::vector<TitleBarButton> buttons;
return buttons;
}
@ -830,8 +831,8 @@ namespace hex {
namespace impl {
std::vector<impl::Entry> &getEntries() {
static std::vector<impl::Entry> entries;
std::vector<Entry> &getEntries() {
static std::vector<Entry> entries;
return entries;
}
@ -851,8 +852,8 @@ namespace hex {
namespace impl {
std::vector<impl::Entry> &getEntries() {
static std::vector<impl::Entry> entries;
std::vector<Entry> &getEntries() {
static std::vector<Entry> entries;
return entries;
}
@ -882,7 +883,7 @@ namespace hex {
ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *reinterpret_cast<UserData*>(data->UserData);
auto &userData = *static_cast<UserData*>(data->UserData);
if (data->BufTextLen >= userData.maxChars)
userData.editingDone = true;
@ -911,7 +912,7 @@ namespace hex {
ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *reinterpret_cast<UserData*>(data->UserData);
auto &userData = *static_cast<UserData*>(data->UserData);
userData.data->resize(data->BufSize);
@ -1029,4 +1030,55 @@ namespace hex {
}
namespace ContentRegistry::Experiments {
namespace impl {
std::map<std::string, Experiment> &getExperiments() {
static std::map<std::string, Experiment> experiments;
return experiments;
}
}
void addExperiment(const std::string &experimentName, const std::string &unlocalizedName, const std::string &unlocalizedDescription) {
auto &experiments = impl::getExperiments();
if (experiments.contains(experimentName)) {
log::error("Experiment with name '{}' already exists!", experimentName);
return;
}
experiments[experimentName] = impl::Experiment {
.unlocalizedName = unlocalizedName,
.unlocalizedDescription = unlocalizedDescription,
.enabled = false
};
}
void enableExperiement(const std::string &experimentName, bool enabled) {
auto &experiments = impl::getExperiments();
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
return;
}
experiments[experimentName].enabled = enabled;
}
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName) {
auto &experiments = impl::getExperiments();
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
return false;
}
return experiments[experimentName].enabled;
}
}
}

View File

@ -516,6 +516,8 @@
"hex.builtin.provider.motorola_srec": "Motorola SREC Provider",
"hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}",
"hex.builtin.provider.view": "View",
"hex.builtin.setting.experiments": "Experiments",
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
"hex.builtin.setting.folders": "Folders",
"hex.builtin.setting.folders.add_folder": "Add new folder",
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",