1
0
mirror of synced 2025-01-18 17:14:13 +01:00

feat: Added binary hex cell visualizer

Closes #939
This commit is contained in:
WerWolv 2023-02-18 22:20:02 +01:00
parent 774803492c
commit 0017cd2e40
8 changed files with 98 additions and 19 deletions

View File

@ -417,7 +417,8 @@ namespace hex {
protected:
const static int TextInputFlags;
bool drawDefaultEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const;
bool drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const;
bool drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const;
private:
u16 m_bytesPerCell;
u16 m_maxCharsPerCell;

View File

@ -44,6 +44,7 @@ namespace hex {
std::string to_string(u128 value);
std::string to_string(i128 value);
std::optional<u8> parseBinaryString(const std::string &string);
std::string toByteString(u64 bytes);
std::string makePrintable(u8 c);

View File

@ -607,7 +607,7 @@ namespace hex {
const int DataVisualizer::TextInputFlags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoHorizontalScroll;
bool DataVisualizer::drawDefaultEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
bool DataVisualizer::drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const {
struct UserData {
u8 *data;
i32 maxChars;
@ -636,6 +636,37 @@ namespace hex {
return userData.editingDone || ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape);
}
bool DataVisualizer::drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const {
struct UserData {
std::string *data;
i32 maxChars;
bool editingDone;
};
UserData userData = {
.data = &data,
.maxChars = this->getMaxCharsPerCell(),
.editingDone = false
};
ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *reinterpret_cast<UserData*>(data->UserData);
userData.data->resize(data->BufSize);
if (data->BufTextLen >= userData.maxChars)
userData.editingDone = true;
return 0;
}, &userData);
ImGui::PopID();
return userData.editingDone || ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Escape);
}
void impl::addDataVisualizer(const std::string &unlocalizedName, DataVisualizer *visualizer) {
getVisualizers().insert({ unlocalizedName, visualizer });

View File

@ -66,6 +66,25 @@ namespace hex {
return { data + index + 1 };
}
std::optional<u8> parseBinaryString(const std::string &string) {
if (string.empty())
return std::nullopt;
u8 byte = 0x00;
for (char c : string) {
byte <<= 1;
if (c == '1')
byte |= 0b01;
else if (c == '0')
byte |= 0b00;
else
return std::nullopt;
}
return byte;
}
std::string toByteString(u64 bytes) {
double value = bytes;
u8 unitIndex = 0;

View File

@ -821,6 +821,7 @@
"hex.builtin.view.yara.reset": "Reset",
"hex.builtin.view.yara.rule_added": "Yara rule added!",
"hex.builtin.view.yara.whole_data": "Whole file matches!",
"hex.builtin.visualizer.binary": "Binary",
"hex.builtin.visualizer.decimal.signed.16bit": "Decimal Signed (16 bits)",
"hex.builtin.visualizer.decimal.signed.32bit": "Decimal Signed (32 bits)",
"hex.builtin.visualizer.decimal.signed.64bit": "Decimal Signed (64 bits)",

View File

@ -146,19 +146,11 @@ namespace hex::plugin::builtin {
value = value.substr(2);
if (value.size() > 8) return { };
u8 byte = 0x00;
for (char c : value) {
byte <<= 1;
if (c == '1')
byte |= 0b01;
else if (c == '0')
byte |= 0b00;
else
return { };
}
return { byte };
if (auto result = hex::parseBinaryString(value); result.has_value())
return { result.value() };
else
return { };
}
);

View File

@ -1,5 +1,4 @@
#include <hex/api/content_registry.hpp>
#include <hex/providers/provider.hpp>
#include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h>
@ -54,7 +53,7 @@ namespace hex::plugin::builtin {
hex::unused(address, startedEditing);
if (size == ByteCount) {
return drawDefaultEditingTextBox(address, getFormatString(upperCase), getImGuiDataType<T>(), data, ImGuiInputTextFlags_CharsHexadecimal);
return drawDefaultScalarEditingTextBox(address, getFormatString(upperCase), getImGuiDataType<T>(), data, ImGuiInputTextFlags_CharsHexadecimal);
}
else
return false;
@ -107,7 +106,7 @@ namespace hex::plugin::builtin {
hex::unused(address, startedEditing);
if (size == ByteCount) {
return drawDefaultEditingTextBox(address, getFormatString(upperCase), getImGuiDataType<u8>(), data, ImGuiInputTextFlags_CharsHexadecimal);
return drawDefaultScalarEditingTextBox(address, getFormatString(upperCase), getImGuiDataType<u8>(), data, ImGuiInputTextFlags_CharsHexadecimal);
}
else
return false;
@ -298,6 +297,39 @@ namespace hex::plugin::builtin {
};
class DataVisualizerBinary : public hex::ContentRegistry::HexEditor::DataVisualizer {
public:
DataVisualizerBinary() : DataVisualizer(1, 8) { }
void draw(u64 address, const u8 *data, size_t size, bool) override {
hex::unused(address);
if (size == 1)
ImGui::TextFormatted("{:08b}", *data);
}
bool drawEditing(u64 address, u8 *data, size_t, bool, bool startedEditing) override {
hex::unused(address, startedEditing);
if (startedEditing) {
this->m_inputBuffer = hex::format("{:08b}", *data);
}
if (drawDefaultTextEditingTextBox(address, this->m_inputBuffer, ImGuiInputTextFlags_None)) {
hex::trim(this->m_inputBuffer);
if (auto result = hex::parseBinaryString(this->m_inputBuffer); result.has_value()) {
*data = result.value();
return true;
}
}
return false;
}
private:
std::string m_inputBuffer;
};
void registerDataVisualizers() {
ContentRegistry::HexEditor::addDataVisualizer<DataVisualizerHexadecimal<u8>>("hex.builtin.visualizer.hexadecimal.8bit");
ContentRegistry::HexEditor::addDataVisualizer<DataVisualizerHexadecimal<u16>>("hex.builtin.visualizer.hexadecimal.16bit");
@ -320,6 +352,8 @@ namespace hex::plugin::builtin {
ContentRegistry::HexEditor::addDataVisualizer<DataVisualizerRGBA8>("hex.builtin.visualizer.rgba8");
ContentRegistry::HexEditor::addDataVisualizer<DataVisualizerHexii>("hex.builtin.visualizer.hexii");
ContentRegistry::HexEditor::addDataVisualizer<DataVisualizerBinary>("hex.builtin.visualizer.binary");
}
}

View File

@ -300,6 +300,8 @@ namespace hex::plugin::builtin::ui {
if (!this->m_editingAddress.has_value())
this->m_editingCellType = CellType::None;
this->m_enteredEditingMode = false;
}
}
@ -678,8 +680,6 @@ namespace hex::plugin::builtin::ui {
ImGui::EndTable();
}
ImGui::PopStyleVar();
this->m_enteredEditingMode = false;
}
void HexEditor::drawFooter(const ImVec2 &size) {