Added proper data inspector view
This commit is contained in:
parent
9c0a270d90
commit
bf6ed3d540
@ -36,6 +36,7 @@ add_executable(ImHex
|
|||||||
source/views/view_help.cpp
|
source/views/view_help.cpp
|
||||||
source/views/view_tools.cpp
|
source/views/view_tools.cpp
|
||||||
source/views/view_strings.cpp
|
source/views/view_strings.cpp
|
||||||
|
source/views/view_data_inspector.cpp
|
||||||
|
|
||||||
libs/glad/source/glad.c
|
libs/glad/source/glad.c
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ namespace hex {
|
|||||||
enum class Events {
|
enum class Events {
|
||||||
DataChanged,
|
DataChanged,
|
||||||
PatternChanged,
|
PatternChanged,
|
||||||
FileDropped
|
FileDropped,
|
||||||
|
ByteSelected
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventHandler {
|
struct EventHandler {
|
||||||
|
57
include/views/view_data_inspector.hpp
Normal file
57
include/views/view_data_inspector.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "views/view.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
namespace prv { class Provider; }
|
||||||
|
|
||||||
|
struct GUID {
|
||||||
|
u32 data1;
|
||||||
|
u16 data2;
|
||||||
|
u16 data3;
|
||||||
|
u8 data4[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
union PreviewData {
|
||||||
|
u8 unsigned8;
|
||||||
|
s8 signed8;
|
||||||
|
u16 unsigned16;
|
||||||
|
s16 signed16;
|
||||||
|
u32 unsigned32;
|
||||||
|
s32 signed32;
|
||||||
|
u64 unsigned64;
|
||||||
|
s64 signed64;
|
||||||
|
char8_t ansiChar;
|
||||||
|
char16_t wideChar;
|
||||||
|
u8 utf8Char[4];
|
||||||
|
float float32;
|
||||||
|
double float64;
|
||||||
|
__time32_t time32;
|
||||||
|
__time64_t time64;
|
||||||
|
GUID guid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewDataInspector : public View {
|
||||||
|
public:
|
||||||
|
explicit ViewDataInspector(prv::Provider* &dataProvider);
|
||||||
|
~ViewDataInspector() override;
|
||||||
|
|
||||||
|
void createView() override;
|
||||||
|
void createMenu() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
prv::Provider* &m_dataProvider;
|
||||||
|
bool m_windowOpen = true;
|
||||||
|
bool m_shouldInvalidate = true;
|
||||||
|
|
||||||
|
PreviewData m_previewData = { 0 };
|
||||||
|
size_t m_validBytes = 0;
|
||||||
|
std::vector<std::pair<std::string, std::string>> m_cachedData;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -47,6 +47,8 @@
|
|||||||
#include <stdio.h> // sprintf, scanf
|
#include <stdio.h> // sprintf, scanf
|
||||||
#include <stdint.h> // uint8_t, etc.
|
#include <stdint.h> // uint8_t, etc.
|
||||||
|
|
||||||
|
#include "views/view.hpp"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define _PRISizeT "I"
|
#define _PRISizeT "I"
|
||||||
#define ImSnprintf _snprintf
|
#define ImSnprintf _snprintf
|
||||||
@ -77,7 +79,6 @@ struct MemoryEditor
|
|||||||
bool ReadOnly; // = false // disable any editing.
|
bool ReadOnly; // = false // disable any editing.
|
||||||
int Cols; // = 16 // number of columns to display.
|
int Cols; // = 16 // number of columns to display.
|
||||||
bool OptShowOptions; // = true // display options button/context menu. when disabled, options will be locked unless you provide your own UI for them.
|
bool OptShowOptions; // = true // display options button/context menu. when disabled, options will be locked unless you provide your own UI for them.
|
||||||
bool OptShowDataPreview; // = false // display a footer previewing the decimal/binary/hex/float representation of the currently selected bytes.
|
|
||||||
bool OptShowHexII; // = false // display values in HexII representation instead of regular hexadecimal: hide null/zero bytes, ascii values as ".X".
|
bool OptShowHexII; // = false // display values in HexII representation instead of regular hexadecimal: hide null/zero bytes, ascii values as ".X".
|
||||||
bool OptShowAscii; // = true // display ASCII representation on the right side.
|
bool OptShowAscii; // = true // display ASCII representation on the right side.
|
||||||
bool OptGreyOutZeroes; // = true // display null/zero bytes using the TextDisabled color.
|
bool OptGreyOutZeroes; // = true // display null/zero bytes using the TextDisabled color.
|
||||||
@ -109,7 +110,6 @@ struct MemoryEditor
|
|||||||
ReadOnly = false;
|
ReadOnly = false;
|
||||||
Cols = 16;
|
Cols = 16;
|
||||||
OptShowOptions = true;
|
OptShowOptions = true;
|
||||||
OptShowDataPreview = false;
|
|
||||||
OptShowHexII = false;
|
OptShowHexII = false;
|
||||||
OptShowAscii = true;
|
OptShowAscii = true;
|
||||||
OptGreyOutZeroes = true;
|
OptGreyOutZeroes = true;
|
||||||
@ -189,8 +189,6 @@ struct MemoryEditor
|
|||||||
|
|
||||||
if (ImGui::Begin(title, &Open, ImGuiWindowFlags_NoScrollbar))
|
if (ImGui::Begin(title, &Open, ImGuiWindowFlags_NoScrollbar))
|
||||||
{
|
{
|
||||||
if (ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) && ImGui::IsMouseReleased(ImGuiMouseButton_Right))
|
|
||||||
ImGui::OpenPopup("context");
|
|
||||||
DrawContents(mem_data, mem_size, base_display_addr);
|
DrawContents(mem_data, mem_size, base_display_addr);
|
||||||
if (ContentsWidthChanged)
|
if (ContentsWidthChanged)
|
||||||
{
|
{
|
||||||
@ -229,8 +227,6 @@ struct MemoryEditor
|
|||||||
float footer_height = 0;
|
float footer_height = 0;
|
||||||
if (OptShowOptions)
|
if (OptShowOptions)
|
||||||
footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1;
|
footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1;
|
||||||
if (OptShowDataPreview)
|
|
||||||
footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1 + ImGui::GetTextLineHeightWithSpacing() * 3;
|
|
||||||
|
|
||||||
ImGui::BeginChild("offset", ImVec2(0, s.LineHeight), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav);
|
ImGui::BeginChild("offset", ImVec2(0, s.LineHeight), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav);
|
||||||
ImGui::Text("% *c ", s.AddrDigitsCount, ' ');
|
ImGui::Text("% *c ", s.AddrDigitsCount, ' ');
|
||||||
@ -267,8 +263,6 @@ struct MemoryEditor
|
|||||||
if (DataPreviewAddrEnd >= mem_size)
|
if (DataPreviewAddrEnd >= mem_size)
|
||||||
DataPreviewAddrEnd = (size_t)-1;
|
DataPreviewAddrEnd = (size_t)-1;
|
||||||
|
|
||||||
size_t preview_data_type_size = OptShowDataPreview ? DataTypeGetSize(PreviewDataType) : 0;
|
|
||||||
|
|
||||||
size_t data_editing_addr_backup = DataEditingAddr;
|
size_t data_editing_addr_backup = DataEditingAddr;
|
||||||
size_t data_editing_addr_next = (size_t)-1;
|
size_t data_editing_addr_next = (size_t)-1;
|
||||||
if (DataEditingAddr != (size_t)-1)
|
if (DataEditingAddr != (size_t)-1)
|
||||||
@ -428,9 +422,15 @@ struct MemoryEditor
|
|||||||
|
|
||||||
DataPreviewAddr = addr;
|
DataPreviewAddr = addr;
|
||||||
DataPreviewAddrEnd = addr;
|
DataPreviewAddrEnd = addr;
|
||||||
|
|
||||||
|
hex::View::postEvent(hex::Events::ByteSelected, &DataPreviewAddr);
|
||||||
}
|
}
|
||||||
if (!ReadOnly && ImGui::IsItemHovered() && ((ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyShift) || ImGui::IsMouseDragging(0))) {
|
if (!ReadOnly && ImGui::IsItemHovered() && ((ImGui::IsMouseClicked(0) && ImGui::GetIO().KeyShift) || ImGui::IsMouseDragging(0))) {
|
||||||
DataPreviewAddrEnd = addr;
|
DataPreviewAddrEnd = addr;
|
||||||
|
|
||||||
|
size_t dataPreviewStart = std::min(DataPreviewAddr, DataPreviewAddrEnd);
|
||||||
|
|
||||||
|
hex::View::postEvent(hex::Events::ByteSelected, &dataPreviewStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,19 +513,12 @@ struct MemoryEditor
|
|||||||
DataEditingAddr = DataPreviewAddr = data_editing_addr_next;
|
DataEditingAddr = DataPreviewAddr = data_editing_addr_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool lock_show_data_preview = OptShowDataPreview;
|
|
||||||
if (OptShowOptions)
|
if (OptShowOptions)
|
||||||
{
|
{
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
DrawOptionsLine(s, mem_data, mem_size, base_display_addr);
|
DrawOptionsLine(s, mem_data, mem_size, base_display_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lock_show_data_preview)
|
|
||||||
{
|
|
||||||
ImGui::Separator();
|
|
||||||
DrawPreviewLine(s, mem_data, mem_size, base_display_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the main window of our ideal child content size (FIXME: we are missing an API to get the contents size from the child)
|
// Notify the main window of our ideal child content size (FIXME: we are missing an API to get the contents size from the child)
|
||||||
ImGui::SetCursorPosX(s.WindowWidth);
|
ImGui::SetCursorPosX(s.WindowWidth);
|
||||||
}
|
}
|
||||||
@ -538,13 +531,12 @@ struct MemoryEditor
|
|||||||
|
|
||||||
// Options menu
|
// Options menu
|
||||||
if (ImGui::Button("Options"))
|
if (ImGui::Button("Options"))
|
||||||
ImGui::OpenPopup("context");
|
ImGui::OpenPopup("options");
|
||||||
if (ImGui::BeginPopup("context"))
|
|
||||||
{
|
if (ImGui::BeginPopup("options")) {
|
||||||
ImGui::PushItemWidth(56);
|
ImGui::PushItemWidth(56);
|
||||||
if (ImGui::DragInt("##cols", &Cols, 0.2f, 4, 32, "%d cols")) { ContentsWidthChanged = true; if (Cols < 1) Cols = 1; }
|
if (ImGui::DragInt("##cols", &Cols, 0.2f, 4, 32, "%d cols")) { ContentsWidthChanged = true; if (Cols < 1) Cols = 1; }
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::Checkbox("Show Data Preview", &OptShowDataPreview);
|
|
||||||
ImGui::Checkbox("Show HexII", &OptShowHexII);
|
ImGui::Checkbox("Show HexII", &OptShowHexII);
|
||||||
if (ImGui::Checkbox("Show Ascii", &OptShowAscii)) { ContentsWidthChanged = true; }
|
if (ImGui::Checkbox("Show Ascii", &OptShowAscii)) { ContentsWidthChanged = true; }
|
||||||
ImGui::Checkbox("Grey out zeroes", &OptGreyOutZeroes);
|
ImGui::Checkbox("Grey out zeroes", &OptGreyOutZeroes);
|
||||||
@ -582,66 +574,7 @@ struct MemoryEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawPreviewLine(const Sizes& s, void* mem_data_void, size_t mem_size, size_t base_display_addr)
|
static bool IsBigEndian()
|
||||||
{
|
|
||||||
IM_UNUSED(base_display_addr);
|
|
||||||
ImU8* mem_data = (ImU8*)mem_data_void;
|
|
||||||
ImGuiStyle& style = ImGui::GetStyle();
|
|
||||||
ImGui::AlignTextToFramePadding();
|
|
||||||
ImGui::Text("Preview as:");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::PushItemWidth((s.GlyphWidth * 10.0f) + style.FramePadding.x * 2.0f + style.ItemInnerSpacing.x);
|
|
||||||
if (ImGui::BeginCombo("##combo_type", DataTypeGetDesc(PreviewDataType), ImGuiComboFlags_HeightLargest))
|
|
||||||
{
|
|
||||||
for (int n = 0; n < ImGuiDataType_COUNT; n++)
|
|
||||||
if (ImGui::Selectable(DataTypeGetDesc((ImGuiDataType)n), PreviewDataType == n))
|
|
||||||
PreviewDataType = (ImGuiDataType)n;
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::PushItemWidth((s.GlyphWidth * 6.0f) + style.FramePadding.x * 2.0f + style.ItemInnerSpacing.x);
|
|
||||||
ImGui::Combo("##combo_endianess", &PreviewEndianess, "LE\0BE\0\0");
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
|
|
||||||
char buf[128] = "";
|
|
||||||
float x = s.GlyphWidth * 6.0f;
|
|
||||||
bool has_value = DataPreviewAddr != (size_t)-1;
|
|
||||||
if (has_value)
|
|
||||||
DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Dec, buf, (size_t)IM_ARRAYSIZE(buf));
|
|
||||||
ImGui::Text("Dec"); ImGui::SameLine(x); ImGui::TextUnformatted(has_value ? buf : "N/A");
|
|
||||||
if (has_value)
|
|
||||||
DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Hex, buf, (size_t)IM_ARRAYSIZE(buf));
|
|
||||||
ImGui::Text("Hex"); ImGui::SameLine(x); ImGui::TextUnformatted(has_value ? buf : "N/A");
|
|
||||||
if (has_value)
|
|
||||||
DrawPreviewData(DataPreviewAddr, mem_data, mem_size, PreviewDataType, DataFormat_Bin, buf, (size_t)IM_ARRAYSIZE(buf));
|
|
||||||
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
|
||||||
ImGui::Text("Bin"); ImGui::SameLine(x); ImGui::TextUnformatted(has_value ? buf : "N/A");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utilities for Data Preview
|
|
||||||
const char* DataTypeGetDesc(ImGuiDataType data_type) const
|
|
||||||
{
|
|
||||||
const char* descs[] = { "Int8", "Uint8", "Int16", "Uint16", "Int32", "Uint32", "Int64", "Uint64", "Float", "Double" };
|
|
||||||
IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
|
|
||||||
return descs[data_type];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DataTypeGetSize(ImGuiDataType data_type) const
|
|
||||||
{
|
|
||||||
const size_t sizes[] = { 1, 1, 2, 2, 4, 4, 8, 8, sizeof(float), sizeof(double) };
|
|
||||||
IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
|
|
||||||
return sizes[data_type];
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* DataFormatGetDesc(DataFormat data_format) const
|
|
||||||
{
|
|
||||||
const char* descs[] = { "Bin", "Dec", "Hex" };
|
|
||||||
IM_ASSERT(data_format >= 0 && data_format < DataFormat_COUNT);
|
|
||||||
return descs[data_format];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsBigEndian() const
|
|
||||||
{
|
{
|
||||||
uint16_t x = 1;
|
uint16_t x = 1;
|
||||||
char c[2];
|
char c[2];
|
||||||
@ -688,132 +621,6 @@ struct MemoryEditor
|
|||||||
fp = IsBigEndian() ? EndianessCopyBigEndian : EndianessCopyLittleEndian;
|
fp = IsBigEndian() ? EndianessCopyBigEndian : EndianessCopyLittleEndian;
|
||||||
return fp(dst, src, size, PreviewEndianess);
|
return fp(dst, src, size, PreviewEndianess);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* FormatBinary(const uint8_t* buf, int width) const
|
|
||||||
{
|
|
||||||
IM_ASSERT(width <= 64);
|
|
||||||
size_t out_n = 0;
|
|
||||||
static char out_buf[64 + 8 + 1];
|
|
||||||
int n = width / 8;
|
|
||||||
for (int j = n - 1; j >= 0; --j)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
out_buf[out_n++] = (buf[j] & (1 << (7 - i))) ? '1' : '0';
|
|
||||||
out_buf[out_n++] = ' ';
|
|
||||||
}
|
|
||||||
IM_ASSERT(out_n < IM_ARRAYSIZE(out_buf));
|
|
||||||
out_buf[out_n] = 0;
|
|
||||||
return out_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [Internal]
|
|
||||||
void DrawPreviewData(size_t addr, const ImU8* mem_data, size_t mem_size, ImGuiDataType data_type, DataFormat data_format, char* out_buf, size_t out_buf_size) const
|
|
||||||
{
|
|
||||||
uint8_t buf[8];
|
|
||||||
size_t elem_size = DataTypeGetSize(data_type);
|
|
||||||
size_t size = addr + elem_size > mem_size ? mem_size - addr : elem_size;
|
|
||||||
if (ReadFn)
|
|
||||||
for (int i = 0, n = (int)size; i < n; ++i)
|
|
||||||
buf[i] = ReadFn(mem_data, addr + i);
|
|
||||||
else
|
|
||||||
memcpy(buf, mem_data + addr, size);
|
|
||||||
|
|
||||||
if (data_format == DataFormat_Bin)
|
|
||||||
{
|
|
||||||
uint8_t binbuf[8];
|
|
||||||
EndianessCopy(binbuf, buf, size);
|
|
||||||
ImSnprintf(out_buf, out_buf_size, "%s", FormatBinary(binbuf, (int)size * 8));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_buf[0] = 0;
|
|
||||||
switch (data_type)
|
|
||||||
{
|
|
||||||
case ImGuiDataType_S8:
|
|
||||||
{
|
|
||||||
int8_t int8 = 0;
|
|
||||||
EndianessCopy(&int8, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hhd", int8); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%02x", int8 & 0xFF); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_U8:
|
|
||||||
{
|
|
||||||
uint8_t uint8 = 0;
|
|
||||||
EndianessCopy(&uint8, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hhu", uint8); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%02x", uint8 & 0XFF); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_S16:
|
|
||||||
{
|
|
||||||
int16_t int16 = 0;
|
|
||||||
EndianessCopy(&int16, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hd", int16); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%04x", int16 & 0xFFFF); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_U16:
|
|
||||||
{
|
|
||||||
uint16_t uint16 = 0;
|
|
||||||
EndianessCopy(&uint16, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%hu", uint16); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%04x", uint16 & 0xFFFF); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_S32:
|
|
||||||
{
|
|
||||||
int32_t int32 = 0;
|
|
||||||
EndianessCopy(&int32, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%d", int32); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%08x", int32); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_U32:
|
|
||||||
{
|
|
||||||
uint32_t uint32 = 0;
|
|
||||||
EndianessCopy(&uint32, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%u", uint32); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%08x", uint32); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_S64:
|
|
||||||
{
|
|
||||||
int64_t int64 = 0;
|
|
||||||
EndianessCopy(&int64, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%lld", (long long)int64); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)int64); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_U64:
|
|
||||||
{
|
|
||||||
uint64_t uint64 = 0;
|
|
||||||
EndianessCopy(&uint64, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%llu", (long long)uint64); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)uint64); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_Float:
|
|
||||||
{
|
|
||||||
float float32 = 0.0f;
|
|
||||||
EndianessCopy(&float32, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%f", float32); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "%a", float32); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_Double:
|
|
||||||
{
|
|
||||||
double float64 = 0.0;
|
|
||||||
EndianessCopy(&float64, buf, size);
|
|
||||||
if (data_format == DataFormat_Dec) { ImSnprintf(out_buf, out_buf_size, "%f", float64); return; }
|
|
||||||
if (data_format == DataFormat_Hex) { ImSnprintf(out_buf, out_buf_size, "%a", float64); return; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ImGuiDataType_COUNT:
|
|
||||||
break;
|
|
||||||
} // Switch
|
|
||||||
IM_ASSERT(0); // Shouldn't reach
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef _PRISizeT
|
#undef _PRISizeT
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "views/view_help.hpp"
|
#include "views/view_help.hpp"
|
||||||
#include "views/view_tools.hpp"
|
#include "views/view_tools.hpp"
|
||||||
#include "views/view_strings.hpp"
|
#include "views/view_strings.hpp"
|
||||||
|
#include "views/view_data_inspector.hpp"
|
||||||
|
|
||||||
#include "providers/provider.hpp"
|
#include "providers/provider.hpp"
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ int main() {
|
|||||||
window.addView<hex::ViewHexEditor>(dataProvider, patternData);
|
window.addView<hex::ViewHexEditor>(dataProvider, patternData);
|
||||||
window.addView<hex::ViewPattern>(dataProvider, patternData);
|
window.addView<hex::ViewPattern>(dataProvider, patternData);
|
||||||
window.addView<hex::ViewPatternData>(dataProvider, patternData);
|
window.addView<hex::ViewPatternData>(dataProvider, patternData);
|
||||||
|
window.addView<hex::ViewDataInspector>(dataProvider);
|
||||||
window.addView<hex::ViewHashes>(dataProvider);
|
window.addView<hex::ViewHashes>(dataProvider);
|
||||||
window.addView<hex::ViewInformation>(dataProvider);
|
window.addView<hex::ViewInformation>(dataProvider);
|
||||||
window.addView<hex::ViewStrings>(dataProvider);
|
window.addView<hex::ViewStrings>(dataProvider);
|
||||||
|
140
source/views/view_data_inspector.cpp
Normal file
140
source/views/view_data_inspector.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "views/view_data_inspector.hpp"
|
||||||
|
|
||||||
|
#include "providers/provider.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end);
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
ViewDataInspector::ViewDataInspector(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) {
|
||||||
|
View::subscribeEvent(Events::ByteSelected, [this](const void* userData){
|
||||||
|
size_t offset = *static_cast<const size_t*>(userData);
|
||||||
|
|
||||||
|
this->m_validBytes = std::min(this->m_dataProvider->getSize() - offset, sizeof(PreviewData));
|
||||||
|
std::memset(&this->m_previewData, 0x00, sizeof(PreviewData));
|
||||||
|
this->m_dataProvider->read(offset, &this->m_previewData, sizeof(PreviewData));
|
||||||
|
|
||||||
|
this->m_shouldInvalidate = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewDataInspector::~ViewDataInspector() {
|
||||||
|
View::unsubscribeEvent(Events::ByteSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewDataInspector::createView() {
|
||||||
|
if (!this->m_windowOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->m_shouldInvalidate) {
|
||||||
|
this->m_shouldInvalidate = false;
|
||||||
|
|
||||||
|
this->m_cachedData.clear();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string binary;
|
||||||
|
for (u8 i = 0; i < 8; i++)
|
||||||
|
binary += ((this->m_previewData.unsigned8 << i) & 0x80) == 0 ? '0' : '1';
|
||||||
|
this->m_cachedData.emplace_back("Binary (8 bit)", binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_cachedData.emplace_back("uint8_t", hex::format("%u", this->m_previewData.unsigned8));
|
||||||
|
this->m_cachedData.emplace_back("int8_t", hex::format("%d", this->m_previewData.unsigned8));
|
||||||
|
this->m_cachedData.emplace_back("uint16_t", hex::format("%u", this->m_previewData.unsigned16));
|
||||||
|
this->m_cachedData.emplace_back("int16_t", hex::format("%d", this->m_previewData.unsigned16));
|
||||||
|
this->m_cachedData.emplace_back("uint32_t", hex::format("%lu", this->m_previewData.unsigned32));
|
||||||
|
this->m_cachedData.emplace_back("int32_t", hex::format("%ld", this->m_previewData.unsigned32));
|
||||||
|
this->m_cachedData.emplace_back("uint64_t", hex::format("%llu", this->m_previewData.unsigned64));
|
||||||
|
this->m_cachedData.emplace_back("int64_t", hex::format("%lld", this->m_previewData.unsigned64));
|
||||||
|
|
||||||
|
this->m_cachedData.emplace_back("ANSI Character / char8_t", hex::format("%c", this->m_previewData.ansiChar));
|
||||||
|
this->m_cachedData.emplace_back("Wide Character / char16_t", hex::format("%lc", this->m_previewData.wideChar));
|
||||||
|
{
|
||||||
|
char buffer[5] = { 0 };
|
||||||
|
std::memcpy(buffer, &this->m_previewData.utf8Char, 4);
|
||||||
|
u32 utf8 = 0;
|
||||||
|
ImTextCharFromUtf8(&utf8, buffer, buffer + 4);
|
||||||
|
this->m_cachedData.emplace_back("UTF-8 code point", hex::format("U+%08lx", utf8));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_cachedData.emplace_back("float (32 bit)", hex::format("%e", this->m_previewData.float32));
|
||||||
|
this->m_cachedData.emplace_back("double (64 bit)", hex::format("%e", this->m_previewData.float64));
|
||||||
|
|
||||||
|
{
|
||||||
|
std::tm * ptm = _localtime32(&this->m_previewData.time32);
|
||||||
|
char buffer[32];
|
||||||
|
if (std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm))
|
||||||
|
this->m_cachedData.emplace_back("__time32_t", buffer);
|
||||||
|
else
|
||||||
|
this->m_cachedData.emplace_back("__time32_t", "Invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::tm * ptm = _localtime64(&this->m_previewData.time64);
|
||||||
|
char buffer[64];
|
||||||
|
if (std::strftime(buffer, 64, "%a, %d.%m.%Y %H:%M:%S", ptm) != 0)
|
||||||
|
this->m_cachedData.emplace_back("__time64_t", buffer);
|
||||||
|
else
|
||||||
|
this->m_cachedData.emplace_back("__time64_t", "Invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_cachedData.emplace_back("GUID", hex::format("{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}",
|
||||||
|
this->m_previewData.guid.data1, this->m_previewData.guid.data2, this->m_previewData.guid.data3,
|
||||||
|
this->m_previewData.guid.data4[0], this->m_previewData.guid.data4[1], this->m_previewData.guid.data4[2], this->m_previewData.guid.data4[3],
|
||||||
|
this->m_previewData.guid.data4[4], this->m_previewData.guid.data4[5], this->m_previewData.guid.data4[6], this->m_previewData.guid.data4[7]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ImGui::Begin("Data Preview", &this->m_windowOpen)) {
|
||||||
|
if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) {
|
||||||
|
if (ImGui::BeginChild("##scrolling")) {
|
||||||
|
if (ImGui::BeginTable("##datainspector", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
|
||||||
|
ImGui::TableSetupColumn("Name");
|
||||||
|
ImGui::TableSetupColumn("Value");
|
||||||
|
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
u32 rowCount = 0;
|
||||||
|
for (const auto &[name, value] : this->m_cachedData) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(name.c_str());
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(value.c_str());
|
||||||
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
|
||||||
|
((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030);
|
||||||
|
rowCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("RGBA Color");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::ColorButton("##nolabel", ImColor(this->m_previewData.unsigned32),
|
||||||
|
ImGuiColorEditFlags_None, ImVec2(ImGui::GetColumnWidth(), 15));
|
||||||
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
|
||||||
|
((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030);
|
||||||
|
rowCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewDataInspector::createMenu() {
|
||||||
|
if (ImGui::BeginMenu("View")) {
|
||||||
|
ImGui::MenuItem("Data Preview View", "", &this->m_windowOpen);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -96,10 +96,12 @@ namespace hex {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (ImGui::Begin("Pattern", &this->m_windowOpen, ImGuiWindowFlags_None)) {
|
if (ImGui::Begin("Pattern", &this->m_windowOpen, ImGuiWindowFlags_None)) {
|
||||||
this->m_textEditor.Render("Pattern");
|
if (this->m_dataProvider != nullptr && this->m_dataProvider->isAvailable()) {
|
||||||
|
this->m_textEditor.Render("Pattern");
|
||||||
|
|
||||||
if (this->m_textEditor.IsTextChanged()) {
|
if (this->m_textEditor.IsTextChanged()) {
|
||||||
this->parsePattern(this->m_textEditor.GetText().data());
|
this->parsePattern(this->m_textEditor.GetText().data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user