some reordering

This commit is contained in:
silverweed 2024-09-27 11:54:50 +02:00
parent 6468ad1dd7
commit 57bf7675f8
3 changed files with 294 additions and 239 deletions

View file

@ -145,7 +145,10 @@ struct Sec_Hover_Fn {
} }
--cur_section_nesting; --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 // returns true if `val_read` was read
@ -265,9 +268,9 @@ struct Sec_Hover_Fn {
return true; return true;
} }
void tkey() void tkey(const char *title = "TKey")
{ {
titled_section("TKey", [this] { titled_section(title, [this] {
u16 version_be; u16 version_be;
memcpy(&version_be, data + start + 4, sizeof(u16)); memcpy(&version_be, data + start + 4, sizeof(u16));
u32 version = bswap(version_be); u32 version = bswap(version_be);
@ -441,6 +444,221 @@ struct Sec_Hover_Fn {
}); });
} }
void cluster_summary()
{
frame<Frame_Record>("Cluster Summary", [this] {
field_le<u64>("First Entry: %" PRIu64);
field<u64>("", [] (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<Frame_List>("Cluster", [this] (u32 col_idx) {
titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] {
frame<Frame_List>("Pages", [this] (u32 page_idx) {
titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] {
field<i32>("", [] (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<i64>("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) {
if (n_cols < 0) {
return push_str8_node_child(arena, prev, "Element Offset: <suppressed>");
}
return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols);
}, &n_cols))
{
return;
}
if (n_cols >= 0)
field_le<i32>("Compression Settings: %d");
}, HoverSec_HideIfNotHovered);
});
}
template <Frame_Type FType, typename F>
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<u32>("ROOT magic number");
field<u32>("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<u32>("fBEGIN: 0x%" PRIX64);
if (is_big) {
field_be<u64>("fEND: 0x%" PRIX64);
field_be<u64>("Seek Free: 0x%" PRIX64);
} else {
field_be<u32>("fEND: 0x%" PRIX64);
field_be<u32>("Seek Free: 0x%" PRIX64);
}
field_be<u32>("NBytes Free: %u");
field_be<u32>("N Free: %u");
field_be<u32>("NBytes Name: %u");
field_be<u8>("Units: %u");
field_be<u32>("Compression: %u");
if (is_big)
field_be<u64>("Seek Info: 0x%" PRIX64);
else
field_be<u32>("Seek Info: 0x%" PRIX64);
field_be<u32>("NBytes Info: %u");
range("Padding", section.post_size);
});
}
void tfile_object()
{
titled_section("TFile Object", [this] {
tkey();
field_str8<u8>("File Name: %s");
field_str8<u8>("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<u16>("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<u32>("Created: ", hover_display_datetime_str);
field<u32>("Modified: ", hover_display_datetime_str);
field_be<u32>("NBytes Key: %u");
field_be<u32>("NBytes Name: %u");
if (is_big) {
field_be<u64>("Seek Dir: 0x%" PRIX64) ;
field_be<u64>("Seek Parent: 0x%" PRIX64) ;
field_be<u64>("Seek Keys: 0x%" PRIX64) ;
} else {
field_be<u32>("Seek Dir: 0x%" PRIX64) ;
field_be<u32>("Seek Parent: 0x%" PRIX64) ;
field_be<u32>("Seek Keys: 0x%" PRIX64) ;
}
field_be<u16>("UUID Vers.Class: %u");
field_le<u16>("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<u32>("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<u16>("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<u16>("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<u64>("First: 0x%" PRIX64);
field_be<u64>("Last: 0x%" PRIX64);
} else {
field_be<u32>("First: 0x%X");
field_be<u32>("Last: 0x%X");
}
});
}
void tkey_list()
{
titled_section("TKey List", [this] {
tkey();
field_str8<u8>("Empty: %s");
field_str8<u8>("File Name: %s");
field_str8<u8>("Empty: %s");
field_be<u32>("N Keys: %u");
tkey("RNTuple Key");
field_str8<u8>("RNTuple Class: %s");
field_str8<u8>("RNTuple Name: %s");
field_str8<u8>("RNTuple Desc: %s");
});
}
void rntuple_anchor() void rntuple_anchor()
{ {
titled_section("RNTuple Anchor", [this] { titled_section("RNTuple Anchor", [this] {
@ -527,82 +745,16 @@ struct Sec_Hover_Fn {
}); });
} }
void cluster_summary() void page()
{ {
frame<Frame_Record>("Cluster Summary", [this] { // only try hovering a key if this is the first page of the cluster (<=> pre_size != 0)
field_le<u64>("First Entry: %" PRIu64); if (section.pre_size)
field<u64>("", [] (Arena *arena, String8_Node *prev, const char *, u64 x) { tkey();
u64 entries = (x << 8) >> 8; b8 zipped;
u8 flags = x >> 56; if (!maybe_rootzip(&zipped))
String8_Node *sn = push_str8_node_child(arena, prev, "Entries: %" PRIu64, entries); return;
return push_str8_node(arena, sn, "Flags: 0b%b", flags); range("Payload", section.range.len - section.post_size); // TODO: improve
}); field_le<u64>("Checksum: 0x%" PRIX64);
});
}
void cluster()
{
frame<Frame_List>("Cluster", [this] (u32 col_idx) {
titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] {
frame<Frame_List>("Pages", [this] (u32 page_idx) {
titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] {
field<i32>("", [] (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<i64>("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) {
if (n_cols < 0) {
return push_str8_node_child(arena, prev, "Element Offset: <suppressed>");
}
return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols);
}, &n_cols))
{
return;
}
if (n_cols >= 0)
field_le<i32>("Compression Settings: %d");
}, HoverSec_HideIfNotHovered);
});
}
template <Frame_Type FType, typename F>
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;
} }
void page_list() void page_list()
@ -626,127 +778,6 @@ struct Sec_Hover_Fn {
}, HoverSec_HideIfNotHovered); }, 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<u32>("ROOT magic number");
field<u32>("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<u32>("fBEGIN: 0x%" PRIX64);
if (is_big) {
field_be<u64>("fEND: 0x%" PRIX64);
field_be<u64>("Seek Free: 0x%" PRIX64);
} else {
field_be<u32>("fEND: 0x%" PRIX64);
field_be<u32>("Seek Free: 0x%" PRIX64);
}
field_be<u32>("NBytes Free: %u");
field_be<u32>("N Free: %u");
field_be<u32>("NBytes Name: %u");
field_be<u8>("Units: %u");
field_be<u32>("Compression: %u");
if (is_big)
field_be<u64>("Seek Info: 0x%" PRIX64);
else
field_be<u32>("Seek Info: 0x%" PRIX64);
field_be<u32>("NBytes Info: %u");
range("Padding", section.post_size);
});
}
void tfile_object()
{
titled_section("TFile Object", [this] {
tkey();
field_str8<u8>("File Name: %s");
field_str8<u8>("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<u16>("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<u32>("Created: ", hover_display_datetime_str);
field<u32>("Modified: ", hover_display_datetime_str);
field_be<u32>("NBytes Key: %u");
field_be<u32>("NBytes Name: %u");
if (is_big) {
field_be<u64>("Seek Dir: 0x%" PRIX64) ;
field_be<u64>("Seek Parent: 0x%" PRIX64) ;
field_be<u64>("Seek Keys: 0x%" PRIX64) ;
} else {
field_be<u32>("Seek Dir: 0x%" PRIX64) ;
field_be<u32>("Seek Parent: 0x%" PRIX64) ;
field_be<u32>("Seek Keys: 0x%" PRIX64) ;
}
field_be<u16>("UUID Vers.Class: %u");
field_le<u16>("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<u32>("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<u16>("Version: %u");
// hover_try_object(hover)
field_be<u8>("Name: %u");
field_be<u32>("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<u16>("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<u64>("First: 0x%" PRIX64);
field_be<u64>("Last: 0x%" PRIX64);
} else {
field_be<u32>("First: 0x%X");
field_be<u32>("Last: 0x%X");
}
});
}
}; };
// `off` is the absolute offset into `data`. // `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, "Bits per elem: %u", pinfo->bits_per_elem);
push_str8_node_child(arena, info.desc, "-----------"); push_str8_node_child(arena, info.desc, "-----------");
} else { } else {
info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c());
} }
u64 start = section.range.start - section.pre_size; 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 }; Sec_Hover_Fn hover { start, roff, data, section, arena, info, cur_field_off, display_grouped };
switch (section.id) { switch (section.id) {
case Sec_RNTuple_Anchor: { case Sec_RNTuple_Anchor:
hover.rntuple_anchor(); hover.rntuple_anchor();
} break; break;
case Sec_TFile_Header: { case Sec_TFile_Header:
hover.tfile_header(); hover.tfile_header();
} break; break;
case Sec_TFile_Object: { case Sec_TFile_Object:
hover.tfile_object(); hover.tfile_object();
} break; break;
case Sec_RNTuple_Header: { case Sec_RNTuple_Header:
hover.rntuple_header(); hover.rntuple_header();
} break; break;
case Sec_RNTuple_Footer: { case Sec_RNTuple_Footer:
hover.rntuple_footer(); hover.rntuple_footer();
} break; break;
case Sec_Page_List: { case Sec_Page_List:
hover.page_list(); hover.page_list();
} break; break;
#if 0 case Sec_Page:
case Sec_Page: { hover.page();
// only try hovering a key if this is the first page of the cluster (<=> pre_size != 0) break;
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<u64>("Checksum: 0x%" PRIX64)
;
} break;
case Sec_TFile_Info: { case Sec_TFile_Info:
hover.tfile_info(); hover.tfile_info();
} break; break;
#endif
case Sec_TFile_FreeList: { case Sec_TFile_FreeList:
hover.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. // 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. // @Speed: there is probably a more efficient way to do this by construction.
if (info.highlighted_desc && !display_grouped) { if (info.highlighted_desc && !display_grouped) {

View file

@ -140,7 +140,7 @@ internal const String8 section_names[Sec_COUNT] = {
str8("None"), str8("None"),
str8("TFile Header"), str8("TFile Header"),
str8("TFile Object"), str8("TFile Object"),
str8("TFile Info"), str8("TFile Streamer Info"),
str8("TFile FreeList"), str8("TFile FreeList"),
str8("TKey List"), str8("TKey List"),
str8("RNTuple Anchor"), str8("RNTuple Anchor"),

View file

@ -39,14 +39,14 @@ String8 to_pretty_size(Arena *arena, u64 bytes)
} }
internal 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<String8_Node>(arena); String8_Node *snode = arena_push<String8_Node>(arena);
va_list args; snode->str = push_str8fv(arena, fmt, args2);
va_start(args, fmt);
snode->str = push_str8fv(arena, fmt, args);
va_end(args);
if (prev) { if (prev) {
prev->next = snode; prev->next = snode;
@ -57,20 +57,34 @@ String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt,
} }
snode->prev = prev; snode->prev = prev;
va_end(args2);
return snode; return snode;
} }
internal 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<String8_Node>(arena);
va_list args; va_list args;
va_start(args, fmt); 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); 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<String8_Node>(arena);
snode->str = push_str8fv(arena, fmt, args2);
snode->prev = parent->last_child; snode->prev = parent->last_child;
if (parent->first_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->head = parent->head;
snode->parent = parent; 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; return snode;
} }