From 57bf7675f820107aed1103a165d02f8c1d014923 Mon Sep 17 00:00:00 2001 From: silverweed Date: Fri, 27 Sep 2024 11:54:50 +0200 Subject: [PATCH] some reordering --- src/hover.cpp | 484 +++++++++++++++++++++++++++----------------------- src/rntuple.h | 2 +- src/str.cpp | 47 +++-- 3 files changed, 294 insertions(+), 239 deletions(-) diff --git a/src/hover.cpp b/src/hover.cpp index cefb6cc..cc10452 100644 --- a/src/hover.cpp +++ b/src/hover.cpp @@ -145,7 +145,10 @@ struct Sec_Hover_Fn { } --cur_section_nesting; - info.desc = prev_desc; + + // pop ourselves unless we're the top-level section + if (prev_desc) + info.desc = prev_desc; } // returns true if `val_read` was read @@ -265,9 +268,9 @@ struct Sec_Hover_Fn { return true; } - void tkey() + void tkey(const char *title = "TKey") { - titled_section("TKey", [this] { + titled_section(title, [this] { u16 version_be; memcpy(&version_be, data + start + 4, sizeof(u16)); u32 version = bswap(version_be); @@ -441,6 +444,221 @@ struct Sec_Hover_Fn { }); } + void cluster_summary() + { + frame("Cluster Summary", [this] { + field_le("First Entry: %" PRIu64); + field("", [] (Arena *arena, String8_Node *prev, const char *, u64 x) { + u64 entries = (x << 8) >> 8; + u8 flags = x >> 56; + String8_Node *sn = push_str8_node_child(arena, prev, "Entries: %" PRIu64, entries); + return push_str8_node(arena, sn, "Flags: 0b%b", flags); + }); + }); + } + + void cluster() + { + frame("Cluster", [this] (u32 col_idx) { + titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] { + frame("Pages", [this] (u32 page_idx) { + titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] { + field("", [] (Arena *arena, String8_Node *prev, const char *, i32 n_elems) { + b8 has_checksum = n_elems < 0; + String8_Node *sn = push_str8_node_child(arena, prev, "N Elements: %u", std::abs(n_elems)); + return push_str8_node(arena, sn, "Has Checksum: %s", has_checksum ? "yes" : "no"); + }); + locator("Element Locator"); + }, HoverSec_HideIfNotHovered); + }); + + i64 n_cols; + if (!field("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) { + if (n_cols < 0) { + return push_str8_node_child(arena, prev, "Element Offset: "); + } + return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols); + }, &n_cols)) + { + return; + } + if (n_cols >= 0) + field_le("Compression Settings: %d"); + }, HoverSec_HideIfNotHovered); + }); + } + + template + void frame(const char *title, F &&frame_body_fn, u64 sec_flags = 0) + { + u64 start_off = cur_field_off; + u64 size; + + titled_section(title, [this, title, start_off, &size, &frame_body_fn] { + u32 n_items = 0; + Frame_Type ftype = frame_header(size, &n_items); + if (ftype != FType) + return; + + if constexpr (FType == Frame_List) { + for (u32 i = 0; i < n_items; ++i) + frame_body_fn(i); + } else { + frame_body_fn(); + } + + assert(cur_field_off >= start_off); + u64 allocated_size = cur_field_off - start_off; + if (size < allocated_size) { + fprintf(stderr, "Frame %s told us its size was %" PRIu64 " but we accounted for %" PRIu64 " bytes!\n", + title, size, allocated_size); + } + + u64 extra_size = size - allocated_size; + if (extra_size > 0) + range("Unknown", extra_size); + }, sec_flags); + + cur_field_off = start_off + size; + } + + // ============================================================== + // TOP-LEVEL SECTIONS + // ============================================================== + void tfile_header() + { + titled_section("TFile Header", [this] { + u32 root_version_be; + memcpy(&root_version_be, data + start + 4, sizeof(u32)); + u32 root_version = bswap(root_version_be); + b8 is_big = root_version > 1000'000; + + field_be("ROOT magic number"); + field("ROOT version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) { + x = bswap(x); + x -= (x > 1000'000) * 1000'000; + return push_str8_node_child(arena, prev, fmt, x); + }); + field_be("fBEGIN: 0x%" PRIX64); + if (is_big) { + field_be("fEND: 0x%" PRIX64); + field_be("Seek Free: 0x%" PRIX64); + } else { + field_be("fEND: 0x%" PRIX64); + field_be("Seek Free: 0x%" PRIX64); + } + field_be("NBytes Free: %u"); + field_be("N Free: %u"); + field_be("NBytes Name: %u"); + field_be("Units: %u"); + field_be("Compression: %u"); + if (is_big) + field_be("Seek Info: 0x%" PRIX64); + else + field_be("Seek Info: 0x%" PRIX64); + field_be("NBytes Info: %u"); + range("Padding", section.post_size); + }); + } + + void tfile_object() + { + titled_section("TFile Object", [this] { + tkey(); + field_str8("File Name: %s"); + field_str8("File Title: %s"); + + u16 version_be; + memcpy(&version_be, data + cur_field_off, sizeof(u16)); + u16 version = bswap(version_be); + b8 is_big = version > 1000; + + field("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) { + x = bswap(x); + x -= (x > 1000) * 1000; + return push_str8_node_child(arena, prev, fmt, x); + }); + field("Created: ", hover_display_datetime_str); + field("Modified: ", hover_display_datetime_str); + field_be("NBytes Key: %u"); + field_be("NBytes Name: %u"); + if (is_big) { + field_be("Seek Dir: 0x%" PRIX64) ; + field_be("Seek Parent: 0x%" PRIX64) ; + field_be("Seek Keys: 0x%" PRIX64) ; + } else { + field_be("Seek Dir: 0x%" PRIX64) ; + field_be("Seek Parent: 0x%" PRIX64) ; + field_be("Seek Keys: 0x%" PRIX64) ; + } + field_be("UUID Vers.Class: %u"); + field_le("UUID: %u"); + if (!is_big) + range("Padding", 3 * sizeof(u32)); + }); + } + + void tfile_info() + { + titled_section("TFile Streamer Info", [this] { + tkey(); + b8 zipped; + if (!maybe_rootzip(&zipped)) + return; + + if (zipped) { + range("Compressed Payload", section.range.len); + } else { + field("Byte Count: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) { + x = bswap(x); + x -= 0x4000'0000; + return push_str8_node_child(arena, prev, fmt, x); + }); + field_be("Version: %u"); + range("TObject Data", section.range.len - 6); + } + }); + } + + void tfile_freelist() + { + titled_section("TFile FreeList", [this] { + tkey(); + u16 version_be; + memcpy(&version_be, data + start + cur_field_off, sizeof(u16)); + u32 version = bswap(version_be); + b8 is_big = version > 1000; + + field("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) { + x = bswap(x); + x -= (x > 1000) * 1000; + return push_str8_node_child(arena, prev, fmt, x); + }); + if (is_big) { + field_be("First: 0x%" PRIX64); + field_be("Last: 0x%" PRIX64); + } else { + field_be("First: 0x%X"); + field_be("Last: 0x%X"); + } + }); + } + + void tkey_list() + { + titled_section("TKey List", [this] { + tkey(); + field_str8("Empty: %s"); + field_str8("File Name: %s"); + field_str8("Empty: %s"); + field_be("N Keys: %u"); + tkey("RNTuple Key"); + field_str8("RNTuple Class: %s"); + field_str8("RNTuple Name: %s"); + field_str8("RNTuple Desc: %s"); + }); + } + void rntuple_anchor() { titled_section("RNTuple Anchor", [this] { @@ -527,82 +745,16 @@ struct Sec_Hover_Fn { }); } - void cluster_summary() + void page() { - frame("Cluster Summary", [this] { - field_le("First Entry: %" PRIu64); - field("", [] (Arena *arena, String8_Node *prev, const char *, u64 x) { - u64 entries = (x << 8) >> 8; - u8 flags = x >> 56; - String8_Node *sn = push_str8_node_child(arena, prev, "Entries: %" PRIu64, entries); - return push_str8_node(arena, sn, "Flags: 0b%b", flags); - }); - }); - } - - void cluster() - { - frame("Cluster", [this] (u32 col_idx) { - titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] { - frame("Pages", [this] (u32 page_idx) { - titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] { - field("", [] (Arena *arena, String8_Node *prev, const char *, i32 n_elems) { - b8 has_checksum = n_elems < 0; - String8_Node *sn = push_str8_node_child(arena, prev, "N Elements: %u", std::abs(n_elems)); - return push_str8_node(arena, sn, "Has Checksum: %s", has_checksum ? "yes" : "no"); - }); - locator("Element Locator"); - }, HoverSec_HideIfNotHovered); - }); - - i64 n_cols; - if (!field("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) { - if (n_cols < 0) { - return push_str8_node_child(arena, prev, "Element Offset: "); - } - return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols); - }, &n_cols)) - { - return; - } - if (n_cols >= 0) - field_le("Compression Settings: %d"); - }, HoverSec_HideIfNotHovered); - }); - } - - template - void frame(const char *title, F &&frame_body_fn, u64 sec_flags = 0) - { - u64 start_off = cur_field_off; - u64 size; - - titled_section(title, [this, title, start_off, &size, &frame_body_fn] { - u32 n_items = 0; - Frame_Type ftype = frame_header(size, &n_items); - if (ftype != FType) - return; - - if constexpr (FType == Frame_List) { - for (u32 i = 0; i < n_items; ++i) - frame_body_fn(i); - } else { - frame_body_fn(); - } - - assert(cur_field_off >= start_off); - u64 allocated_size = cur_field_off - start_off; - if (size < allocated_size) { - fprintf(stderr, "Frame %s told us its size was %" PRIu64 " but we accounted for %" PRIu64 " bytes!\n", - title, size, allocated_size); - } - - u64 extra_size = size - allocated_size; - if (extra_size > 0) - range("Unknown", extra_size); - }, sec_flags); - - cur_field_off = start_off + size; + // only try hovering a key if this is the first page of the cluster (<=> pre_size != 0) + if (section.pre_size) + tkey(); + b8 zipped; + if (!maybe_rootzip(&zipped)) + return; + range("Payload", section.range.len - section.post_size); // TODO: improve + field_le("Checksum: 0x%" PRIX64); } void page_list() @@ -626,127 +778,6 @@ struct Sec_Hover_Fn { }, HoverSec_HideIfNotHovered); }); } - - void tfile_header() - { - titled_section("TFile Header", [this] { - u32 root_version_be; - memcpy(&root_version_be, data + start + 4, sizeof(u32)); - u32 root_version = bswap(root_version_be); - b8 is_big = root_version > 1000'000; - - field_be("ROOT magic number"); - field("ROOT version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) { - x = bswap(x); - x -= (x > 1000'000) * 1000'000; - return push_str8_node_child(arena, prev, fmt, x); - }); - field_be("fBEGIN: 0x%" PRIX64); - if (is_big) { - field_be("fEND: 0x%" PRIX64); - field_be("Seek Free: 0x%" PRIX64); - } else { - field_be("fEND: 0x%" PRIX64); - field_be("Seek Free: 0x%" PRIX64); - } - field_be("NBytes Free: %u"); - field_be("N Free: %u"); - field_be("NBytes Name: %u"); - field_be("Units: %u"); - field_be("Compression: %u"); - if (is_big) - field_be("Seek Info: 0x%" PRIX64); - else - field_be("Seek Info: 0x%" PRIX64); - field_be("NBytes Info: %u"); - range("Padding", section.post_size); - }); - } - - void tfile_object() - { - titled_section("TFile Object", [this] { - tkey(); - field_str8("File Name: %s"); - field_str8("File Title: %s"); - - u16 version_be; - memcpy(&version_be, data + cur_field_off, sizeof(u16)); - u16 version = bswap(version_be); - b8 is_big = version > 1000; - - field("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) { - x = bswap(x); - x -= (x > 1000) * 1000; - return push_str8_node_child(arena, prev, fmt, x); - }); - field("Created: ", hover_display_datetime_str); - field("Modified: ", hover_display_datetime_str); - field_be("NBytes Key: %u"); - field_be("NBytes Name: %u"); - if (is_big) { - field_be("Seek Dir: 0x%" PRIX64) ; - field_be("Seek Parent: 0x%" PRIX64) ; - field_be("Seek Keys: 0x%" PRIX64) ; - } else { - field_be("Seek Dir: 0x%" PRIX64) ; - field_be("Seek Parent: 0x%" PRIX64) ; - field_be("Seek Keys: 0x%" PRIX64) ; - } - field_be("UUID Vers.Class: %u"); - field_le("UUID: %u"); - if (!is_big) - range("Padding", 3 * sizeof(u32)); - }); - } - - void tfile_info() - { - titled_section("TFile Info", [this] { - tkey(); - b8 zipped; - if (!maybe_rootzip(&zipped)) - return; - - if (zipped) { - range("Compressed Payload", section.range.len); - } else { - field("Byte Count: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) { - x = bswap(x); - x -= 0x400000000; - return push_str8_node_child(arena, prev, fmt, x); - }); - field_be("Version: %u"); - // hover_try_object(hover) - field_be("Name: %u"); - field_be("N Objects: %u");; - } - }); - } - - void tfile_freelist() - { - titled_section("TFile FreeList", [this] { - tkey(); - u16 version_be; - memcpy(&version_be, data + start + cur_field_off, sizeof(u16)); - u32 version = bswap(version_be); - b8 is_big = version > 1000; - - field("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) { - x = bswap(x); - x -= (x > 1000) * 1000; - return push_str8_node_child(arena, prev, fmt, x); - }); - if (is_big) { - field_be("First: 0x%" PRIX64); - field_be("Last: 0x%" PRIX64); - } else { - field_be("First: 0x%X"); - field_be("Last: 0x%X"); - } - }); - } }; // `off` is the absolute offset into `data`. @@ -769,7 +800,6 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co push_str8_node_child(arena, info.desc, "Bits per elem: %u", pinfo->bits_per_elem); push_str8_node_child(arena, info.desc, "-----------"); } else { - info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c()); } u64 start = section.range.start - section.pre_size; @@ -778,52 +808,52 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co Sec_Hover_Fn hover { start, roff, data, section, arena, info, cur_field_off, display_grouped }; switch (section.id) { - case Sec_RNTuple_Anchor: { + case Sec_RNTuple_Anchor: hover.rntuple_anchor(); - } break; + break; - case Sec_TFile_Header: { + case Sec_TFile_Header: hover.tfile_header(); - } break; + break; - case Sec_TFile_Object: { + case Sec_TFile_Object: hover.tfile_object(); - } break; + break; - case Sec_RNTuple_Header: { + case Sec_RNTuple_Header: hover.rntuple_header(); - } break; + break; - case Sec_RNTuple_Footer: { + case Sec_RNTuple_Footer: hover.rntuple_footer(); - } break; + break; - case Sec_Page_List: { + case Sec_Page_List: hover.page_list(); - } break; + break; - #if 0 - case Sec_Page: { - // only try hovering a key if this is the first page of the cluster (<=> pre_size != 0) - b8 ok = section.pre_size && hover.tkey(); - ok = ok || hover.maybe_rootzip() - || hover.range("Payload", section.range.len - section.post_size) // TODO: improve - || hover.field_le("Checksum: 0x%" PRIX64) - ; - } break; + case Sec_Page: + hover.page(); + break; - case Sec_TFile_Info: { + case Sec_TFile_Info: hover.tfile_info(); - } break; - #endif + break; - case Sec_TFile_FreeList: { + case Sec_TFile_FreeList: hover.tfile_freelist(); - } break; + break; - default:; + case Sec_TKey_List: + hover.tkey_list(); + break; + + default: + info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c()); } + assert(info.desc); + // If we're displaying individual values, only show the ancestry of the highlighted desc and its siblings. // @Speed: there is probably a more efficient way to do this by construction. if (info.highlighted_desc && !display_grouped) { diff --git a/src/rntuple.h b/src/rntuple.h index a61433e..7961fb4 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -140,7 +140,7 @@ internal const String8 section_names[Sec_COUNT] = { str8("None"), str8("TFile Header"), str8("TFile Object"), - str8("TFile Info"), + str8("TFile Streamer Info"), str8("TFile FreeList"), str8("TKey List"), str8("RNTuple Anchor"), diff --git a/src/str.cpp b/src/str.cpp index 2982a1d..5ab4ace 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -39,14 +39,14 @@ String8 to_pretty_size(Arena *arena, u64 bytes) } internal -String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, ...) +String8_Node *push_str8_node_v(Arena *arena, String8_Node *prev, const char *fmt, va_list args) { + va_list args2; + va_copy(args2, args); + String8_Node *snode = arena_push(arena); - va_list args; - va_start(args, fmt); - snode->str = push_str8fv(arena, fmt, args); - va_end(args); + snode->str = push_str8fv(arena, fmt, args2); if (prev) { prev->next = snode; @@ -57,20 +57,34 @@ String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, } snode->prev = prev; + va_end(args2); return snode; } internal -String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const char *fmt, ...) +String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, ...) { - assert(parent); - - String8_Node *snode = arena_push(arena); - va_list args; va_start(args, fmt); - snode->str = push_str8fv(arena, fmt, args); + String8_Node *snode = push_str8_node_v(arena, prev, fmt, args); va_end(args); + return snode; +} + +internal +String8_Node *push_str8_node_child_v(Arena *arena, String8_Node *parent, const char *fmt, va_list args) +{ + va_list args2; + va_copy(args2, args); + if (!parent) { + // If there is no parent, just behave the same as push_str8_node. + String8_Node *snode = push_str8_node_v(arena, nullptr, fmt, args2); + va_end(args2); + return snode; + } + + String8_Node *snode = arena_push(arena); + snode->str = push_str8fv(arena, fmt, args2); snode->prev = parent->last_child; if (parent->first_child) { @@ -82,6 +96,17 @@ String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const cha snode->head = parent->head; snode->parent = parent; + va_end(args2); + return snode; +} + +internal +String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + String8_Node *snode = push_str8_node_child_v(arena, parent, fmt, args); + va_end(args); return snode; }