From 83ad84491f6abd195b8ce984602672d86a7a18d2 Mon Sep 17 00:00:00 2001 From: silverweed Date: Fri, 19 Jul 2024 16:31:48 +0200 Subject: [PATCH] add cluster highlighting --- src/render.cpp | 58 +++++++++++++++++--- src/render.h | 6 +- src/rntuple.cpp | 1 + src/rntuple.h | 17 +++--- third_party/imgui_club/imgui_memory_editor.h | 6 +- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/render.cpp b/src/render.cpp index afa3cde..4effbbd 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -37,6 +37,7 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) const RNTuple_Data &rdata = app->rndata; const TFile_Data &tdata = app->tfile_data; u64 rblob_sz = rdata.rblob_header_size; // @Incomplete + i64 hilite_cluster = app->viewer.highlight_cluster ? app->viewer.highlighted_cluster : -1; off += app->viewer.base_display_addr; @@ -50,6 +51,8 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) // Handle pages // fast case: `off` is in the same page info as previous `off`. if (app->last_pinfo->range.start < off && off < app->last_pinfo->range.end()) { + if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster) + return COL(app->viewer.col_highlight); if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size()) return COL(app->viewer.col_checksum); return COL(app->viewer.col_page); @@ -60,6 +63,8 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) app->last_pinfo = app->last_pinfo->next; if (app->last_pinfo && app->last_pinfo->range.start <= off && off < app->last_pinfo->range.end()) { + if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster) + return COL(app->viewer.col_highlight); if (off == app->last_pinfo->range.start) return COL(app->viewer.col_page_start); if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size()) @@ -99,8 +104,9 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) for (Page_Info_Node *pinfo = group.first; pinfo; pinfo = pinfo->next) { if (pinfo->range.start <= off && off < pinfo->range.end()) { app->last_pinfo = pinfo; - if (pinfo->range.start == off) return COL(app->viewer.col_page_start); - if (off >= pinfo->range.end() - pinfo->checksum_size()) return COL(app->viewer.col_checksum); + if (hilite_cluster >= 0 && pinfo->cluster_id == (u64)hilite_cluster) return COL(app->viewer.col_highlight); + if (pinfo->range.start == off) return COL(app->viewer.col_page_start); + if (off >= pinfo->range.end() - pinfo->checksum_size()) return COL(app->viewer.col_checksum); return COL(app->viewer.col_page); } } @@ -120,9 +126,11 @@ internal MemoryEditor make_memory_editor(App_State &app) { MemoryEditor mem_edit; - mem_edit.ReadOnly = true; mem_edit.Cols = 32; mem_edit.OptShowDataPreview = true; + // Do nothing on write. + // Note that we don't use ReadOnly = true because that disables selecting bytes + mem_edit.WriteFn = [] (ImU8*, size_t, ImU8) {}; mem_edit.BgColorFn = mem_edit_bg_color_fn; mem_edit.BgColorFnUserData = &app; return mem_edit; @@ -147,6 +155,7 @@ void make_viewer(App_State &app) COL(col_page_start, 200, 0, 200); COL(col_checksum, 134, 65, 25); COL(col_page_list, 60, 110, 120); + COL(col_highlight, 160, 160, 160); #undef COL app.viewer = viewer; @@ -188,6 +197,25 @@ void viewer_jump_to_page_list(App_State &app, u64 page_list_idx) viewer_jump_to(app.viewer, cg_info.rng_page_list.start); } +internal +void viewer_jump_to_cluster(App_State &app, u64 cluster_idx) +{ + assert(app.rndata.n_clusters > 0); + cluster_idx = (cluster_idx + app.rndata.n_clusters) % app.rndata.n_clusters; + + // @Speed + Page_Info_Node *page = app.rndata.pages; + for (u64 i = 0; i < app.rndata.n_pages; ++i) { + if (page->cluster_id == cluster_idx) + break; + page = page->next; + assert(page); + } + + app.viewer.highlighted_cluster = cluster_idx; + viewer_jump_to(app.viewer, page->range.start); +} + internal void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) { @@ -228,7 +256,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) // Draw main content { - const u64 step_u64 = 1; + const i64 step_i64 = 1; ImGui::BeginTable("Hex View", 2, ImGuiTableFlags_Resizable); @@ -296,10 +324,10 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) if (ImGui::Button("Page")) viewer_jump_to_page(app, app.viewer.latest_page_gone_to); ImGui::SameLine(); { - const u64 step_fast_u64 = app.rndata.n_pages / 100; - u64 page_to_go_to = app.viewer.latest_page_gone_to; + const i64 step_fast_i64 = app.rndata.n_pages / 100; + i64 page_to_go_to = app.viewer.latest_page_gone_to; ImGui::PushItemWidth(100.f); - if (ImGui::InputScalar("##page_viewed", ImGuiDataType_U64, &page_to_go_to, &step_u64, &step_fast_u64, "%u")) + if (ImGui::InputScalar("##page_viewed", ImGuiDataType_S64, &page_to_go_to, &step_i64, &step_fast_i64, "%u")) viewer_jump_to_page(app, page_to_go_to); ImGui::PopItemWidth(); } @@ -315,9 +343,9 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) if (ImGui::Button("Page List")) viewer_jump_to_page_list(app, app.viewer.latest_page_list_gone_to); ImGui::SameLine(); { - u64 page_list_to_go_to = app.viewer.latest_page_list_gone_to; + i64 page_list_to_go_to = app.viewer.latest_page_list_gone_to; ImGui::PushItemWidth(80.f); - if (ImGui::InputScalar("##page_list_viewed", ImGuiDataType_U64, &page_list_to_go_to, &step_u64, nullptr, "%u")) + if (ImGui::InputScalar("##page_list_viewed", ImGuiDataType_S64, &page_list_to_go_to, &step_i64, nullptr, "%u")) viewer_jump_to_page_list(app, page_list_to_go_to); ImGui::PopItemWidth(); } @@ -334,6 +362,18 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) ImGui::Text("Num pages: %lu", app.rndata.n_pages); ImGui::Text("Num elements: %lu", app.rndata.n_elems); + { + const i64 step_fast_i64 = app.rndata.n_clusters / 100; + i64 cluster_to_highlight = app.viewer.highlighted_cluster; + ImGui::PushItemWidth(100.f); + if (ImGui::InputScalar("##highlighted_cluster", ImGuiDataType_S64, &cluster_to_highlight, &step_i64, &step_fast_i64, "%u")) { + viewer_jump_to_cluster(app, cluster_to_highlight); + } + ImGui::PopItemWidth(); + ImGui::SameLine(); + ImGui::Checkbox("Highlight cluster", &app.viewer.highlight_cluster); + } + ImGui::EndTable(); } diff --git a/src/render.h b/src/render.h index eb33c6e..99a9eb7 100644 --- a/src/render.h +++ b/src/render.h @@ -13,9 +13,13 @@ struct Viewer { f32 col_page_start[3]; f32 col_checksum[3]; f32 col_page_list[3]; + f32 col_highlight[3]; u64 base_display_addr; - + + b8 highlight_cluster; + u64 highlighted_cluster; + u64 latest_page_gone_to; u64 latest_key_gone_to; u64 latest_checksum_gone_to; diff --git a/src/rntuple.cpp b/src/rntuple.cpp index 83a9261..3d69631 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -119,6 +119,7 @@ void gather_ntuple_metadata(Arena *arena, RMicroFileReader &reader, const RNTupl pinfo->range.start = page_info.fLocator.GetPosition(); pinfo->range.len = page_info.fLocator.fBytesOnStorage + (page_info.fHasChecksum) * checksum_size; pinfo->n_elems = page_info.fHasChecksum ? -page_info.fNElements : page_info.fNElements; + pinfo->cluster_id = cluster_desc.GetId(); if (!pinfo_head) { // first node inserted diff --git a/src/rntuple.h b/src/rntuple.h index 5becf8d..a647e29 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -5,23 +5,24 @@ struct Byte_Range { u64 end() const { return start + len; } }; +// Used to store location information about stuff like checksums, page lists, etc +struct Range_Seq { + Range_Seq *next; + Byte_Range range; +}; + struct Page_Info_Node { Page_Info_Node *next; Byte_Range range; // len includes checksum i32 n_elems; // negative = page has checksum + u64 cluster_id; u64 checksum_size() const { return (n_elems < 0) * 8; } }; -// Used to store location information about stuff like checksums, page lists, etc -struct Range_Seq { - Range_Seq *next; - Byte_Range range; -}; - static const Page_Info_Node invalid_pinfo {}; struct Page_Info_Group { @@ -71,12 +72,10 @@ struct RNTuple_Data { u64 n_elems; u64 tot_page_size; + // TODO Range_Seq *checksums; u64 n_checksums; - Range_Seq *page_lists; - u64 n_page_lists; - Cluster_Group_Info *cluster_groups; u64 n_cluster_groups; u64 tot_page_list_size; diff --git a/third_party/imgui_club/imgui_memory_editor.h b/third_party/imgui_club/imgui_memory_editor.h index 63eb01f..3fd1dcf 100644 --- a/third_party/imgui_club/imgui_memory_editor.h +++ b/third_party/imgui_club/imgui_memory_editor.h @@ -245,7 +245,7 @@ struct MemoryEditor bool data_next = false; - if (/*ReadOnly ||*/ DataEditingAddr >= mem_size) + if (ReadOnly || DataEditingAddr >= mem_size) DataEditingAddr = (size_t)-1; if (DataPreviewAddr >= mem_size) DataPreviewAddr = (size_t)-1; @@ -320,7 +320,6 @@ struct MemoryEditor draw_list->AddRectFilled(pos, ImVec2(pos.x + highlight_width, pos.y + s.LineHeight), BgColorFn(mem_data, addr, BgColorFnUserData)); } - #if 0 if (DataEditingAddr == addr) { // Display text input on current byte @@ -381,7 +380,6 @@ struct MemoryEditor ImGui::PopID(); } else - #endif { // NB: The trailing space is not visible but ensure there's no gap that the mouse cannot click on. ImU8 b = ReadFn ? ReadFn(mem_data, addr) : mem_data[addr]; @@ -404,7 +402,7 @@ struct MemoryEditor else ImGui::Text(format_byte_space, b); } - if (/*!ReadOnly &&*/ ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) + if (!ReadOnly && ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) { DataEditingTakeFocus = true; data_editing_addr_next = addr;