From 1698feaa7fbba4279b370ca4522745b0e892377a Mon Sep 17 00:00:00 2001 From: silverweed <silverweed14@proton.me> Date: Tue, 12 Nov 2024 11:48:59 +0100 Subject: [PATCH] allow individually hovering over uncompressed page values --- src/hover.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++-- src/render.cpp | 3 +- src/rntuple.cpp | 4 ++- src/rntuple.h | 1 + src/types.h | 6 ++++ 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/hover.cpp b/src/hover.cpp index 433062f..827fe28 100644 --- a/src/hover.cpp +++ b/src/hover.cpp @@ -688,6 +688,66 @@ struct Sec_Hover_Fn { cur_field_off = start_off + size; } + void display_individual_elem(ROOT::Experimental::EColumnType type, u64 elem_idx, u64 n_elems, u64 field_len) + { + String8 title = push_str8f(arena, "Element %" PRIu64 " / %" PRIu64, elem_idx, n_elems); + titled_section(title.c(), [=] { + using CT = ROOT::Experimental::EColumnType; + switch(type) { + case CT::kIndex64: + case CT::kIndex32: + case CT::kUInt64: + return field_le<u64>("Value: %" PRIu64); + case CT::kByte: + case CT::kUInt8: + return field_le<u8>("Value: %u"); + case CT::kChar: + return field_le<char>("Value: %c"); + case CT::kInt8: + return field_le<i8>("Value: %d"); + case CT::kReal64: + return field_le<f64>("Value: %f"); + case CT::kReal32: + return field_le<f32>("Value: %f"); + // TODO + // case CT::kReal16: + // return field_le<f16>("Value: %f"); + case CT::kInt64: + return field_le<i64>("Value: %" PRIi64); + case CT::kInt32: + return field_le<i32>("Value: %d"); + case CT::kUInt32: + return field_le<u32>("Value: %u"); + case CT::kInt16: + return field_le<i16>("Value: %d"); + case CT::kUInt16: + return field_le<u16>("Value: %u"); + case CT::kSwitch: + titled_section("Switch", [this] { + field_le<u64>("Idx: %" PRIu64); + field_le<u32>("Tag: %u"); + }); + return false; + // case CT::kSplitIndex64: + // case CT::kSplitIndex32: + // case CT::kSplitReal64: + // case CT::kSplitReal32: + // case CT::kSplitInt64: + // case CT::kSplitUInt64: + // case CT::kSplitInt32: + // case CT::kSplitUInt32: + // case CT::kSplitInt16: + // case CT::kSplitUInt16: + // case CT::kReal32Trunc: + // case CT::kReal32Quant: + // case CT::kBit: + default: + range("Payload", field_len); + return false; + } + }); + } + // ============================================================== // TOP-LEVEL SECTIONS // ============================================================== @@ -918,8 +978,23 @@ struct Sec_Hover_Fn { if (zipped) { range("Payload", section.range.len - section.post_size - ROOTZIP_RANGE_LEN); } else { - // TODO: improve (hover individual elements?) - range("Payload", section.range.len - section.post_size); + Page_Info_Node *pinfo = (Page_Info_Node *)section.info; + b8 display_individual = !display_grouped; + if (display_individual && pinfo) { + assert(is_pow2(pinfo->bits_per_elem)); + u64 n_elems = std::abs(pinfo->n_elems); + u64 field_len = pinfo->bits_per_elem / 8; + // align cur_field_off to the start of the element + u64 off_in_elems = off - cur_field_off; + off_in_elems = (off_in_elems & ~(field_len - 1)); + u64 elem_idx = off_in_elems / field_len; + cur_field_off += off_in_elems; + display_individual_elem(pinfo->elem_type, elem_idx, n_elems, field_len); + // advance to the end of the section + cur_field_off += field_len * (n_elems - elem_idx - 1); + } else { + range("Payload", section.range.len - section.post_size); + } } b8 has_checksum = section.post_size > 0; if (has_checksum) diff --git a/src/render.cpp b/src/render.cpp index e97fe52..15c64f7 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -411,7 +411,8 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) app.inspected_file.mem, hover_display_grouped, old_version); ImGui::TextColored(ImColor(0.5f, 0.5f, 0.5f), "(Hint: hold Alt for single-field hover information)"); ImGui::TextColored(ImColor(0.5f, 0.5f, 0.5f), "(Hint: Shift-Click to jump to the start of this section)"); - imgui_render_string_tree(scratch.arena, hover_info.desc->head, hover_info.highlighted_desc); + if (hover_info.desc) + imgui_render_string_tree(scratch.arena, hover_info.desc->head, hover_info.highlighted_desc); app.viewer.hovered_range = hover_info.rng; // Shift-clicking on a page section will update the current page in the legend diff --git a/src/rntuple.cpp b/src/rntuple.cpp index ab7123a..d288199 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -242,7 +242,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF for (const RClusterDescriptor::RColumnRange &col_range : cluster_desc.GetColumnRangeIterable()) { const auto &col_descriptor = descriptor.GetColumnDescriptor(col_range.fPhysicalColumnId); - const char *elem_type_name = RColumnElementBase::GetColumnTypeName(col_descriptor.GetType()); + ROOT::Experimental::EColumnType elem_type = col_descriptor.GetType(); + const char *elem_type_name = RColumnElementBase::GetColumnTypeName(elem_type); const auto &field_desc = descriptor.GetFieldDescriptor(col_descriptor.GetFieldId()); const String8 owner_field_name = build_fully_qualified_field_name(arena, descriptor, &field_desc); @@ -258,6 +259,7 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF // If in the future we get RNTuples with more than 4B clusters we can just change the type to u64. assert(cluster_desc.GetId() <= UINT_MAX); pinfo->cluster_id = cluster_desc.GetId(); + pinfo->elem_type = elem_type; pinfo->elem_type_name = push_str8f(arena, "%s", elem_type_name); pinfo->owner_field_name = owner_field_name; pinfo->bits_per_elem = col_descriptor.GetBitsOnStorage(); diff --git a/src/rntuple.h b/src/rntuple.h index 258aa2d..f5f2529 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -21,6 +21,7 @@ struct Page_Info_Node { u64 page_id; u8 bits_per_elem; + ROOT::Experimental::EColumnType elem_type; String8 elem_type_name; String8 owner_field_name; diff --git a/src/types.h b/src/types.h index 2c6abf8..9f2bcc5 100644 --- a/src/types.h +++ b/src/types.h @@ -11,6 +11,7 @@ using b32 = int32_t; using b32x = int; using i8 = int8_t; +using i16 = int16_t; using i32 = int32_t; using i64 = int64_t; @@ -46,3 +47,8 @@ u16 bswap(u16 x) { return x; } u32 bswap(u32 x) { return x; } u64 bswap(u64 x) { return x; } #endif + +constexpr b8 is_pow2(u64 x) +{ + return (x & (x - 1)) == 0; +}