mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 05:27:41 -05:00
build: More repo cleanup, move libimhex and external libs to /lib folder
This commit is contained in:
29
lib/libimhex/include/hex.hpp
Normal file
29
lib/libimhex/include/hex.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
constexpr static const auto ImHexApiURL = "https://api.werwolv.net/imhex";
|
||||
constexpr static const auto GitHubApiURL = "https://api.github.com/repos/WerWolv/ImHex";
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
using u128 = __uint128_t;
|
||||
|
||||
using s8 = std::int8_t;
|
||||
using s16 = std::int16_t;
|
||||
using s32 = std::int32_t;
|
||||
using s64 = std::int64_t;
|
||||
using s128 = __int128_t;
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct Region {
|
||||
u64 address;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
296
lib/libimhex/include/hex/api/content_registry.hpp
Normal file
296
lib/libimhex/include/hex/api/content_registry.hpp
Normal file
@@ -0,0 +1,296 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class View;
|
||||
class LanguageDefinition;
|
||||
namespace pl { class Evaluator; }
|
||||
namespace dp { class Node; }
|
||||
namespace prv { class Provider; }
|
||||
|
||||
/*
|
||||
The Content Registry is the heart of all features in ImHex that are in some way extendable by Plugins.
|
||||
It allows you to add/register new content that will be picked up and used by the ImHex core or by other
|
||||
plugins when needed.
|
||||
*/
|
||||
namespace ContentRegistry {
|
||||
|
||||
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
||||
namespace Settings {
|
||||
using Callback = std::function<bool(const std::string&, nlohmann::json&)>;
|
||||
|
||||
struct Entry {
|
||||
std::string name;
|
||||
Callback callback;
|
||||
};
|
||||
|
||||
void load();
|
||||
void store();
|
||||
|
||||
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, s64 defaultValue, const Callback &callback);
|
||||
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue, const Callback &callback);
|
||||
|
||||
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, s64 value);
|
||||
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &value);
|
||||
void write(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string>& value);
|
||||
|
||||
s64 read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, s64 defaultValue);
|
||||
std::string read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::string &defaultValue);
|
||||
std::vector<std::string> read(const std::string &unlocalizedCategory, const std::string &unlocalizedName, const std::vector<std::string>& defaultValue = { });
|
||||
|
||||
std::map<std::string, std::vector<Entry>>& getEntries();
|
||||
nlohmann::json getSetting(const std::string &unlocalizedCategory, const std::string &unlocalizedName);
|
||||
nlohmann::json& getSettingsData();
|
||||
}
|
||||
|
||||
/* Command Palette Command Registry. Allows adding of new commands to the command palette */
|
||||
namespace CommandPaletteCommands {
|
||||
|
||||
enum class Type : u32 {
|
||||
SymbolCommand,
|
||||
KeywordCommand
|
||||
};
|
||||
|
||||
using DisplayCallback = std::function<std::string(std::string)>;
|
||||
using ExecuteCallback = std::function<void(std::string)>;
|
||||
|
||||
struct Entry {
|
||||
Type type;
|
||||
std::string command;
|
||||
std::string unlocalizedDescription;
|
||||
DisplayCallback displayCallback;
|
||||
ExecuteCallback executeCallback;
|
||||
};
|
||||
|
||||
void add(Type type, const std::string &command, const std::string &unlocalizedDescription, const DisplayCallback &displayCallback, const ExecuteCallback &executeCallback = [](auto){});
|
||||
std::vector<Entry>& getEntries();
|
||||
}
|
||||
|
||||
/* Pattern Language Function Registry. Allows adding of new functions that may be used inside the pattern language */
|
||||
namespace PatternLanguage {
|
||||
|
||||
constexpr static u32 UnlimitedParameters = 0xFFFF'FFFF;
|
||||
constexpr static u32 MoreParametersThan = 0x8000'0000;
|
||||
constexpr static u32 LessParametersThan = 0x4000'0000;
|
||||
constexpr static u32 NoParameters = 0x0000'0000;
|
||||
|
||||
using Namespace = std::vector<std::string>;
|
||||
using Callback = std::function<std::optional<hex::pl::Token::Literal>(hex::pl::Evaluator*, const std::vector<hex::pl::Token::Literal>&)>;
|
||||
|
||||
struct Function {
|
||||
u32 parameterCount;
|
||||
Callback func;
|
||||
bool dangerous;
|
||||
};
|
||||
|
||||
void addFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func);
|
||||
void addDangerousFunction(const Namespace &ns, const std::string &name, u32 parameterCount, const Callback &func);
|
||||
std::map<std::string, ContentRegistry::PatternLanguage::Function>& getFunctions();
|
||||
}
|
||||
|
||||
/* View Registry. Allows adding of new windows */
|
||||
namespace Views {
|
||||
|
||||
namespace impl {
|
||||
|
||||
void add(View *view);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<hex::derived_from<View> T, typename ... Args>
|
||||
void add(Args&& ... args) {
|
||||
return impl::add(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
std::vector<View*>& getEntries();
|
||||
|
||||
}
|
||||
|
||||
/* Tools Registry. Allows adding new entries to the tools window */
|
||||
namespace Tools {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<void()>;
|
||||
|
||||
struct Entry {
|
||||
std::string name;
|
||||
Callback function;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void add(const std::string &unlocalizedName, const impl::Callback &function);
|
||||
|
||||
std::vector<impl::Entry>& getEntries();
|
||||
}
|
||||
|
||||
/* Data Inspector Registry. Allows adding of new types to the data inspector */
|
||||
namespace DataInspector {
|
||||
|
||||
enum class NumberDisplayStyle {
|
||||
Decimal,
|
||||
Hexadecimal,
|
||||
Octal
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
using DisplayFunction = std::function<std::string()>;
|
||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8>&, std::endian, NumberDisplayStyle)>;
|
||||
|
||||
struct Entry {
|
||||
std::string unlocalizedName;
|
||||
size_t requiredSize;
|
||||
impl::GeneratorFunction generatorFunction;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void add(const std::string &unlocalizedName, size_t requiredSize, impl::GeneratorFunction function);
|
||||
|
||||
std::vector<impl::Entry>& getEntries();
|
||||
}
|
||||
|
||||
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
|
||||
namespace DataProcessorNode {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using CreatorFunction = std::function<dp::Node*()>;
|
||||
|
||||
struct Entry {
|
||||
std::string category;
|
||||
std::string name;
|
||||
CreatorFunction creatorFunction;
|
||||
};
|
||||
|
||||
void add(const Entry &entry);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<hex::derived_from<dp::Node> T, typename ... Args>
|
||||
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, Args&& ... args) {
|
||||
add(impl::Entry{ unlocalizedCategory.c_str(), unlocalizedName.c_str(),
|
||||
[=]{
|
||||
auto node = new T(std::forward<Args>(args)...);
|
||||
node->setUnlocalizedName(unlocalizedName);
|
||||
return node;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void addSeparator();
|
||||
|
||||
std::vector<impl::Entry>& getEntries();
|
||||
|
||||
}
|
||||
|
||||
/* Language Registry. Allows together with the LangEntry class and the _lang user defined literal to add new languages */
|
||||
namespace Language {
|
||||
void registerLanguage(const std::string &name, const std::string &languageCode);
|
||||
void addLocalizations(const std::string &languageCode, const LanguageDefinition &definition);
|
||||
|
||||
std::map<std::string, std::string>& getLanguages();
|
||||
std::map<std::string, std::vector<LanguageDefinition>>& getLanguageDefinitions();
|
||||
}
|
||||
|
||||
/* Interface Registry. Allows adding new items to various interfaces */
|
||||
namespace Interface {
|
||||
using DrawCallback = std::function<void()>;
|
||||
|
||||
void addWelcomeScreenEntry(const DrawCallback &function);
|
||||
void addFooterItem(const DrawCallback &function);
|
||||
void addToolbarItem(const DrawCallback &function);
|
||||
|
||||
std::vector<DrawCallback>& getWelcomeScreenEntries();
|
||||
std::vector<DrawCallback>& getFooterItems();
|
||||
std::vector<DrawCallback>& getToolbarItems();
|
||||
}
|
||||
|
||||
/* Provider Registry. Allows adding new data providers to be created from the UI */
|
||||
namespace Provider {
|
||||
|
||||
namespace impl {
|
||||
|
||||
void addProviderName(const std::string &unlocalizedName);
|
||||
|
||||
}
|
||||
|
||||
template<hex::derived_from<hex::prv::Provider> T>
|
||||
void add(const std::string &unlocalizedName, bool addToList = true) {
|
||||
(void) EventManager::subscribe<RequestCreateProvider>([expectedName = unlocalizedName](const std::string &name, hex::prv::Provider **provider){
|
||||
if (name != expectedName) return;
|
||||
|
||||
auto newProvider = new T();
|
||||
|
||||
hex::ImHexApi::Provider::add(newProvider);
|
||||
|
||||
if (provider != nullptr)
|
||||
*provider = newProvider;
|
||||
});
|
||||
|
||||
if (addToList)
|
||||
impl::addProviderName(unlocalizedName);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getEntries();
|
||||
|
||||
}
|
||||
|
||||
namespace DataFormatter {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
|
||||
struct Entry {
|
||||
std::string unlocalizedName;
|
||||
Callback callback;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void add(const std::string &unlocalizedName, const impl::Callback &callback);
|
||||
|
||||
std::vector<impl::Entry>& getEntries();
|
||||
|
||||
}
|
||||
|
||||
namespace FileHandler {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<bool(fs::path)>;
|
||||
struct Entry {
|
||||
std::vector<std::string> extensions;
|
||||
Callback callback;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void add(const std::vector<std::string> &extensions, const impl::Callback &callback);
|
||||
|
||||
std::vector<impl::Entry>& getEntries();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
128
lib/libimhex/include/hex/api/event.hpp
Normal file
128
lib/libimhex/include/hex/api/event.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <functional>
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
#define EVENT_DEF(event_name, ...) \
|
||||
struct event_name final : public hex::Event<__VA_ARGS__> { \
|
||||
constexpr static auto id = [] { return hex::EventId(); }(); \
|
||||
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
|
||||
}
|
||||
|
||||
class GLFWwindow;
|
||||
|
||||
namespace hex {
|
||||
|
||||
class EventId {
|
||||
public:
|
||||
explicit constexpr EventId(const char *func = __builtin_FUNCTION(), u32 line = __builtin_LINE()) {
|
||||
this->m_hash = line ^ 123456789;
|
||||
for (auto c : std::string_view(func)) {
|
||||
this->m_hash = (this->m_hash >> 5) | (this->m_hash << 27);
|
||||
this->m_hash ^= c;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool operator ==(const EventId &rhs) const = default;
|
||||
|
||||
private:
|
||||
u32 m_hash;
|
||||
};
|
||||
|
||||
struct EventBase {
|
||||
EventBase() noexcept = default;
|
||||
};
|
||||
|
||||
template<typename ... Params>
|
||||
struct Event : public EventBase {
|
||||
using Callback = std::function<void(Params...)>;
|
||||
|
||||
explicit Event(Callback func) noexcept : m_func(std::move(func)) {}
|
||||
|
||||
void operator()(Params... params) const noexcept {
|
||||
this->m_func(params...);
|
||||
}
|
||||
|
||||
private:
|
||||
Callback m_func;
|
||||
};
|
||||
|
||||
class EventManager {
|
||||
public:
|
||||
using EventList = std::list<std::pair<EventId, EventBase*>>;
|
||||
|
||||
template<typename E>
|
||||
[[nodiscard]] static EventList::iterator subscribe(typename E::Callback function) {
|
||||
return s_events.insert(s_events.end(), std::make_pair(E::id, new E(function)));
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
static void subscribe(void *token, typename E::Callback function) {
|
||||
s_tokenStore.insert(std::make_pair(token, subscribe<E>(function)));
|
||||
}
|
||||
|
||||
static void unsubscribe(EventList::iterator iter) noexcept {
|
||||
s_events.remove(*iter);
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
static void unsubscribe(void *token) noexcept {
|
||||
auto iter = std::find_if(s_tokenStore.begin(), s_tokenStore.end(), [&](auto &item){
|
||||
return item.first == token && item.second->first == E::id;
|
||||
});
|
||||
|
||||
if (iter != s_tokenStore.end()) {
|
||||
s_events.remove(*iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
static void post(auto&& ... args) noexcept {
|
||||
for (const auto &[id, event] : s_events) {
|
||||
if (id == E::id)
|
||||
(*reinterpret_cast<E *>(event))(std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static std::map<void*, EventList::iterator> s_tokenStore;
|
||||
static EventList s_events;
|
||||
};
|
||||
|
||||
namespace pl { class PatternData; }
|
||||
|
||||
/* Default Events */
|
||||
EVENT_DEF(EventFileLoaded, fs::path);
|
||||
EVENT_DEF(EventFileUnloaded);
|
||||
EVENT_DEF(EventDataChanged);
|
||||
EVENT_DEF(EventPatternChanged, std::vector<pl::PatternData*>&);
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow*);
|
||||
EVENT_DEF(EventRegionSelected, Region);
|
||||
EVENT_DEF(EventProjectFileStore);
|
||||
EVENT_DEF(EventProjectFileLoad);
|
||||
EVENT_DEF(EventSettingsChanged);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider*);
|
||||
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
EVENT_DEF(RequestSelectionChange, Region);
|
||||
EVENT_DEF(RequestAddBookmark, ImHexApi::Bookmarks::Entry);
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestChangeWindowTitle, std::string);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestOpenFile, fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, u32);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestCreateProvider, std::string, hex::prv::Provider **);
|
||||
|
||||
EVENT_DEF(QuerySelection, Region&);
|
||||
|
||||
}
|
||||
67
lib/libimhex/include/hex/api/imhex_api.hpp
Normal file
67
lib/libimhex/include/hex/api/imhex_api.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/api/task.hpp>
|
||||
#include <hex/api/keybinding.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
namespace ImHexApi {
|
||||
namespace Common {
|
||||
|
||||
void closeImHex(bool noQuestions = false);
|
||||
void restartImHex();
|
||||
|
||||
};
|
||||
|
||||
namespace Bookmarks {
|
||||
struct Entry {
|
||||
Region region;
|
||||
|
||||
std::vector<char> name;
|
||||
std::vector<char> comment;
|
||||
u32 color;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
void add(Region region, const std::string &name, const std::string &comment, u32 color = 0x00000000);
|
||||
void add(u64 addr, size_t size, const std::string &name, const std::string &comment, u32 color = 0x00000000);
|
||||
|
||||
std::list<Entry>& getEntries();
|
||||
};
|
||||
|
||||
namespace Provider {
|
||||
|
||||
prv::Provider* get();
|
||||
const std::vector<prv::Provider*>& getProviders();
|
||||
|
||||
bool isValid();
|
||||
|
||||
void add(prv::Provider *provider);
|
||||
|
||||
template<hex::derived_from<prv::Provider> T>
|
||||
void add(auto&& ... args) {
|
||||
add(new T(std::forward<decltype(args)>(args)...));
|
||||
}
|
||||
|
||||
void remove(prv::Provider *provider);
|
||||
|
||||
};
|
||||
|
||||
namespace Tasks {
|
||||
|
||||
Task createTask(const std::string &unlocalizedName, u64 maxValue);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
190
lib/libimhex/include/hex/api/keybinding.hpp
Normal file
190
lib/libimhex/include/hex/api/keybinding.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
struct ImGuiWindow;
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct View;
|
||||
|
||||
enum class Keys {
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
|
||||
|
||||
class Key {
|
||||
public:
|
||||
constexpr Key(Keys key) :m_key(static_cast<u32>(key)) { }
|
||||
|
||||
auto operator<=>(const Key&) const = default;
|
||||
|
||||
private:
|
||||
u32 m_key;
|
||||
};
|
||||
|
||||
class Shortcut {
|
||||
public:
|
||||
|
||||
Shortcut operator+(const Key &other) const {
|
||||
Shortcut result = *this;
|
||||
result.m_keys.insert(other);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Shortcut& operator+=(const Key &other) {
|
||||
this->m_keys.insert(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator<(const Shortcut &other) const {
|
||||
return this->m_keys < other.m_keys;
|
||||
}
|
||||
|
||||
bool operator==(const Shortcut &other) const {
|
||||
return this->m_keys == other.m_keys;
|
||||
}
|
||||
private:
|
||||
friend Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||
|
||||
std::set<Key> m_keys;
|
||||
};
|
||||
|
||||
inline Shortcut operator+(const Key &lhs, const Key &rhs) {
|
||||
Shortcut result;
|
||||
result.m_keys = { lhs, rhs };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static constexpr auto CTRL = Key(static_cast<Keys>(0x1000'0000));
|
||||
static constexpr auto ALT = Key(static_cast<Keys>(0x2000'0000));
|
||||
static constexpr auto SHIFT = Key(static_cast<Keys>(0x3000'0000));
|
||||
static constexpr auto SUPER = Key(static_cast<Keys>(0x4000'0000));
|
||||
|
||||
class ShortcutManager {
|
||||
public:
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const std::function<void()> &callback);
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const std::function<void()> &callback);
|
||||
static void process(View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode);
|
||||
};
|
||||
|
||||
}
|
||||
32
lib/libimhex/include/hex/api/task.hpp
Normal file
32
lib/libimhex/include/hex/api/task.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class Task {
|
||||
public:
|
||||
Task(const std::string& unlocalizedName, u64 maxValue);
|
||||
~Task();
|
||||
|
||||
void setMaxValue(u64 maxValue);
|
||||
void update(u64 currValue);
|
||||
void finish();
|
||||
|
||||
[[nodiscard]]
|
||||
double getProgress() const;
|
||||
|
||||
[[nodiscard]]
|
||||
const std::string& getName() const;
|
||||
|
||||
[[nodiscard]]
|
||||
bool isPending() const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
u64 m_maxValue, m_currValue;
|
||||
};
|
||||
|
||||
}
|
||||
57
lib/libimhex/include/hex/data_processor/attribute.hpp
Normal file
57
lib/libimhex/include/hex/data_processor/attribute.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
class Node;
|
||||
|
||||
class Attribute {
|
||||
public:
|
||||
enum class Type {
|
||||
Integer,
|
||||
Float,
|
||||
Buffer
|
||||
};
|
||||
|
||||
enum class IOType {
|
||||
In, Out
|
||||
};
|
||||
|
||||
Attribute(IOType ioType, Type type, std::string unlocalizedName);
|
||||
~Attribute();
|
||||
|
||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||
void setID(u32 id) { this->m_id = id; }
|
||||
|
||||
[[nodiscard]] IOType getIOType() const { return this->m_ioType; }
|
||||
[[nodiscard]] Type getType() const { return this->m_type; }
|
||||
[[nodiscard]] const std::string& getUnlocalizedName() const { return this->m_unlocalizedName; }
|
||||
|
||||
void addConnectedAttribute(u32 linkId, Attribute *to) { this->m_connectedAttributes.insert({ linkId, to }); }
|
||||
void removeConnectedAttribute(u32 linkId) { this->m_connectedAttributes.erase(linkId); }
|
||||
[[nodiscard]] std::map<u32, Attribute*>& getConnectedAttributes() { return this->m_connectedAttributes; }
|
||||
|
||||
[[nodiscard]] Node* getParentNode() { return this->m_parentNode; }
|
||||
|
||||
[[nodiscard]] std::optional<std::vector<u8>>& getOutputData() { return this->m_outputData; }
|
||||
private:
|
||||
u32 m_id;
|
||||
IOType m_ioType;
|
||||
Type m_type;
|
||||
std::string m_unlocalizedName;
|
||||
std::map<u32, Attribute*> m_connectedAttributes;
|
||||
Node *m_parentNode = nullptr;
|
||||
|
||||
std::optional<std::vector<u8>> m_outputData;
|
||||
|
||||
friend class Node;
|
||||
void setParentNode(Node *node) { this->m_parentNode = node; }
|
||||
};
|
||||
|
||||
}
|
||||
22
lib/libimhex/include/hex/data_processor/link.hpp
Normal file
22
lib/libimhex/include/hex/data_processor/link.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
class Link {
|
||||
public:
|
||||
Link(u32 from, u32 to);
|
||||
|
||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||
void setID(u32 id) { this->m_id = id; }
|
||||
|
||||
[[nodiscard]] u32 getFromID() const { return this->m_from; }
|
||||
[[nodiscard]] u32 getToID() const { return this->m_to; }
|
||||
|
||||
private:
|
||||
u32 m_id;
|
||||
u32 m_from, m_to;
|
||||
};
|
||||
|
||||
}
|
||||
95
lib/libimhex/include/hex/data_processor/node.hpp
Normal file
95
lib/libimhex/include/hex/data_processor/node.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/data_processor/attribute.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace hex::prv { class Provider; class Overlay; }
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
class Node {
|
||||
public:
|
||||
Node(std::string unlocalizedTitle, std::vector<Attribute> attributes);
|
||||
|
||||
virtual ~Node() = default;
|
||||
|
||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||
void setID(u32 id) { this->m_id = id; }
|
||||
|
||||
[[nodiscard]] const std::string& getUnlocalizedName() const { return this->m_unlocalizedName; }
|
||||
void setUnlocalizedName(const std::string &unlocalizedName) { this->m_unlocalizedName = unlocalizedName; }
|
||||
|
||||
[[nodiscard]] const std::string& getUnlocalizedTitle() const { return this->m_unlocalizedTitle; }
|
||||
[[nodiscard]] std::vector<Attribute>& getAttributes() { return this->m_attributes; }
|
||||
|
||||
void setCurrentOverlay(prv::Overlay *overlay) {
|
||||
this->m_overlay = overlay;
|
||||
}
|
||||
|
||||
virtual void drawNode() { }
|
||||
virtual void process() = 0;
|
||||
|
||||
virtual void store(nlohmann::json &j) { }
|
||||
virtual void load(nlohmann::json &j) { }
|
||||
|
||||
using NodeError = std::pair<Node*, std::string>;
|
||||
|
||||
void resetOutputData() {
|
||||
for (auto &attribute : this->m_attributes)
|
||||
attribute.getOutputData().reset();
|
||||
}
|
||||
|
||||
void resetProcessedInputs() {
|
||||
this->m_processedInputs.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_id;
|
||||
std::string m_unlocalizedTitle, m_unlocalizedName;
|
||||
std::vector<Attribute> m_attributes;
|
||||
std::set<u32> m_processedInputs;
|
||||
prv::Overlay *m_overlay = nullptr;
|
||||
|
||||
Attribute* getConnectedInputAttribute(u32 index) {
|
||||
if (index >= this->getAttributes().size())
|
||||
throw std::runtime_error("Attribute index out of bounds!");
|
||||
|
||||
auto &connectedAttribute = this->getAttributes()[index].getConnectedAttributes();
|
||||
|
||||
if (connectedAttribute.empty())
|
||||
return nullptr;
|
||||
|
||||
return connectedAttribute.begin()->second;
|
||||
}
|
||||
|
||||
void markInputProcessed(u32 index) {
|
||||
const auto &[iter, inserted] = this->m_processedInputs.insert(index);
|
||||
if (!inserted)
|
||||
throwNodeError("Recursion detected!");
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
[[noreturn]] void throwNodeError(const std::string &message) {
|
||||
throw NodeError(this, message);
|
||||
}
|
||||
|
||||
std::vector<u8> getBufferOnInput(u32 index);
|
||||
u64 getIntegerOnInput(u32 index);
|
||||
float getFloatOnInput(u32 index);
|
||||
|
||||
void setBufferOnOutput(u32 index, std::vector<u8> data);
|
||||
void setIntegerOnOutput(u32 index, u64 integer);
|
||||
void setFloatOnOutput(u32 index, float floatingPoint);
|
||||
|
||||
void setOverlayData(u64 address, const std::vector<u8> &data);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
162
lib/libimhex/include/hex/helpers/concepts.hpp
Normal file
162
lib/libimhex/include/hex/helpers/concepts.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename>
|
||||
struct is_integral_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<s8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<s16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<s32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<s64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<u128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<s128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<bool> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char8_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char16_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<char32_t> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_integral_helper<wchar_t> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_integral : public is_integral_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
|
||||
template<typename>
|
||||
struct is_signed_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<s8> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<s16> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<s32> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<s64> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<s128> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<char> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<float> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<double> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_signed_helper<long double> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_signed : public is_signed_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
|
||||
template<typename>
|
||||
struct is_floating_point_helper : public std::false_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<float> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<double> : public std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_floating_point_helper<long double> : public std::true_type { };
|
||||
|
||||
template<typename T>
|
||||
struct is_floating_point : public is_floating_point_helper<std::remove_cvref_t<T>>::type { };
|
||||
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 12000
|
||||
#if __has_include(<concepts>)
|
||||
// Make sure we break when derived_from is implemented in libc++. Then we can fix a compatibility version above
|
||||
#include <concepts>
|
||||
#endif
|
||||
// libcxx 12 still doesn't have many default concepts implemented, as a result we need to define it ourself using clang built-ins.
|
||||
// [concept.derived] (patch from https://reviews.llvm.org/D74292)
|
||||
namespace hex {
|
||||
template<class _Dp, class _Bp>
|
||||
concept derived_from =
|
||||
__is_base_of(_Bp, _Dp) && __is_convertible_to(const volatile _Dp*, const volatile _Bp*);
|
||||
}
|
||||
|
||||
#else
|
||||
// Assume supported
|
||||
#include <concepts>
|
||||
namespace hex {
|
||||
using std::derived_from;
|
||||
}
|
||||
#endif
|
||||
|
||||
// [concepts.arithmetic]
|
||||
namespace hex {
|
||||
|
||||
template<class T>
|
||||
concept integral = hex::is_integral<T>::value;
|
||||
|
||||
template<class T>
|
||||
concept signed_integral = integral<T> && hex::is_signed<T>::value;
|
||||
|
||||
template<class T>
|
||||
concept unsigned_integral = integral<T> && !signed_integral<T>;
|
||||
|
||||
template<class T>
|
||||
concept floating_point = std::is_floating_point<T>::value;
|
||||
|
||||
}
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename T>
|
||||
struct always_false : std::false_type {};
|
||||
|
||||
template<typename T, size_t Size>
|
||||
concept has_size = sizeof(T) == Size;
|
||||
|
||||
}
|
||||
|
||||
58
lib/libimhex/include/hex/helpers/crypto.hpp
Normal file
58
lib/libimhex/include/hex/helpers/crypto.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
namespace hex::crypt {
|
||||
|
||||
void initialize();
|
||||
void exit();
|
||||
|
||||
u16 crc8(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut);
|
||||
u16 crc16(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut);
|
||||
u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init, u32 xorout, bool reflectIn, bool reflectOut);
|
||||
|
||||
std::array<u8, 16> md5(prv::Provider* &data, u64 offset, size_t size);
|
||||
std::array<u8, 20> sha1(prv::Provider* &data, u64 offset, size_t size);
|
||||
std::array<u8, 28> sha224(prv::Provider* &data, u64 offset, size_t size);
|
||||
std::array<u8, 32> sha256(prv::Provider* &data, u64 offset, size_t size);
|
||||
std::array<u8, 48> sha384(prv::Provider* &data, u64 offset, size_t size);
|
||||
std::array<u8, 64> sha512(prv::Provider* &data, u64 offset, size_t size);
|
||||
|
||||
std::array<u8, 16> md5(const std::vector<u8> &data);
|
||||
std::array<u8, 20> sha1(const std::vector<u8> &data);
|
||||
std::array<u8, 28> sha224(const std::vector<u8> &data);
|
||||
std::array<u8, 32> sha256(const std::vector<u8> &data);
|
||||
std::array<u8, 48> sha384(const std::vector<u8> &data);
|
||||
std::array<u8, 64> sha512(const std::vector<u8> &data);
|
||||
|
||||
std::vector<u8> decode64(const std::vector<u8> &input);
|
||||
std::vector<u8> encode64(const std::vector<u8> &input);
|
||||
std::vector<u8> decode16(const std::string &input);
|
||||
std::string encode16(const std::vector<u8> &input);
|
||||
|
||||
enum class AESMode : u8 {
|
||||
ECB = 0,
|
||||
CBC = 1,
|
||||
CFB128 = 2,
|
||||
CTR = 3,
|
||||
GCM = 4,
|
||||
CCM = 5,
|
||||
OFB = 6,
|
||||
XTS = 7
|
||||
};
|
||||
|
||||
enum class KeyLength : u8 {
|
||||
Key128Bits = 0,
|
||||
Key192Bits = 1,
|
||||
Key256Bits = 2
|
||||
};
|
||||
|
||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
||||
}
|
||||
62
lib/libimhex/include/hex/helpers/disassembler.hpp
Normal file
62
lib/libimhex/include/hex/helpers/disassembler.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#if __has_include(<capstone/capstone.h>)
|
||||
#include <capstone/capstone.h>
|
||||
#else
|
||||
#include <capstone.h>
|
||||
#endif
|
||||
#include <hex.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
enum class Architecture : s32 {
|
||||
ARM,
|
||||
ARM64,
|
||||
MIPS,
|
||||
X86,
|
||||
PPC,
|
||||
SPARC,
|
||||
SYSZ,
|
||||
XCORE,
|
||||
M68K,
|
||||
TMS320C64X,
|
||||
M680X,
|
||||
EVM,
|
||||
MOS65XX,
|
||||
WASM,
|
||||
BPF,
|
||||
RISCV,
|
||||
|
||||
MAX,
|
||||
MIN = ARM
|
||||
};
|
||||
|
||||
class Disassembler {
|
||||
public:
|
||||
static constexpr cs_arch toCapstoneArchictecture(Architecture architecture) {
|
||||
return static_cast<cs_arch>(architecture);
|
||||
}
|
||||
|
||||
static inline bool isSupported(Architecture architecture) {
|
||||
return cs_support(toCapstoneArchictecture(architecture));
|
||||
}
|
||||
|
||||
constexpr static const char * const ArchitectureNames[] = { "ARM32", "ARM64", "MIPS", "x86", "PowerPC", "Sparc", "SystemZ", "XCore", "68K", "TMS320C64x", "680X", "Ethereum", "MOS65XX", "WebAssembly", "Berkeley Packet Filter", "RISC-V" };
|
||||
|
||||
static inline s32 getArchitectureSupportedCount() {
|
||||
static s32 supportedCount = -1;
|
||||
|
||||
if (supportedCount != -1) {
|
||||
return supportedCount;
|
||||
}
|
||||
|
||||
for (supportedCount = static_cast<s32>(Architecture::MIN); supportedCount < static_cast<s32>(Architecture::MAX); supportedCount++) {
|
||||
if (!cs_support(supportedCount)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return supportedCount;
|
||||
}
|
||||
};
|
||||
}
|
||||
36
lib/libimhex/include/hex/helpers/encoding_file.hpp
Normal file
36
lib/libimhex/include/hex/helpers/encoding_file.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class EncodingFile {
|
||||
public:
|
||||
enum class Type {
|
||||
Thingy
|
||||
};
|
||||
|
||||
EncodingFile() = default;
|
||||
EncodingFile(Type type, const fs::path &path);
|
||||
|
||||
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(const std::vector<u8> &buffer) const;
|
||||
[[nodiscard]] size_t getLongestSequence() const { return this->m_longestSequence; }
|
||||
|
||||
[[nodiscard]] bool valid() const { return this->m_valid; }
|
||||
|
||||
private:
|
||||
void parseThingyFile(std::ifstream &content);
|
||||
|
||||
bool m_valid = false;
|
||||
|
||||
std::map<u32, std::map<std::vector<u8>, std::string>> m_mapping;
|
||||
size_t m_longestSequence = 0;
|
||||
};
|
||||
|
||||
}
|
||||
63
lib/libimhex/include/hex/helpers/file.hpp
Normal file
63
lib/libimhex/include/hex/helpers/file.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
#define off64_t off_t
|
||||
#define fopen64 fopen
|
||||
#define fseeko64 fseek
|
||||
#define ftello64 ftell
|
||||
#define ftruncate64 ftruncate
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
class File {
|
||||
public:
|
||||
enum class Mode {
|
||||
Read,
|
||||
Write,
|
||||
Create
|
||||
};
|
||||
|
||||
explicit File(const fs::path &path, Mode mode);
|
||||
File();
|
||||
File(const File&) = delete;
|
||||
File(File &&other) noexcept;
|
||||
|
||||
~File();
|
||||
|
||||
[[nodiscard]] bool isValid() const { return this->m_file != nullptr; }
|
||||
|
||||
void seek(u64 offset);
|
||||
void close();
|
||||
|
||||
size_t readBuffer(u8 *buffer, size_t size);
|
||||
std::vector<u8> readBytes(size_t numBytes = 0);
|
||||
std::string readString(size_t numBytes = 0);
|
||||
|
||||
void write(const u8 *buffer, size_t size);
|
||||
void write(const std::vector<u8> &bytes);
|
||||
void write(const std::string &string);
|
||||
|
||||
[[nodiscard]] size_t getSize() const;
|
||||
void setSize(u64 size);
|
||||
|
||||
void flush();
|
||||
void remove();
|
||||
|
||||
auto getHandle() { return this->m_file; }
|
||||
const fs::path& getPath() { return this->m_path; }
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
fs::path m_path;
|
||||
};
|
||||
|
||||
}
|
||||
19
lib/libimhex/include/hex/helpers/fmt.hpp
Normal file
19
lib/libimhex/include/hex/helpers/fmt.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename ... Args>
|
||||
inline std::string format(std::string_view format, Args ... args) {
|
||||
return fmt::format(fmt::runtime(format), args...);
|
||||
}
|
||||
|
||||
template<typename ... Args>
|
||||
inline void print(std::string_view format, Args ... args) {
|
||||
fmt::print(fmt::runtime(format), args...);
|
||||
}
|
||||
|
||||
}
|
||||
57
lib/libimhex/include/hex/helpers/lang.hpp
Normal file
57
lib/libimhex/include/hex/helpers/lang.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class LanguageDefinition {
|
||||
public:
|
||||
LanguageDefinition(std::initializer_list<std::pair<std::string, std::string>> entries);
|
||||
|
||||
const std::map<std::string, std::string>& getEntries() const;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> m_entries;
|
||||
};
|
||||
|
||||
class LangEntry {
|
||||
public:
|
||||
explicit LangEntry(const char *unlocalizedString);
|
||||
explicit LangEntry(const std::string &unlocalizedString);
|
||||
explicit LangEntry(std::string_view unlocalizedString);
|
||||
|
||||
operator std::string() const;
|
||||
operator std::string_view() const;
|
||||
operator const char*() const;
|
||||
|
||||
[[nodiscard]] std::string_view get() const;
|
||||
|
||||
static void loadLanguage(std::string_view language);
|
||||
static const std::map<std::string, std::string>& getSupportedLanguages();
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedString;
|
||||
};
|
||||
|
||||
std::string operator+(const std::string &&left, const LangEntry &&right);
|
||||
std::string operator+(const LangEntry &&left, const std::string &&right);
|
||||
std::string operator+(const std::string_view &&left, const LangEntry &&right);
|
||||
std::string operator+(const LangEntry &&left, const std::string_view &&right);
|
||||
std::string operator+(const char *left, const LangEntry &&right);
|
||||
std::string operator+(const LangEntry &&left, const char *right);
|
||||
std::string operator+(const LangEntry &&left, const LangEntry &&right);
|
||||
|
||||
namespace lang_literals {
|
||||
|
||||
inline LangEntry operator""_lang(const char *string, size_t) {
|
||||
return LangEntry(string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
23
lib/libimhex/include/hex/helpers/literals.hpp
Normal file
23
lib/libimhex/include/hex/helpers/literals.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
namespace hex::literals {
|
||||
|
||||
/* Byte literals */
|
||||
|
||||
constexpr static inline unsigned long long operator ""_Bytes(unsigned long long bytes) noexcept {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
constexpr static inline unsigned long long operator ""_KiB(unsigned long long kiB) noexcept {
|
||||
return operator ""_Bytes(kiB * 1024);
|
||||
}
|
||||
|
||||
constexpr static inline unsigned long long operator ""_MiB(unsigned long long MiB) noexcept {
|
||||
return operator ""_KiB(MiB * 1024);
|
||||
}
|
||||
|
||||
constexpr static inline unsigned long long operator ""_GiB(unsigned long long GiB) noexcept {
|
||||
return operator ""_MiB(GiB * 1024);
|
||||
}
|
||||
|
||||
}
|
||||
35
lib/libimhex/include/hex/helpers/loader_script_handler.hpp
Normal file
35
lib/libimhex/include/hex/helpers/loader_script_handler.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
struct _object;
|
||||
typedef struct _object PyObject;
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
class LoaderScript {
|
||||
public:
|
||||
LoaderScript() = delete;
|
||||
|
||||
static bool processFile(const fs::path &scriptPath);
|
||||
|
||||
static void setFilePath(const fs::path &filePath) { LoaderScript::s_filePath = filePath; }
|
||||
static void setDataProvider(prv::Provider* provider) { LoaderScript::s_dataProvider = provider; }
|
||||
private:
|
||||
static inline fs::path s_filePath;
|
||||
static inline prv::Provider* s_dataProvider;
|
||||
|
||||
static PyObject* Py_getFilePath(PyObject *self, PyObject *args);
|
||||
static PyObject* Py_addPatch(PyObject *self, PyObject *args);
|
||||
static PyObject* Py_addBookmark(PyObject *self, PyObject *args);
|
||||
|
||||
static PyObject* Py_addStruct(PyObject *self, PyObject *args);
|
||||
static PyObject* Py_addUnion(PyObject *self, PyObject *args);
|
||||
};
|
||||
|
||||
}
|
||||
40
lib/libimhex/include/hex/helpers/logger.hpp
Normal file
40
lib/libimhex/include/hex/helpers/logger.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/color.h>
|
||||
|
||||
namespace hex::log {
|
||||
|
||||
void debug(const std::string &fmt, auto ... args) {
|
||||
#if defined(DEBUG)
|
||||
fmt::print(fg(fmt::color::green_yellow) | fmt::emphasis::bold, "[DEBUG] ");
|
||||
fmt::print(fmt::runtime(fmt), args...);
|
||||
fmt::print("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void info(const std::string &fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::cadet_blue) | fmt::emphasis::bold, "[INFO] ");
|
||||
fmt::print(fmt::runtime(fmt), args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void warn(const std::string &fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::orange) | fmt::emphasis::bold, "[WARN] ");
|
||||
fmt::print(fmt::runtime(fmt), args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void error(const std::string &fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::red) | fmt::emphasis::bold, "[ERROR] ");
|
||||
fmt::print(fmt::runtime(fmt), args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void fatal(const std::string &fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::purple) | fmt::emphasis::bold, "[FATAL] ");
|
||||
fmt::print(fmt::runtime(fmt), args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
}
|
||||
22
lib/libimhex/include/hex/helpers/magic.hpp
Normal file
22
lib/libimhex/include/hex/helpers/magic.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/literals.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
namespace hex::magic {
|
||||
|
||||
using namespace hex::literals;
|
||||
|
||||
bool compile();
|
||||
std::string getDescription(const std::vector<u8> &data);
|
||||
std::string getDescription(prv::Provider *provider, size_t size = 5_MiB);
|
||||
std::string getMIMEType(const std::vector<u8> &data);
|
||||
std::string getMIMEType(prv::Provider *provider, size_t size = 5_MiB);
|
||||
|
||||
}
|
||||
66
lib/libimhex/include/hex/helpers/net.hpp
Normal file
66
lib/libimhex/include/hex/helpers/net.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <future>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <atomic>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <curl/system.h>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
using CURL = void;
|
||||
struct curl_slist;
|
||||
|
||||
namespace hex {
|
||||
|
||||
template<typename T>
|
||||
struct Response {
|
||||
s32 code;
|
||||
T body;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Response<void> {
|
||||
s32 code;
|
||||
};
|
||||
|
||||
class Net {
|
||||
public:
|
||||
Net();
|
||||
~Net();
|
||||
|
||||
std::future<Response<std::string>> getString(const std::string &url, u32 timeout = 2000);
|
||||
std::future<Response<nlohmann::json>> getJson(const std::string &url, u32 timeout = 2000);
|
||||
|
||||
std::future<Response<std::string>> uploadFile(const std::string &url, const fs::path &filePath, u32 timeout = 2000);
|
||||
std::future<Response<void>> downloadFile(const std::string &url, const fs::path &filePath, u32 timeout = 2000);
|
||||
|
||||
[[nodiscard]]
|
||||
std::string encode(const std::string &input);
|
||||
|
||||
[[nodiscard]]
|
||||
float getProgress() const { return this->m_progress; }
|
||||
|
||||
void cancel() { this->m_shouldCancel = true; }
|
||||
|
||||
private:
|
||||
void setCommonSettings(std::string &response, const std::string &url, u32 timeout = 2000, const std::map<std::string, std::string> &extraHeaders = { }, const std::string &body = { });
|
||||
std::optional<s32> execute();
|
||||
|
||||
friend int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
||||
private:
|
||||
CURL *m_ctx;
|
||||
curl_slist *m_headers = nullptr;
|
||||
|
||||
std::mutex m_transmissionActive;
|
||||
float m_progress = 0.0F;
|
||||
bool m_shouldCancel = false;
|
||||
};
|
||||
|
||||
}
|
||||
17
lib/libimhex/include/hex/helpers/patches.hpp
Normal file
17
lib/libimhex/include/hex/helpers/patches.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
|
||||
using Patches = std::map<u64, u8>;
|
||||
|
||||
std::vector<u8> generateIPSPatch(const Patches &patches);
|
||||
std::vector<u8> generateIPS32Patch(const Patches &patches);
|
||||
|
||||
Patches loadIPSPatch(const std::vector<u8> &ipsPatch);
|
||||
Patches loadIPS32Patch(const std::vector<u8> &ipsPatch);
|
||||
}
|
||||
27
lib/libimhex/include/hex/helpers/paths.hpp
Normal file
27
lib/libimhex/include/hex/helpers/paths.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
enum class ImHexPath {
|
||||
Patterns,
|
||||
PatternsInclude,
|
||||
Magic,
|
||||
Python,
|
||||
Plugins,
|
||||
Yara,
|
||||
Config,
|
||||
Resources,
|
||||
Constants
|
||||
};
|
||||
|
||||
std::string getExecutablePath();
|
||||
|
||||
std::vector<fs::path> getPath(ImHexPath path, bool listNonExisting = false);
|
||||
|
||||
}
|
||||
10
lib/libimhex/include/hex/helpers/paths_mac.h
Normal file
10
lib/libimhex/include/hex/helpers/paths_mac.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
namespace hex {
|
||||
std::string getMacExecutableDirectoryPath();
|
||||
std::string getMacApplicationSupportDirectoryPath();
|
||||
}
|
||||
#endif
|
||||
105
lib/libimhex/include/hex/helpers/project_file_handler.hpp
Normal file
105
lib/libimhex/include/hex/helpers/project_file_handler.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "patches.hpp"
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class ProjectFile {
|
||||
public:
|
||||
ProjectFile() = delete;
|
||||
|
||||
static bool load(const fs::path &filePath);
|
||||
static bool store(fs::path filePath = { });
|
||||
|
||||
[[nodiscard]] static bool hasUnsavedChanges() {
|
||||
return ProjectFile::s_hasUnsavedChanged;
|
||||
}
|
||||
|
||||
static void markDirty() {
|
||||
bool setWindowTitle = !hasUnsavedChanges();
|
||||
|
||||
ProjectFile::s_hasUnsavedChanged = true;
|
||||
|
||||
if (setWindowTitle)
|
||||
EventManager::post<RequestChangeWindowTitle>(fs::path(getFilePath()).filename().string());
|
||||
}
|
||||
|
||||
[[nodiscard]] static const fs::path& getProjectFilePath() {
|
||||
return ProjectFile::s_currProjectFilePath;
|
||||
}
|
||||
|
||||
static void clearProjectFilePath() {
|
||||
ProjectFile::s_currProjectFilePath.clear();
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const fs::path& getFilePath() {
|
||||
return ProjectFile::s_filePath;
|
||||
}
|
||||
|
||||
static void setFilePath(const fs::path &filePath) {
|
||||
ProjectFile::s_filePath = filePath;
|
||||
|
||||
EventManager::post<RequestChangeWindowTitle>(filePath.filename().string());
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const std::string& getPattern() {
|
||||
return ProjectFile::s_pattern;
|
||||
}
|
||||
|
||||
static void setPattern(const std::string &pattern) {
|
||||
markDirty();
|
||||
ProjectFile::s_pattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const Patches& getPatches() {
|
||||
return ProjectFile::s_patches;
|
||||
}
|
||||
|
||||
static void setPatches(const Patches &patches) {
|
||||
markDirty();
|
||||
ProjectFile::s_patches = patches;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const std::list<ImHexApi::Bookmarks::Entry>& getBookmarks() {
|
||||
return ProjectFile::s_bookmarks;
|
||||
}
|
||||
|
||||
static void setBookmarks(const std::list<ImHexApi::Bookmarks::Entry> &bookmarks) {
|
||||
markDirty();
|
||||
ProjectFile::s_bookmarks = bookmarks;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const std::string& getDataProcessorContent() {
|
||||
return ProjectFile::s_dataProcessorContent;
|
||||
}
|
||||
|
||||
static void setDataProcessorContent(const std::string &json) {
|
||||
markDirty();
|
||||
ProjectFile::s_dataProcessorContent = json;
|
||||
}
|
||||
|
||||
private:
|
||||
static fs::path s_currProjectFilePath;
|
||||
static bool s_hasUnsavedChanged;
|
||||
|
||||
static fs::path s_filePath;
|
||||
static std::string s_pattern;
|
||||
static Patches s_patches;
|
||||
static std::list<ImHexApi::Bookmarks::Entry> s_bookmarks;
|
||||
static std::string s_dataProcessorContent;
|
||||
};
|
||||
|
||||
}
|
||||
115
lib/libimhex/include/hex/helpers/shared_data.hpp
Normal file
115
lib/libimhex/include/hex/helpers/shared_data.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/task.hpp>
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace hex { class SharedData; }
|
||||
|
||||
namespace hex::plugin::internal {
|
||||
void initializePlugin(SharedData &sharedData);
|
||||
}
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
namespace dp { class Node; }
|
||||
namespace pl { class PatternData; }
|
||||
|
||||
class View;
|
||||
|
||||
class SharedData {
|
||||
SharedData() = default;
|
||||
public:
|
||||
SharedData(const SharedData&) = delete;
|
||||
SharedData(SharedData&&) = delete;
|
||||
|
||||
friend class Window;
|
||||
|
||||
template<typename T>
|
||||
static T& getVariable(std::string variableName) {
|
||||
return std::any_cast<T&>(SharedData::sharedVariables[variableName]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void setVariable(std::string variableName, T value) {
|
||||
SharedData::sharedVariables[variableName] = value;
|
||||
}
|
||||
|
||||
static void clearVariables() {
|
||||
SharedData::sharedVariables.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
static std::vector<std::function<void()>> deferredCalls;
|
||||
|
||||
static std::vector<prv::Provider*> providers;
|
||||
static u32 currentProvider;
|
||||
|
||||
static std::map<std::string, std::vector<ContentRegistry::Settings::Entry>> settingsEntries;
|
||||
static nlohmann::json settingsJson;
|
||||
static std::vector<ContentRegistry::CommandPaletteCommands::Entry> commandPaletteCommands;
|
||||
static std::map<std::string, ContentRegistry::PatternLanguage::Function> patternLanguageFunctions;
|
||||
static std::vector<View*> views;
|
||||
static std::vector<ContentRegistry::Tools::impl::Entry> toolsEntries;
|
||||
static std::vector<ContentRegistry::DataInspector::impl::Entry> dataInspectorEntries;
|
||||
static u32 patternPaletteOffset;
|
||||
static std::string popupMessage;
|
||||
static std::list<ImHexApi::Bookmarks::Entry> bookmarkEntries;
|
||||
static std::vector<pl::PatternData*> patternData;
|
||||
|
||||
static std::map<std::string, std::string> languageNames;
|
||||
static std::map<std::string, std::vector<LanguageDefinition>> languageDefinitions;
|
||||
static std::map<std::string, std::string> loadedLanguageStrings;
|
||||
|
||||
static std::vector<ContentRegistry::Interface::DrawCallback> welcomeScreenEntries;
|
||||
static std::vector<ContentRegistry::Interface::DrawCallback> footerItems;
|
||||
static std::vector<ContentRegistry::Interface::DrawCallback> toolbarItems;
|
||||
|
||||
static std::map<Shortcut, std::function<void()>> globalShortcuts;
|
||||
|
||||
static std::mutex tasksMutex;
|
||||
static std::list<Task*> runningTasks;
|
||||
|
||||
static std::vector<std::string> providerNames;
|
||||
|
||||
static std::vector<ContentRegistry::DataProcessorNode::impl::Entry> dataProcessorNodes;
|
||||
static u32 dataProcessorNodeIdCounter;
|
||||
static u32 dataProcessorLinkIdCounter;
|
||||
static u32 dataProcessorAttrIdCounter;
|
||||
|
||||
static std::vector<ContentRegistry::DataFormatter::impl::Entry> dataFormatters;
|
||||
static std::vector<ContentRegistry::FileHandler::impl::Entry> fileHandlers;
|
||||
|
||||
static std::list<fs::path> recentFilePaths;
|
||||
|
||||
static int mainArgc;
|
||||
static char **mainArgv;
|
||||
static char **mainEnvp;
|
||||
|
||||
static ImFontAtlas *fontAtlas;
|
||||
static ImFontConfig fontConfig;
|
||||
static ImVec2 windowPos;
|
||||
static ImVec2 windowSize;
|
||||
|
||||
static float globalScale;
|
||||
static float fontScale;
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::any> sharedVariables;
|
||||
};
|
||||
|
||||
}
|
||||
55
lib/libimhex/include/hex/helpers/socket.hpp
Normal file
55
lib/libimhex/include/hex/helpers/socket.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define SOCKET_NONE INVALID_SOCKET
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define SOCKET_NONE -1
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
Socket() = default;
|
||||
Socket(const Socket&) = delete;
|
||||
Socket(Socket &&other);
|
||||
|
||||
Socket(const std::string &address, u16 port);
|
||||
~Socket();
|
||||
|
||||
void connect(const std::string &address, u16 port);
|
||||
void disconnect();
|
||||
|
||||
[[nodiscard]]
|
||||
bool isConnected() const;
|
||||
|
||||
std::string readString(size_t size = 0x1000) const;
|
||||
std::vector<u8> readBytes(size_t size = 0x1000) const;
|
||||
|
||||
void writeString(const std::string &string) const;
|
||||
void writeBytes(const std::vector<u8> &bytes) const;
|
||||
|
||||
private:
|
||||
bool m_connected = false;
|
||||
#if defined(OS_WINDOWS)
|
||||
SOCKET m_socket = SOCKET_NONE;
|
||||
#else
|
||||
int m_socket = SOCKET_NONE;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
329
lib/libimhex/include/hex/helpers/utils.hpp
Normal file
329
lib/libimhex/include/hex/helpers/utils.hpp
Normal file
@@ -0,0 +1,329 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <nfd.hpp>
|
||||
|
||||
#define TOKEN_CONCAT_IMPL(x, y) x ## y
|
||||
#define TOKEN_CONCAT(x, y) TOKEN_CONCAT_IMPL(x, y)
|
||||
#define ANONYMOUS_VARIABLE(prefix) TOKEN_CONCAT(prefix, __COUNTER__)
|
||||
|
||||
struct ImVec2;
|
||||
|
||||
namespace hex {
|
||||
|
||||
long double operator""_scaled(long double value);
|
||||
long double operator""_scaled(unsigned long long value);
|
||||
ImVec2 scaled(const ImVec2 &vector);
|
||||
|
||||
std::string to_string(u128 value);
|
||||
std::string to_string(s128 value);
|
||||
|
||||
std::string toByteString(u64 bytes);
|
||||
std::string makePrintable(u8 c);
|
||||
|
||||
void runCommand(const std::string &command);
|
||||
void openWebpage(std::string url);
|
||||
|
||||
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const hex::unsigned_integral auto &value) {
|
||||
using ValueType = std::remove_cvref_t<decltype(value)>;
|
||||
ValueType mask = (std::numeric_limits<ValueType>::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to;
|
||||
|
||||
return (value & mask) >> to;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u64 extract(u32 from, u32 to, const std::vector<u8> &bytes) {
|
||||
u8 index = 0;
|
||||
while(from > 32 && to > 32) {
|
||||
if (from - 8 < 0 || to - 8 < 0)
|
||||
return 0;
|
||||
|
||||
from -= 8;
|
||||
to -= 8;
|
||||
index++;
|
||||
}
|
||||
|
||||
u64 value = 0;
|
||||
std::memcpy(&value, &bytes[index], std::min(sizeof(value), bytes.size() - index));
|
||||
u64 mask = (std::numeric_limits<u64>::max() >> (64 - (from + 1)));
|
||||
|
||||
return (value & mask) >> to;
|
||||
}
|
||||
|
||||
constexpr inline s128 signExtend(size_t numBits, s128 value) {
|
||||
s128 mask = 1U << (numBits - 1);
|
||||
return (value ^ mask) - mask;
|
||||
}
|
||||
|
||||
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
template<size_t Size>
|
||||
struct SizeTypeImpl { };
|
||||
|
||||
template<> struct SizeTypeImpl<1> { using Type = u8; };
|
||||
template<> struct SizeTypeImpl<2> { using Type = u16; };
|
||||
template<> struct SizeTypeImpl<4> { using Type = u32; };
|
||||
template<> struct SizeTypeImpl<8> { using Type = u64; };
|
||||
template<> struct SizeTypeImpl<16> { using Type = u128; };
|
||||
|
||||
template<size_t Size>
|
||||
using SizeType = typename SizeTypeImpl<Size>::Type;
|
||||
|
||||
template<typename T>
|
||||
constexpr T changeEndianess(const T &value, std::endian endian) {
|
||||
if (endian == std::endian::native)
|
||||
return value;
|
||||
|
||||
constexpr auto Size = sizeof(T);
|
||||
|
||||
SizeType<Size> unswapped;
|
||||
std::memcpy(&unswapped, &value, Size);
|
||||
|
||||
SizeType<Size> swapped;
|
||||
|
||||
if constexpr (!std::has_single_bit(Size) || Size > 16)
|
||||
static_assert(always_false<T>::value, "Invalid type provided!");
|
||||
|
||||
switch (Size) {
|
||||
case 1: swapped = unswapped; break;
|
||||
case 2: swapped = __builtin_bswap16(unswapped); break;
|
||||
case 4: swapped = __builtin_bswap32(unswapped); break;
|
||||
case 8: swapped = __builtin_bswap64(unswapped); break;
|
||||
case 16: swapped = (u128(__builtin_bswap64(unswapped & 0xFFFF'FFFF'FFFF'FFFF)) << 64) | __builtin_bswap64(u128(unswapped) >> 64); break;
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
|
||||
T result;
|
||||
std::memcpy(&result, &swapped, Size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr u128 bitmask(u8 bits) {
|
||||
return u128(-1) >> (128 - bits);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T changeEndianess(T value, size_t size, std::endian endian) {
|
||||
if (endian == std::endian::native)
|
||||
return value;
|
||||
|
||||
u128 unswapped = 0;
|
||||
std::memcpy(&unswapped, &value, size);
|
||||
|
||||
u128 swapped;
|
||||
|
||||
switch (size) {
|
||||
case 1: swapped = unswapped; break;
|
||||
case 2: swapped = __builtin_bswap16(unswapped); break;
|
||||
case 4: swapped = __builtin_bswap32(unswapped); break;
|
||||
case 8: swapped = __builtin_bswap64(unswapped); break;
|
||||
case 16: swapped = (u128(__builtin_bswap64(unswapped & 0xFFFF'FFFF'FFFF'FFFF)) << 64) | __builtin_bswap64(u128(unswapped) >> 64); break;
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
|
||||
T result = 0;
|
||||
std::memcpy(&result, &swapped, size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
constexpr T bit_width(T x) noexcept {
|
||||
return std::numeric_limits<T>::digits - std::countl_zero(x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T bit_ceil(T x) noexcept {
|
||||
if (x <= 1u)
|
||||
return T(1);
|
||||
|
||||
return T(1) << bit_width(T(x - 1));
|
||||
}
|
||||
|
||||
std::vector<std::string> splitString(const std::string &string, const std::string &delimiter);
|
||||
std::string combineStrings(const std::vector<std::string> &strings, const std::string &delimiter = "");
|
||||
|
||||
std::string toEngineeringString(double value);
|
||||
|
||||
template<typename T>
|
||||
std::vector<u8> toBytes(T value) {
|
||||
std::vector<u8> bytes(sizeof(T));
|
||||
std::memcpy(bytes.data(), &value, sizeof(T));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
inline std::vector<u8> parseByteString(const std::string &string) {
|
||||
auto byteString = std::string(string);
|
||||
byteString.erase(std::remove(byteString.begin(), byteString.end(), ' '), byteString.end());
|
||||
|
||||
if ((byteString.length() % 2) != 0) return { };
|
||||
|
||||
std::vector<u8> result;
|
||||
for (u32 i = 0; i < byteString.length(); i += 2) {
|
||||
if (!std::isxdigit(byteString[i]) || !std::isxdigit(byteString[i + 1]))
|
||||
return { };
|
||||
|
||||
result.push_back(std::strtoul(byteString.substr(i, 2).c_str(), nullptr, 16));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::string toBinaryString(hex::unsigned_integral auto number) {
|
||||
if (number == 0) return "0";
|
||||
|
||||
std::string result;
|
||||
for (s16 bit = hex::bit_width(number) - 1; bit >= 0; bit--)
|
||||
result += (number & (0b1 << bit)) == 0 ? '0' : '1';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void trimLeft(std::string &s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch) && ch >= 0x20;
|
||||
}));
|
||||
}
|
||||
|
||||
inline void trimRight(std::string &s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch) && ch >= 0x20;
|
||||
}).base(), s.end());
|
||||
}
|
||||
|
||||
inline void trim(std::string &s) {
|
||||
trimLeft(s);
|
||||
trimRight(s);
|
||||
}
|
||||
|
||||
enum class DialogMode {
|
||||
Open,
|
||||
Save,
|
||||
Folder
|
||||
};
|
||||
|
||||
void openFileBrowser(const std::string &title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(fs::path)> &callback, const std::string &defaultPath = {});
|
||||
|
||||
float float16ToFloat32(u16 float16);
|
||||
|
||||
inline bool equalsIgnoreCase(const std::string &left, const std::string &right) {
|
||||
return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) {
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
inline bool containsIgnoreCase(const std::string &a, const std::string &b) {
|
||||
auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) {
|
||||
return std::toupper(ch1) == std::toupper(ch2);
|
||||
});
|
||||
|
||||
return iter != a.end();
|
||||
}
|
||||
|
||||
template<typename T, typename ... VariantTypes>
|
||||
T get_or(const std::variant<VariantTypes...> &variant, T alt) {
|
||||
const T *value = std::get_if<T>(&variant);
|
||||
if (value == nullptr)
|
||||
return alt;
|
||||
else
|
||||
return *value;
|
||||
}
|
||||
|
||||
bool isProcessElevated();
|
||||
|
||||
namespace scope_guard {
|
||||
|
||||
#define SCOPE_GUARD ::hex::scope_guard::ScopeGuardOnExit() + [&]()
|
||||
#define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_) = SCOPE_GUARD
|
||||
|
||||
template<class F>
|
||||
class ScopeGuard {
|
||||
private:
|
||||
F m_func;
|
||||
bool m_active;
|
||||
public:
|
||||
constexpr ScopeGuard(F func) : m_func(std::move(func)), m_active(true) { }
|
||||
~ScopeGuard() { if (this->m_active) { this->m_func(); } }
|
||||
void release() { this->m_active = false; }
|
||||
|
||||
ScopeGuard(ScopeGuard &&other) noexcept : m_func(std::move(other.m_func)), m_active(other.m_active) {
|
||||
other.cancel();
|
||||
}
|
||||
|
||||
ScopeGuard& operator=(ScopeGuard &&) = delete;
|
||||
};
|
||||
|
||||
enum class ScopeGuardOnExit { };
|
||||
|
||||
template <typename F>
|
||||
constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
|
||||
return ScopeGuard<F>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace first_time_exec {
|
||||
|
||||
#define FIRST_TIME static auto ANONYMOUS_VARIABLE(FIRST_TIME_) = ::hex::first_time_exec::FirstTimeExecutor() + [&]()
|
||||
|
||||
template<class F>
|
||||
class FirstTimeExecute {
|
||||
public:
|
||||
constexpr FirstTimeExecute(F func) { func(); }
|
||||
|
||||
FirstTimeExecute& operator=(FirstTimeExecute &&) = delete;
|
||||
};
|
||||
|
||||
enum class FirstTimeExecutor { };
|
||||
|
||||
template <typename F>
|
||||
constexpr FirstTimeExecute<F> operator+(FirstTimeExecutor, F&& f) {
|
||||
return FirstTimeExecute<F>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace final_cleanup {
|
||||
|
||||
#define FINAL_CLEANUP static auto ANONYMOUS_VARIABLE(ON_EXIT_) = ::hex::final_cleanup::FinalCleanupExecutor() + [&]()
|
||||
|
||||
template<class F>
|
||||
class FinalCleanupExecute {
|
||||
F m_func;
|
||||
public:
|
||||
constexpr FinalCleanupExecute(F func) : m_func(func) { }
|
||||
constexpr ~FinalCleanupExecute() { this->m_func(); }
|
||||
|
||||
FinalCleanupExecute& operator=(FinalCleanupExecute &&) = delete;
|
||||
};
|
||||
|
||||
enum class FinalCleanupExecutor { };
|
||||
|
||||
template <typename F>
|
||||
constexpr FinalCleanupExecute<F> operator+(FinalCleanupExecutor, F&& f) {
|
||||
return FinalCleanupExecute<F>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
2328
lib/libimhex/include/hex/pattern_language/ast_node.hpp
Normal file
2328
lib/libimhex/include/hex/pattern_language/ast_node.hpp
Normal file
File diff suppressed because it is too large
Load Diff
263
lib/libimhex/include/hex/pattern_language/evaluator.hpp
Normal file
263
lib/libimhex/include/hex/pattern_language/evaluator.hpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/pattern_language/log_console.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
enum class DangerousFunctionPermission {
|
||||
Ask,
|
||||
Deny,
|
||||
Allow
|
||||
};
|
||||
|
||||
enum class ControlFlowStatement {
|
||||
None,
|
||||
Continue,
|
||||
Break,
|
||||
Return
|
||||
};
|
||||
|
||||
class PatternData;
|
||||
class PatternCreationLimiter;
|
||||
class ASTNode;
|
||||
|
||||
class Evaluator {
|
||||
public:
|
||||
Evaluator() = default;
|
||||
|
||||
std::optional<std::vector<PatternData*>> evaluate(const std::vector<ASTNode*> &ast);
|
||||
|
||||
[[nodiscard]]
|
||||
LogConsole& getConsole() {
|
||||
return this->m_console;
|
||||
}
|
||||
|
||||
struct Scope { PatternData *parent; std::vector<PatternData*>* scope; };
|
||||
void pushScope(PatternData *parent, std::vector<PatternData*> &scope) {
|
||||
if (this->m_scopes.size() > this->getEvaluationDepth())
|
||||
LogConsole::abortEvaluation(hex::format("evaluation depth exceeded set limit of {}", this->getEvaluationDepth()));
|
||||
|
||||
this->handleAbort();
|
||||
|
||||
this->m_scopes.push_back({ parent, &scope });
|
||||
}
|
||||
|
||||
void popScope() {
|
||||
this->m_scopes.pop_back();
|
||||
}
|
||||
|
||||
const Scope& getScope(s32 index) {
|
||||
return this->m_scopes[this->m_scopes.size() - 1 + index];
|
||||
}
|
||||
|
||||
const Scope& getGlobalScope() {
|
||||
return this->m_scopes.front();
|
||||
}
|
||||
|
||||
size_t getScopeCount() {
|
||||
return this->m_scopes.size();
|
||||
}
|
||||
|
||||
bool isGlobalScope() {
|
||||
return this->m_scopes.size() == 1;
|
||||
}
|
||||
|
||||
void setProvider(prv::Provider *provider) {
|
||||
this->m_provider = provider;
|
||||
}
|
||||
|
||||
void setInVariables(const std::map<std::string, Token::Literal> &inVariables) {
|
||||
this->m_inVariables = inVariables;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::map<std::string, Token::Literal> getOutVariables() const {
|
||||
std::map<std::string, Token::Literal> result;
|
||||
|
||||
for (const auto &[name, offset] : this->m_outVariables) {
|
||||
result.insert({ name, this->getStack()[offset] });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
prv::Provider *getProvider() const {
|
||||
return this->m_provider;
|
||||
}
|
||||
|
||||
void setDefaultEndian(std::endian endian) {
|
||||
this->m_defaultEndian = endian;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::endian getDefaultEndian() const {
|
||||
return this->m_defaultEndian;
|
||||
}
|
||||
|
||||
void setEvaluationDepth(u64 evalDepth) {
|
||||
this->m_evalDepth = evalDepth;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getEvaluationDepth() const {
|
||||
return this->m_evalDepth;
|
||||
}
|
||||
|
||||
void setArrayLimit(u64 arrayLimit) {
|
||||
this->m_arrayLimit = arrayLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getArrayLimit() const {
|
||||
return this->m_arrayLimit;
|
||||
}
|
||||
|
||||
void setPatternLimit(u64 limit) {
|
||||
this->m_patternLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getPatternLimit() {
|
||||
return this->m_patternLimit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getPatternCount() {
|
||||
return this->m_currPatternCount;
|
||||
}
|
||||
|
||||
void setLoopLimit(u64 limit) {
|
||||
this->m_loopLimit = limit;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
u64 getLoopLimit() {
|
||||
return this->m_loopLimit;
|
||||
}
|
||||
|
||||
u64& dataOffset() { return this->m_currOffset; }
|
||||
|
||||
bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguage::Callback &function) {
|
||||
const auto [iter, inserted] = this->m_customFunctions.insert({ name, { numParams, function } });
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const std::map<std::string, ContentRegistry::PatternLanguage::Function>& getCustomFunctions() const {
|
||||
return this->m_customFunctions;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::vector<Token::Literal>& getStack() {
|
||||
return this->m_stack;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const std::vector<Token::Literal>& getStack() const {
|
||||
return this->m_stack;
|
||||
}
|
||||
|
||||
void createVariable(const std::string &name, ASTNode *type, const std::optional<Token::Literal> &value = std::nullopt, bool outVariable = false);
|
||||
void setVariable(const std::string &name, const Token::Literal& value);
|
||||
|
||||
void abort() {
|
||||
this->m_aborted = true;
|
||||
}
|
||||
|
||||
void handleAbort() {
|
||||
if (this->m_aborted)
|
||||
LogConsole::abortEvaluation("evaluation aborted by user");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<Token::Literal> getEnvVariable(const std::string &name) const {
|
||||
if (this->m_envVariables.contains(name))
|
||||
return this->m_envVariables.at(name);
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void setEnvVariable(const std::string &name, const Token::Literal &value) {
|
||||
this->m_envVariables[name] = value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool hasDangerousFunctionBeenCalled() const {
|
||||
return this->m_dangerousFunctionCalled;
|
||||
}
|
||||
|
||||
void dangerousFunctionCalled() {
|
||||
this->m_dangerousFunctionCalled = true;
|
||||
}
|
||||
|
||||
void allowDangerousFunctions(bool allow) {
|
||||
this->m_allowDangerousFunctions = allow ? DangerousFunctionPermission::Allow : DangerousFunctionPermission::Deny;
|
||||
this->m_dangerousFunctionCalled = false;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
DangerousFunctionPermission getDangerousFunctionPermission() const {
|
||||
return this->m_allowDangerousFunctions;
|
||||
}
|
||||
|
||||
void setCurrentControlFlowStatement(ControlFlowStatement statement) {
|
||||
this->m_currControlFlowStatement = statement;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ControlFlowStatement getCurrentControlFlowStatement() const {
|
||||
return this->m_currControlFlowStatement;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void patternCreated();
|
||||
void patternDestroyed();
|
||||
|
||||
private:
|
||||
u64 m_currOffset;
|
||||
prv::Provider *m_provider = nullptr;
|
||||
LogConsole m_console;
|
||||
|
||||
std::endian m_defaultEndian = std::endian::native;
|
||||
u64 m_evalDepth;
|
||||
u64 m_arrayLimit;
|
||||
u64 m_patternLimit;
|
||||
u64 m_loopLimit;
|
||||
|
||||
u64 m_currPatternCount;
|
||||
|
||||
std::atomic<bool> m_aborted;
|
||||
|
||||
std::vector<Scope> m_scopes;
|
||||
std::map<std::string, ContentRegistry::PatternLanguage::Function> m_customFunctions;
|
||||
std::vector<ASTNode*> m_customFunctionDefinitions;
|
||||
std::vector<Token::Literal> m_stack;
|
||||
|
||||
std::map<std::string, Token::Literal> m_envVariables;
|
||||
std::map<std::string, Token::Literal> m_inVariables;
|
||||
std::map<std::string, size_t> m_outVariables;
|
||||
|
||||
std::atomic<bool> m_dangerousFunctionCalled = false;
|
||||
std::atomic<DangerousFunctionPermission> m_allowDangerousFunctions = DangerousFunctionPermission::Ask;
|
||||
ControlFlowStatement m_currControlFlowStatement;
|
||||
|
||||
friend class PatternCreationLimiter;
|
||||
};
|
||||
|
||||
}
|
||||
30
lib/libimhex/include/hex/pattern_language/lexer.hpp
Normal file
30
lib/libimhex/include/hex/pattern_language/lexer.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class Lexer {
|
||||
public:
|
||||
using LexerError = std::pair<u32, std::string>;
|
||||
|
||||
Lexer() = default;
|
||||
|
||||
std::optional<std::vector<Token>> lex(const std::string& code);
|
||||
const std::optional<LexerError>& getError() { return this->m_error; }
|
||||
|
||||
private:
|
||||
std::optional<LexerError> m_error;
|
||||
|
||||
[[noreturn]] void throwLexerError(const std::string &error, u32 lineNumber) const {
|
||||
throw LexerError(lineNumber, "Lexer: " + error);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
49
lib/libimhex/include/hex/pattern_language/log_console.hpp
Normal file
49
lib/libimhex/include/hex/pattern_language/log_console.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class ASTNode;
|
||||
|
||||
class LogConsole {
|
||||
public:
|
||||
enum Level {
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
const auto& getLog() const { return this->m_consoleLog; }
|
||||
|
||||
using EvaluateError = std::pair<u32, std::string>;
|
||||
|
||||
void log(Level level, const std::string &message);
|
||||
|
||||
[[noreturn]]
|
||||
static void abortEvaluation(const std::string &message);
|
||||
|
||||
[[noreturn]]
|
||||
static void abortEvaluation(const std::string &message, const ASTNode *node);
|
||||
|
||||
void clear();
|
||||
|
||||
void setHardError(const EvaluateError &error) { this->m_lastHardError = error; }
|
||||
|
||||
[[nodiscard]]
|
||||
const std::optional<EvaluateError>& getLastHardError() { return this->m_lastHardError; };
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Level, std::string>> m_consoleLog;
|
||||
std::optional<EvaluateError> m_lastHardError;
|
||||
};
|
||||
|
||||
}
|
||||
254
lib/libimhex/include/hex/pattern_language/parser.hpp
Normal file
254
lib/libimhex/include/hex/pattern_language/parser.hpp
Normal file
@@ -0,0 +1,254 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
#include <hex/pattern_language/ast_node.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
using TokenIter = std::vector<Token>::const_iterator;
|
||||
using ParseError = std::pair<u32, std::string>;
|
||||
|
||||
Parser() = default;
|
||||
~Parser() = default;
|
||||
|
||||
std::optional<std::vector<ASTNode*>> parse(const std::vector<Token> &tokens);
|
||||
const std::optional<ParseError>& getError() { return this->m_error; }
|
||||
|
||||
private:
|
||||
std::optional<ParseError> m_error;
|
||||
TokenIter m_curr;
|
||||
TokenIter m_originalPosition;
|
||||
|
||||
std::unordered_map<std::string, ASTNode*> m_types;
|
||||
std::vector<TokenIter> m_matchedOptionals;
|
||||
std::vector<std::vector<std::string>> m_currNamespace;
|
||||
|
||||
u32 getLineNumber(s32 index) const {
|
||||
return this->m_curr[index].lineNumber;
|
||||
}
|
||||
|
||||
auto* create(auto *node) {
|
||||
node->setLineNumber(this->getLineNumber(-1));
|
||||
return node;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& getValue(s32 index) const {
|
||||
auto value = std::get_if<T>(&this->m_curr[index].value);
|
||||
|
||||
if (value == nullptr)
|
||||
throwParseError("failed to decode token. Invalid type.", getLineNumber(index));
|
||||
|
||||
return *value;
|
||||
}
|
||||
|
||||
Token::Type getType(s32 index) const {
|
||||
return this->m_curr[index].type;
|
||||
}
|
||||
|
||||
std::string getNamespacePrefixedName(const std::string &name) {
|
||||
std::string result;
|
||||
for (const auto &part : this->m_currNamespace.back()) {
|
||||
result += part + "::";
|
||||
}
|
||||
|
||||
result += name;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ASTNode* parseFunctionCall();
|
||||
ASTNode* parseStringLiteral();
|
||||
std::string parseNamespaceResolution();
|
||||
ASTNode* parseScopeResolution();
|
||||
ASTNode* parseRValue(ASTNodeRValue::Path &path);
|
||||
ASTNode* parseFactor();
|
||||
ASTNode* parseCastExpression();
|
||||
ASTNode* parseUnaryExpression();
|
||||
ASTNode* parseMultiplicativeExpression();
|
||||
ASTNode* parseAdditiveExpression();
|
||||
ASTNode* parseShiftExpression();
|
||||
ASTNode* parseRelationExpression();
|
||||
ASTNode* parseEqualityExpression();
|
||||
ASTNode* parseBinaryAndExpression();
|
||||
ASTNode* parseBinaryXorExpression();
|
||||
ASTNode* parseBinaryOrExpression();
|
||||
ASTNode* parseBooleanAnd();
|
||||
ASTNode* parseBooleanXor();
|
||||
ASTNode* parseBooleanOr();
|
||||
ASTNode* parseTernaryConditional();
|
||||
ASTNode* parseMathematicalExpression();
|
||||
|
||||
ASTNode* parseFunctionDefinition();
|
||||
ASTNode* parseFunctionVariableDecl();
|
||||
ASTNode* parseFunctionStatement();
|
||||
ASTNode* parseFunctionVariableAssignment();
|
||||
ASTNode* parseFunctionControlFlowStatement();
|
||||
std::vector<ASTNode*> parseStatementBody();
|
||||
ASTNode* parseFunctionConditional();
|
||||
ASTNode* parseFunctionWhileLoop();
|
||||
ASTNode* parseFunctionForLoop();
|
||||
|
||||
void parseAttribute(Attributable *currNode);
|
||||
ASTNode* parseConditional();
|
||||
ASTNode* parseWhileStatement();
|
||||
ASTNodeTypeDecl* parseType(bool allowFunctionTypes = false);
|
||||
ASTNode* parseUsingDeclaration();
|
||||
ASTNode* parsePadding();
|
||||
ASTNode* parseMemberVariable(ASTNodeTypeDecl *type);
|
||||
ASTNode* parseMemberArrayVariable(ASTNodeTypeDecl *type);
|
||||
ASTNode* parseMemberPointerVariable(ASTNodeTypeDecl *type);
|
||||
ASTNode* parseMember();
|
||||
ASTNode* parseStruct();
|
||||
ASTNode* parseUnion();
|
||||
ASTNode* parseEnum();
|
||||
ASTNode* parseBitfield();
|
||||
ASTNode* parseVariablePlacement(ASTNodeTypeDecl *type);
|
||||
ASTNode* parseArrayVariablePlacement(ASTNodeTypeDecl *type);
|
||||
ASTNode* parsePointerVariablePlacement(ASTNodeTypeDecl *type);
|
||||
ASTNode* parsePlacement();
|
||||
std::vector<ASTNode*> parseNamespace();
|
||||
std::vector<ASTNode*> parseStatements();
|
||||
|
||||
ASTNodeTypeDecl* addType(const std::string &name, ASTNode *node, std::optional<std::endian> endian = std::nullopt);
|
||||
|
||||
std::vector<ASTNode*> parseTillToken(Token::Type endTokenType, const auto value) {
|
||||
std::vector<ASTNode*> program;
|
||||
auto guard = SCOPE_GUARD {
|
||||
for (auto &node : program)
|
||||
delete node;
|
||||
};
|
||||
|
||||
while (this->m_curr->type != endTokenType || (*this->m_curr) != value) {
|
||||
for (auto statement : parseStatements())
|
||||
program.push_back(statement);
|
||||
}
|
||||
|
||||
this->m_curr++;
|
||||
|
||||
guard.release();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
[[noreturn]] void throwParseError(const std::string &error, s32 token = -1) const {
|
||||
throw ParseError(this->m_curr[token].lineNumber, "Parser: " + error);
|
||||
}
|
||||
|
||||
/* Token consuming */
|
||||
|
||||
enum class Setting{ };
|
||||
constexpr static auto Normal = static_cast<Setting>(0);
|
||||
constexpr static auto Not = static_cast<Setting>(1);
|
||||
|
||||
bool begin() {
|
||||
this->m_originalPosition = this->m_curr;
|
||||
this->m_matchedOptionals.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
this->m_curr = this->m_originalPosition;
|
||||
}
|
||||
|
||||
template<Setting S = Normal>
|
||||
bool sequence() {
|
||||
if constexpr (S == Normal)
|
||||
return true;
|
||||
else if constexpr (S == Not)
|
||||
return false;
|
||||
else
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
template<Setting S = Normal>
|
||||
bool sequence(Token::Type type, auto value, auto ... args) {
|
||||
if constexpr (S == Normal) {
|
||||
if (!peek(type, value)) {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_curr++;
|
||||
|
||||
if (!sequence<Normal>(args...)) {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if constexpr (S == Not) {
|
||||
if (!peek(type, value))
|
||||
return true;
|
||||
|
||||
this->m_curr++;
|
||||
|
||||
if (!sequence<Normal>(args...))
|
||||
return true;
|
||||
|
||||
reset();
|
||||
return false;
|
||||
} else
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
template<Setting S = Normal>
|
||||
bool oneOf() {
|
||||
if constexpr (S == Normal)
|
||||
return false;
|
||||
else if constexpr (S == Not)
|
||||
return true;
|
||||
else
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
template<Setting S = Normal>
|
||||
bool oneOf(Token::Type type, auto value, auto ... args) {
|
||||
if constexpr (S == Normal)
|
||||
return sequence<Normal>(type, value) || oneOf(args...);
|
||||
else if constexpr (S == Not)
|
||||
return sequence<Not>(type, value) && oneOf(args...);
|
||||
else
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
bool variant(Token::Type type1, auto value1, Token::Type type2, auto value2) {
|
||||
if (!peek(type1, value1)) {
|
||||
if (!peek(type2, value2)) {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_curr++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool optional(Token::Type type, auto value) {
|
||||
if (peek(type, value)) {
|
||||
this->m_matchedOptionals.push_back(this->m_curr);
|
||||
this->m_curr++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peek(Token::Type type, auto value, s32 index = 0) {
|
||||
return this->m_curr[index].type == type && this->m_curr[index] == value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
1580
lib/libimhex/include/hex/pattern_language/pattern_data.hpp
Normal file
1580
lib/libimhex/include/hex/pattern_language/pattern_data.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <bit>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/pattern_language/log_console.hpp>
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class Preprocessor;
|
||||
class Lexer;
|
||||
class Parser;
|
||||
class Validator;
|
||||
class Evaluator;
|
||||
class PatternData;
|
||||
|
||||
class ASTNode;
|
||||
|
||||
class PatternLanguage {
|
||||
public:
|
||||
PatternLanguage();
|
||||
~PatternLanguage();
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<std::vector<ASTNode*>> parseString(const std::string &code);
|
||||
[[nodiscard]]
|
||||
std::optional<std::vector<PatternData*>> executeString(prv::Provider *provider, const std::string &string, const std::map<std::string, Token::Literal> &envVars = { }, const std::map<std::string, Token::Literal> &inVariables = { });
|
||||
[[nodiscard]]
|
||||
std::optional<std::vector<PatternData*>> executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars = { }, const std::map<std::string, Token::Literal> &inVariables = { });
|
||||
[[nodiscard]]
|
||||
const std::vector<ASTNode*>& getCurrentAST() const;
|
||||
|
||||
void abort();
|
||||
|
||||
[[nodiscard]]
|
||||
const std::vector<std::pair<LogConsole::Level, std::string>>& getConsoleLog();
|
||||
[[nodiscard]]
|
||||
const std::optional<std::pair<u32, std::string>>& getError();
|
||||
[[nodiscard]]
|
||||
std::map<std::string, Token::Literal> getOutVariables() const;
|
||||
|
||||
[[nodiscard]]
|
||||
u32 getCreatedPatternCount();
|
||||
[[nodiscard]]
|
||||
u32 getMaximumPatternCount();
|
||||
|
||||
[[nodiscard]]
|
||||
bool hasDangerousFunctionBeenCalled() const;
|
||||
void allowDangerousFunctions(bool allow);
|
||||
|
||||
private:
|
||||
Preprocessor *m_preprocessor;
|
||||
Lexer *m_lexer;
|
||||
Parser *m_parser;
|
||||
Validator *m_validator;
|
||||
Evaluator *m_evaluator;
|
||||
|
||||
std::vector<ASTNode*> m_currAST;
|
||||
|
||||
std::optional<std::pair<u32, std::string>> m_currError;
|
||||
};
|
||||
|
||||
}
|
||||
40
lib/libimhex/include/hex/pattern_language/preprocessor.hpp
Normal file
40
lib/libimhex/include/hex/pattern_language/preprocessor.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class Preprocessor {
|
||||
public:
|
||||
Preprocessor();
|
||||
|
||||
std::optional<std::string> preprocess(const std::string& code, bool initialRun = true);
|
||||
|
||||
void addPragmaHandler(const std::string &pragmaType, const std::function<bool(const std::string&)> &function);
|
||||
void addDefaultPragmaHandlers();
|
||||
|
||||
const std::pair<u32, std::string>& getError() { return this->m_error; }
|
||||
|
||||
private:
|
||||
using PreprocessorError = std::pair<u32, std::string>;
|
||||
|
||||
[[noreturn]] void throwPreprocessorError(const std::string &error, u32 lineNumber) const {
|
||||
throw PreprocessorError(lineNumber, "Preprocessor: " + error);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::function<bool(std::string)>> m_pragmaHandlers;
|
||||
|
||||
std::set<std::tuple<std::string, std::string, u32>> m_defines;
|
||||
std::set<std::tuple<std::string, std::string, u32>> m_pragmas;
|
||||
|
||||
std::pair<u32, std::string> m_error;
|
||||
};
|
||||
|
||||
}
|
||||
348
lib/libimhex/include/hex/pattern_language/token.hpp
Normal file
348
lib/libimhex/include/hex/pattern_language/token.hpp
Normal file
@@ -0,0 +1,348 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class PatternData;
|
||||
|
||||
class Token {
|
||||
public:
|
||||
enum class Type : u64 {
|
||||
Keyword,
|
||||
ValueType,
|
||||
Operator,
|
||||
Integer,
|
||||
String,
|
||||
Identifier,
|
||||
Separator
|
||||
};
|
||||
|
||||
enum class Keyword {
|
||||
Struct,
|
||||
Union,
|
||||
Using,
|
||||
Enum,
|
||||
Bitfield,
|
||||
LittleEndian,
|
||||
BigEndian,
|
||||
If,
|
||||
Else,
|
||||
Parent,
|
||||
This,
|
||||
While,
|
||||
For,
|
||||
Function,
|
||||
Return,
|
||||
Namespace,
|
||||
In,
|
||||
Out,
|
||||
Break,
|
||||
Continue
|
||||
};
|
||||
|
||||
enum class Operator {
|
||||
AtDeclaration,
|
||||
Assignment,
|
||||
Inherit,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
Percent,
|
||||
ShiftLeft,
|
||||
ShiftRight,
|
||||
BitOr,
|
||||
BitAnd,
|
||||
BitXor,
|
||||
BitNot,
|
||||
BoolEquals,
|
||||
BoolNotEquals,
|
||||
BoolGreaterThan,
|
||||
BoolLessThan,
|
||||
BoolGreaterThanOrEquals,
|
||||
BoolLessThanOrEquals,
|
||||
BoolAnd,
|
||||
BoolOr,
|
||||
BoolXor,
|
||||
BoolNot,
|
||||
TernaryConditional,
|
||||
Dollar,
|
||||
AddressOf,
|
||||
SizeOf,
|
||||
ScopeResolution
|
||||
};
|
||||
|
||||
enum class ValueType {
|
||||
Unsigned8Bit = 0x10,
|
||||
Signed8Bit = 0x11,
|
||||
Unsigned16Bit = 0x20,
|
||||
Signed16Bit = 0x21,
|
||||
Unsigned32Bit = 0x40,
|
||||
Signed32Bit = 0x41,
|
||||
Unsigned64Bit = 0x80,
|
||||
Signed64Bit = 0x81,
|
||||
Unsigned128Bit = 0x100,
|
||||
Signed128Bit = 0x101,
|
||||
Character = 0x13,
|
||||
Character16 = 0x23,
|
||||
Boolean = 0x14,
|
||||
Float = 0x42,
|
||||
Double = 0x82,
|
||||
String = 0x15,
|
||||
Auto = 0x16,
|
||||
CustomType = 0x00,
|
||||
Padding = 0x1F,
|
||||
|
||||
Unsigned = 0xFF00,
|
||||
Signed = 0xFF01,
|
||||
FloatingPoint = 0xFF02,
|
||||
Integer = 0xFF03,
|
||||
Any = 0xFFFF
|
||||
};
|
||||
|
||||
enum class Separator {
|
||||
RoundBracketOpen,
|
||||
RoundBracketClose,
|
||||
CurlyBracketOpen,
|
||||
CurlyBracketClose,
|
||||
SquareBracketOpen,
|
||||
SquareBracketClose,
|
||||
Comma,
|
||||
Dot,
|
||||
EndOfExpression,
|
||||
EndOfProgram
|
||||
};
|
||||
|
||||
struct Identifier {
|
||||
explicit Identifier(std::string identifier) : m_identifier(std::move(identifier)) { }
|
||||
|
||||
[[nodiscard]]
|
||||
const std::string &get() const { return this->m_identifier; }
|
||||
|
||||
auto operator<=>(const Identifier&) const = default;
|
||||
bool operator==(const Identifier&) const = default;
|
||||
|
||||
private:
|
||||
std::string m_identifier;
|
||||
};
|
||||
|
||||
using Literal = std::variant<char, bool, u128, s128, double, std::string, PatternData*>;
|
||||
using ValueTypes = std::variant<Keyword, Identifier, Operator, Literal, ValueType, Separator>;
|
||||
|
||||
Token(Type type, auto value, u32 lineNumber) : type(type), value(value), lineNumber(lineNumber) {
|
||||
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static inline bool isUnsigned(const ValueType type) {
|
||||
return (static_cast<u32>(type) & 0x0F) == 0x00;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static inline bool isSigned(const ValueType type) {
|
||||
return (static_cast<u32>(type) & 0x0F) == 0x01;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static inline bool isFloatingPoint(const ValueType type) {
|
||||
return (static_cast<u32>(type) & 0x0F) == 0x02;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static inline u32 getTypeSize(const ValueType type) {
|
||||
return static_cast<u32>(type) >> 4;
|
||||
}
|
||||
|
||||
static u128 literalToUnsigned(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> u128 { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> u128 { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> u128 { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static s128 literalToSigned(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> s128 { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> s128 { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> s128 { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static double literalToFloatingPoint(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> double { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> double { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> double { return value; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static bool literalToBoolean(const pl::Token::Literal &literal) {
|
||||
return std::visit(overloaded {
|
||||
[](std::string) -> bool { throw std::string("expected integral type, got string"); },
|
||||
[](PatternData*) -> bool { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> bool { return value != 0; }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
static std::string literalToString(const pl::Token::Literal &literal, bool cast) {
|
||||
if (!cast && std::get_if<std::string>(&literal) == nullptr)
|
||||
throw std::string("expected string type, got integral");
|
||||
|
||||
return std::visit(overloaded {
|
||||
[](std::string value) -> std::string { return value; },
|
||||
[](u128 value) -> std::string { return std::to_string(u64(value)); },
|
||||
[](s128 value) -> std::string { return std::to_string(s64(value)); },
|
||||
[](bool value) -> std::string { return value ? "true" : "false"; },
|
||||
[](char value) -> std::string { return std::string() + value; },
|
||||
[](PatternData*) -> std::string { throw std::string("expected integral type, got custom type"); },
|
||||
[](auto &&value) -> std::string { return std::to_string(value); }
|
||||
},
|
||||
literal);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr static auto getTypeName(const pl::Token::ValueType type) {
|
||||
switch (type) {
|
||||
case ValueType::Signed8Bit: return "s8";
|
||||
case ValueType::Signed16Bit: return "s16";
|
||||
case ValueType::Signed32Bit: return "s32";
|
||||
case ValueType::Signed64Bit: return "s64";
|
||||
case ValueType::Signed128Bit: return "s128";
|
||||
case ValueType::Unsigned8Bit: return "u8";
|
||||
case ValueType::Unsigned16Bit: return "u16";
|
||||
case ValueType::Unsigned32Bit: return "u32";
|
||||
case ValueType::Unsigned64Bit: return "u64";
|
||||
case ValueType::Unsigned128Bit: return "u128";
|
||||
case ValueType::Float: return "float";
|
||||
case ValueType::Double: return "double";
|
||||
case ValueType::Character: return "char";
|
||||
case ValueType::Character16: return "char16";
|
||||
case ValueType::Padding: return "padding";
|
||||
case ValueType::String: return "str";
|
||||
default: return "< ??? >";
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const ValueTypes &other) const {
|
||||
if (this->type == Type::Integer || this->type == Type::Identifier || this->type == Type::String)
|
||||
return true;
|
||||
else if (this->type == Type::ValueType) {
|
||||
auto otherValueType = std::get_if<ValueType>(&other);
|
||||
auto valueType = std::get_if<ValueType>(&this->value);
|
||||
|
||||
if (otherValueType == nullptr) return false;
|
||||
if (valueType == nullptr) return false;
|
||||
|
||||
if (*otherValueType == *valueType)
|
||||
return true;
|
||||
else if (*otherValueType == ValueType::Any)
|
||||
return *valueType != ValueType::CustomType && *valueType != ValueType::Padding;
|
||||
else if (*otherValueType == ValueType::Unsigned)
|
||||
return isUnsigned(*valueType);
|
||||
else if (*otherValueType == ValueType::Signed)
|
||||
return isSigned(*valueType);
|
||||
else if (*otherValueType == ValueType::FloatingPoint)
|
||||
return isFloatingPoint(*valueType);
|
||||
else if (*otherValueType == ValueType::Integer)
|
||||
return isUnsigned(*valueType) || isSigned(*valueType);
|
||||
}
|
||||
else
|
||||
return other == this->value;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const ValueTypes &other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
Type type;
|
||||
ValueTypes value;
|
||||
u32 lineNumber;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define COMPONENT(type, value) hex::pl::Token::Type::type, hex::pl::Token::type::value
|
||||
|
||||
#define KEYWORD_STRUCT COMPONENT(Keyword, Struct)
|
||||
#define KEYWORD_UNION COMPONENT(Keyword, Union)
|
||||
#define KEYWORD_USING COMPONENT(Keyword, Using)
|
||||
#define KEYWORD_ENUM COMPONENT(Keyword, Enum)
|
||||
#define KEYWORD_BITFIELD COMPONENT(Keyword, Bitfield)
|
||||
#define KEYWORD_LE COMPONENT(Keyword, LittleEndian)
|
||||
#define KEYWORD_BE COMPONENT(Keyword, BigEndian)
|
||||
#define KEYWORD_IF COMPONENT(Keyword, If)
|
||||
#define KEYWORD_ELSE COMPONENT(Keyword, Else)
|
||||
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
||||
#define KEYWORD_THIS COMPONENT(Keyword, This)
|
||||
#define KEYWORD_WHILE COMPONENT(Keyword, While)
|
||||
#define KEYWORD_FOR COMPONENT(Keyword, For)
|
||||
#define KEYWORD_FUNCTION COMPONENT(Keyword, Function)
|
||||
#define KEYWORD_RETURN COMPONENT(Keyword, Return)
|
||||
#define KEYWORD_NAMESPACE COMPONENT(Keyword, Namespace)
|
||||
#define KEYWORD_IN COMPONENT(Keyword, In)
|
||||
#define KEYWORD_OUT COMPONENT(Keyword, Out)
|
||||
#define KEYWORD_BREAK COMPONENT(Keyword, Break)
|
||||
#define KEYWORD_CONTINUE COMPONENT(Keyword, Continue)
|
||||
|
||||
#define INTEGER hex::pl::Token::Type::Integer, hex::pl::Token::Literal(u128(0))
|
||||
#define IDENTIFIER hex::pl::Token::Type::Identifier, ""
|
||||
#define STRING hex::pl::Token::Type::String, hex::pl::Token::Literal("")
|
||||
|
||||
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
|
||||
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
|
||||
#define OPERATOR_INHERIT COMPONENT(Operator, Inherit)
|
||||
#define OPERATOR_PLUS COMPONENT(Operator, Plus)
|
||||
#define OPERATOR_MINUS COMPONENT(Operator, Minus)
|
||||
#define OPERATOR_STAR COMPONENT(Operator, Star)
|
||||
#define OPERATOR_SLASH COMPONENT(Operator, Slash)
|
||||
#define OPERATOR_PERCENT COMPONENT(Operator, Percent)
|
||||
#define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft)
|
||||
#define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight)
|
||||
#define OPERATOR_BITOR COMPONENT(Operator, BitOr)
|
||||
#define OPERATOR_BITAND COMPONENT(Operator, BitAnd)
|
||||
#define OPERATOR_BITXOR COMPONENT(Operator, BitXor)
|
||||
#define OPERATOR_BITNOT COMPONENT(Operator, BitNot)
|
||||
#define OPERATOR_BOOLEQUALS COMPONENT(Operator, BoolEquals)
|
||||
#define OPERATOR_BOOLNOTEQUALS COMPONENT(Operator, BoolNotEquals)
|
||||
#define OPERATOR_BOOLGREATERTHAN COMPONENT(Operator, BoolGreaterThan)
|
||||
#define OPERATOR_BOOLLESSTHAN COMPONENT(Operator, BoolLessThan)
|
||||
#define OPERATOR_BOOLGREATERTHANOREQUALS COMPONENT(Operator, BoolGreaterThanOrEquals)
|
||||
#define OPERATOR_BOOLLESSTHANOREQUALS COMPONENT(Operator, BoolLessThanOrEquals)
|
||||
#define OPERATOR_BOOLAND COMPONENT(Operator, BoolAnd)
|
||||
#define OPERATOR_BOOLOR COMPONENT(Operator, BoolOr)
|
||||
#define OPERATOR_BOOLXOR COMPONENT(Operator, BoolXor)
|
||||
#define OPERATOR_BOOLNOT COMPONENT(Operator, BoolNot)
|
||||
#define OPERATOR_TERNARYCONDITIONAL COMPONENT(Operator, TernaryConditional)
|
||||
#define OPERATOR_DOLLAR COMPONENT(Operator, Dollar)
|
||||
#define OPERATOR_ADDRESSOF COMPONENT(Operator, AddressOf)
|
||||
#define OPERATOR_SIZEOF COMPONENT(Operator, SizeOf)
|
||||
#define OPERATOR_SCOPERESOLUTION COMPONENT(Operator, ScopeResolution)
|
||||
|
||||
#define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType)
|
||||
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
||||
#define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned)
|
||||
#define VALUETYPE_SIGNED COMPONENT(ValueType, Signed)
|
||||
#define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint)
|
||||
#define VALUETYPE_INTEGER COMPONENT(ValueType, Integer)
|
||||
#define VALUETYPE_ANY COMPONENT(ValueType, Any)
|
||||
|
||||
#define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen)
|
||||
#define SEPARATOR_ROUNDBRACKETCLOSE COMPONENT(Separator, RoundBracketClose)
|
||||
#define SEPARATOR_CURLYBRACKETOPEN COMPONENT(Separator, CurlyBracketOpen)
|
||||
#define SEPARATOR_CURLYBRACKETCLOSE COMPONENT(Separator, CurlyBracketClose)
|
||||
#define SEPARATOR_SQUAREBRACKETOPEN COMPONENT(Separator, SquareBracketOpen)
|
||||
#define SEPARATOR_SQUAREBRACKETCLOSE COMPONENT(Separator, SquareBracketClose)
|
||||
#define SEPARATOR_COMMA COMPONENT(Separator, Comma)
|
||||
#define SEPARATOR_DOT COMPONENT(Separator, Dot)
|
||||
#define SEPARATOR_ENDOFEXPRESSION COMPONENT(Separator, EndOfExpression)
|
||||
#define SEPARATOR_ENDOFPROGRAM COMPONENT(Separator, EndOfProgram)
|
||||
31
lib/libimhex/include/hex/pattern_language/validator.hpp
Normal file
31
lib/libimhex/include/hex/pattern_language/validator.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::pl {
|
||||
|
||||
class ASTNode;
|
||||
|
||||
class Validator {
|
||||
public:
|
||||
Validator();
|
||||
|
||||
bool validate(const std::vector<ASTNode*>& ast);
|
||||
|
||||
const std::pair<u32, std::string>& getError() { return this->m_error; }
|
||||
|
||||
private:
|
||||
std::pair<u32, std::string> m_error;
|
||||
|
||||
using ValidatorError = std::pair<u32, std::string>;
|
||||
|
||||
[[noreturn]] void throwValidateError(std::string_view error, u32 lineNumber) const {
|
||||
throw ValidatorError(lineNumber, error);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
20
lib/libimhex/include/hex/plugin.hpp
Normal file
20
lib/libimhex/include/hex/plugin.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(IMHEX_PLUGIN_NAME, name, author, description)
|
||||
|
||||
#define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \
|
||||
namespace hex::plugin::namespaceName::internal { \
|
||||
[[gnu::visibility("default")]] void initializePlugin(); \
|
||||
\
|
||||
[[gnu::visibility("default")]] const char* getPluginName() { return name; } \
|
||||
[[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \
|
||||
[[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \
|
||||
[[gnu::visibility("default")]] void setImGuiContext(ImGuiContext *ctx) { ImGui::SetCurrentContext(ctx); GImGui = ctx; } \
|
||||
} \
|
||||
void hex::plugin::namespaceName::internal::initializePlugin()
|
||||
24
lib/libimhex/include/hex/providers/overlay.hpp
Normal file
24
lib/libimhex/include/hex/providers/overlay.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
class Overlay {
|
||||
public:
|
||||
Overlay() { }
|
||||
|
||||
void setAddress(u64 address) { this->m_address = address; }
|
||||
[[nodiscard]] u64 getAddress() const { return this->m_address; }
|
||||
|
||||
[[nodiscard]] u64 getSize() const { return this->m_data.size(); }
|
||||
[[nodiscard]] std::vector<u8>& getData() { return this->m_data; }
|
||||
|
||||
private:
|
||||
u64 m_address = 0;
|
||||
std::vector<u8> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
89
lib/libimhex/include/hex/providers/provider.hpp
Normal file
89
lib/libimhex/include/hex/providers/provider.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/shared_data.hpp>
|
||||
#include <hex/providers/overlay.hpp>
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
class Provider {
|
||||
public:
|
||||
constexpr static size_t PageSize = 0x1000'0000;
|
||||
|
||||
Provider();
|
||||
virtual ~Provider();
|
||||
|
||||
[[nodiscard]] virtual bool isAvailable() const = 0;
|
||||
[[nodiscard]] virtual bool isReadable() const = 0;
|
||||
[[nodiscard]] virtual bool isWritable() const = 0;
|
||||
[[nodiscard]] virtual bool isResizable() const = 0;
|
||||
[[nodiscard]] virtual bool isSavable() const = 0;
|
||||
|
||||
virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true);
|
||||
virtual void write(u64 offset, const void *buffer, size_t size);
|
||||
|
||||
virtual void resize(ssize_t newSize);
|
||||
|
||||
virtual void save();
|
||||
virtual void saveAs(const fs::path &path);
|
||||
|
||||
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
|
||||
virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0;
|
||||
[[nodiscard]] virtual size_t getActualSize() const = 0;
|
||||
|
||||
void applyOverlays(u64 offset, void *buffer, size_t size);
|
||||
|
||||
[[nodiscard]] std::map<u64, u8>& getPatches();
|
||||
[[nodiscard]] const std::map<u64, u8>& getPatches() const;
|
||||
void applyPatches();
|
||||
|
||||
[[nodiscard]] Overlay* newOverlay();
|
||||
void deleteOverlay(Overlay *overlay);
|
||||
[[nodiscard]] const std::list<Overlay*>& getOverlays();
|
||||
|
||||
[[nodiscard]] u32 getPageCount() const;
|
||||
[[nodiscard]] u32 getCurrentPage() const;
|
||||
void setCurrentPage(u32 page);
|
||||
|
||||
virtual void setBaseAddress(u64 address);
|
||||
[[nodiscard]] virtual u64 getBaseAddress() const;
|
||||
[[nodiscard]] virtual u64 getCurrentPageAddress() const;
|
||||
[[nodiscard]] virtual size_t getSize() const;
|
||||
[[nodiscard]] virtual std::optional<u32> getPageOfAddress(u64 address) const;
|
||||
|
||||
[[nodiscard]] virtual std::string getName() const = 0;
|
||||
[[nodiscard]] virtual std::vector<std::pair<std::string, std::string>> getDataInformation() const = 0;
|
||||
|
||||
[[nodiscard]] virtual bool open() = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
void addPatch(u64 offset, const void *buffer, size_t size, bool createUndo = false);
|
||||
void createUndoPoint();
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
[[nodiscard]] bool canUndo() const;
|
||||
[[nodiscard]] bool canRedo() const;
|
||||
|
||||
[[nodiscard]] virtual bool hasLoadInterface() const;
|
||||
[[nodiscard]] virtual bool hasInterface() const;
|
||||
virtual void drawLoadInterface();
|
||||
virtual void drawInterface();
|
||||
|
||||
protected:
|
||||
u32 m_currPage = 0;
|
||||
u64 m_baseAddress = 0;
|
||||
|
||||
u32 m_patchTreeOffset = 0;
|
||||
std::list<std::map<u64, u8>> m_patches;
|
||||
std::list<Overlay*> m_overlays;
|
||||
};
|
||||
|
||||
}
|
||||
108
lib/libimhex/include/hex/ui/imgui_imhex_extensions.h
Normal file
108
lib/libimhex/include/hex/ui/imgui_imhex_extensions.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
enum ImGuiCustomCol {
|
||||
ImGuiCustomCol_DescButton,
|
||||
ImGuiCustomCol_DescButtonHovered,
|
||||
ImGuiCustomCol_DescButtonActive,
|
||||
|
||||
ImGuiCustomCol_ToolbarGray,
|
||||
ImGuiCustomCol_ToolbarRed,
|
||||
ImGuiCustomCol_ToolbarYellow,
|
||||
ImGuiCustomCol_ToolbarGreen,
|
||||
ImGuiCustomCol_ToolbarBlue,
|
||||
ImGuiCustomCol_ToolbarPurple,
|
||||
ImGuiCustomCol_ToolbarBrown,
|
||||
|
||||
ImGuiCustomCol_Highlight,
|
||||
|
||||
ImGuiCustomCol_COUNT
|
||||
};
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
struct Texture {
|
||||
ImTextureID textureId;
|
||||
int width, height;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool valid() const noexcept {
|
||||
return this->textureId != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr operator ImTextureID() {
|
||||
return this->textureId;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto size() const noexcept {
|
||||
return ImVec2(this->width, this->height);
|
||||
}
|
||||
};
|
||||
|
||||
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data);
|
||||
|
||||
bool IconHyperlink(const char *icon, const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool Hyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool BulletHyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool DescriptionButton(const char* label, const char* description, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
|
||||
void UnderlinedText(const char* label, ImColor color = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2& size_arg = ImVec2(0, 0));
|
||||
|
||||
void Disabled(const std::function<void()> &widgets, bool disabled);
|
||||
void TextSpinner(const char* label);
|
||||
|
||||
void Header(const char *label, bool firstEntry = false);
|
||||
void HeaderColored(const char *label, ImColor color, bool firstEntry);
|
||||
|
||||
void InfoTooltip(const char *text);
|
||||
|
||||
bool TitleBarButton(const char* label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color);
|
||||
bool IconButton(const char* symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
}
|
||||
|
||||
Texture LoadImageFromPath(const char *path);
|
||||
Texture LoadImageFromMemory(const ImU8 *buffer, int size);
|
||||
void UnloadImage(Texture &texture);
|
||||
|
||||
void OpenPopupInWindow(const char *window_name, const char *popup_name);
|
||||
|
||||
struct ImHexCustomData {
|
||||
ImVec4 Colors[ImGuiCustomCol_COUNT];
|
||||
};
|
||||
|
||||
ImU32 GetCustomColorU32(ImGuiCustomCol idx, float alpha_mul = 1.0F);
|
||||
ImVec4 GetCustomColorVec4(ImGuiCustomCol idx, float alpha_mul = 1.0F);
|
||||
|
||||
void StyleCustomColorsDark();
|
||||
void StyleCustomColorsLight();
|
||||
void StyleCustomColorsClassic();
|
||||
|
||||
void SmallProgressBar(float fraction, float yOffset = 0.0F);
|
||||
|
||||
void TextFormatted(const std::string &fmt, auto&& ... args) {
|
||||
ImGui::TextUnformatted(hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
|
||||
void TextFormattedColored(ImColor color, const std::string &fmt, auto&& ... args) {
|
||||
ImGui::TextColored(color, "%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
|
||||
void TextFormattedDisabled(const std::string &fmt, auto&& ... args) {
|
||||
ImGui::TextDisabled("%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
|
||||
void TextFormattedWrapped(const std::string &fmt, auto&& ... args) {
|
||||
ImGui::TextWrapped("%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
}
|
||||
72
lib/libimhex/include/hex/views/view.hpp
Normal file
72
lib/libimhex/include/hex/views/view.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui_internal.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
#include <fontawesome_font.h>
|
||||
#include <codicons_font.h>
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <hex/helpers/lang.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace hex {
|
||||
|
||||
using namespace hex::lang_literals;
|
||||
|
||||
class View {
|
||||
public:
|
||||
explicit View(std::string unlocalizedViewName);
|
||||
virtual ~View() = default;
|
||||
|
||||
virtual void drawContent() = 0;
|
||||
virtual void drawAlwaysVisible() { }
|
||||
virtual void drawMenu();
|
||||
virtual bool isAvailable() const;
|
||||
virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); }
|
||||
|
||||
static void doLater(std::function<void()> &&function);
|
||||
static std::vector<std::function<void()>>& getDeferedCalls();
|
||||
|
||||
static void drawCommonInterfaces();
|
||||
|
||||
static void showMessagePopup(const std::string &message);
|
||||
static void showErrorPopup(const std::string &errorMessage);
|
||||
static void showFatalPopup(const std::string &errorMessage);
|
||||
|
||||
virtual bool hasViewMenuItemEntry() const;
|
||||
virtual ImVec2 getMinSize() const;
|
||||
virtual ImVec2 getMaxSize() const;
|
||||
|
||||
bool& getWindowOpenState();
|
||||
const bool& getWindowOpenState() const;
|
||||
|
||||
[[nodiscard]] const std::string& getUnlocalizedName() const;
|
||||
|
||||
static void confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function<void()> &leftButtonFn, const std::function<void()> &rightButtonFn);
|
||||
static void discardNavigationRequests();
|
||||
|
||||
static inline std::string toWindowName(const std::string &unlocalizedName) {
|
||||
return LangEntry(unlocalizedName) + "###" + unlocalizedName;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedViewName;
|
||||
bool m_windowOpen = false;
|
||||
std::map<Shortcut, std::function<void()>> m_shortcuts;
|
||||
|
||||
friend class ShortcutManager;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user