introduce frame()

This commit is contained in:
silverweed 2024-09-26 14:11:25 +02:00
parent a876064718
commit 331eec77e6

View file

@ -273,38 +273,26 @@ struct Sec_Hover_Fn {
u32 version = bswap(version_be); u32 version = bswap(version_be);
b8 is_big = version > 1000; b8 is_big = version > 1000;
field_be<u32>("NBytes: %u");
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_be<u32>("Obj Len: %u");
field<u32>("Datetime: ", hover_display_datetime_str);
field_be<u16>("Key Len: %u");
field_be<u16>("Cycle: %u");
if (is_big) { if (is_big) {
field_be<u32>("NBytes: %u");
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
x = bswap(x);
x -= 1000;
return push_str8_node_child(arena, prev, fmt, x);
});
field_be<u32>("Obj Len: %u");
field<u32>("Datetime: ", hover_display_datetime_str);
field_be<u16>("Key Len: %u");
field_be<u16>("Cycle: %u");
field_be<u64>("Seek Key: 0x%" PRIX64); field_be<u64>("Seek Key: 0x%" PRIX64);
field_be<u64>("Seek Pdir: 0x%" PRIX64); field_be<u64>("Seek Pdir: 0x%" PRIX64);
field_str8<u8>("Class Name: %s");
field_str8<u8>("Obj Name: %s");
field_str8<u8>("Obj Title: %s");
} else { } else {
field_be<u32>("NBytes: %u");
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
x = bswap(x);
return push_str8_node_child(arena, prev, fmt, x);
});
field_be<u32>("Obj Len: %u");
field<u32>("Datetime: ", hover_display_datetime_str);
field_be<u16>("Key Len: %u");
field_be<u16>("Cycle: %u");
field_be<u32>("Seek Key: 0x%" PRIX64); field_be<u32>("Seek Key: 0x%" PRIX64);
field_be<u32>("Seek Pdir: 0x%" PRIX64); field_be<u32>("Seek Pdir: 0x%" PRIX64);
field_str8<u8>("Class Name: %s");
field_str8<u8>("Obj Name: %s");
field_str8<u8>("Obj Title: %s");
} }
field_str8<u8>("Class Name: %s");
field_str8<u8>("Obj Name: %s");
field_str8<u8>("Obj Title: %s");
}, HoverSec_HideIfNotHovered); }, HoverSec_HideIfNotHovered);
} }
@ -334,47 +322,40 @@ struct Sec_Hover_Fn {
{ {
String8 titlestr = title ? push_str8f(arena, "Frame Header: %s", title) : str8("Frame Header"); String8 titlestr = title ? push_str8f(arena, "Frame Header: %s", title) : str8("Frame Header");
Frame_Type frame_type = Frame_INVALID; Frame_Type frame_type = Frame_INVALID;
titled_section(titlestr.c(), [this, &frame_type, &frame_size = size, n_items, titlestr] { titled_section(titlestr.c(), [this, &frame_type, &frame_size = size, n_items] {
i64 size; i64 size;
memcpy(&size, data + start + cur_field_off, sizeof(size)); memcpy(&size, data + start + cur_field_off, sizeof(size));
if (size >= 0) { if (size >= 0) {
frame_type = Frame_Record; frame_type = Frame_Record;
field<i64>("Record frame size: %" PRIi64 " B", hover_display_val_le_abs<i64>); field<i64>("Record frame size: %" PRIi64 " B", hover_display_val_le_abs<i64>);
} else { } else {
frame_type = Frame_List; if (!n_items) {
assert(n_items); // Since the caller didn't pass us a pointer to n_items, they think we're supposed
memcpy(n_items, data + start + cur_field_off + sizeof(i64), sizeof(*n_items)); // to be parsing a record frame. But it turns out this is actually a frame list!
titled_section("List Frame", [this] { // Something fishy is going on, so just bail out.
field<i64>("Size: %" PRIi64 " B", hover_display_val_le_abs<i64>); frame_type = Frame_INVALID;
field_le<u32>("N Items: %u"); } else {
}); frame_type = Frame_List;
memcpy(n_items, data + start + cur_field_off + sizeof(i64), sizeof(u32));
titled_section("List Frame", [this] {
field<i64>("Size: %" PRIi64 " B", hover_display_val_le_abs<i64>);
field_le<u32>("N Items: %u");
});
}
} }
frame_size = std::abs(size); frame_size = std::abs(size);
}); });
assert(frame_type == Frame_Record || frame_type == Frame_List);
return frame_type; return frame_type;
} }
void field_desc() void field_desc(const char *title)
{ {
static const char *const field_struct_names[] = { static const char *const field_struct_names[] = {
"Leaf", "Collection", "Record", "Variant", "Unsplit" "Leaf", "Collection", "Record", "Variant", "Unsplit"
}; };
titled_section("Field", [this] { frame<Frame_Record>(title, [this] {
u64 start_off = cur_field_off;
u64 size;
Frame_Type ftype = frame_header(size);
if (ftype != Frame_Record)
return;
// DEBUG
if (size > 100000) {
printf("read field_frame_size = %lu at offset 0x%lX!\n", size, start + cur_field_off);
// ended = true;
return;
}
field_le<u32>("Field version: %u"); field_le<u32>("Field version: %u");
field_le<u32>("Type version: %u"); field_le<u32>("Type version: %u");
field_le<u32>("On-disk parent id: %u"); field_le<u32>("On-disk parent id: %u");
@ -398,29 +379,12 @@ struct Sec_Hover_Fn {
field_str8<u32>("Type Name: %s"); field_str8<u32>("Type Name: %s");
field_str8<u32>("Type Alias: %s"); field_str8<u32>("Type Alias: %s");
field_str8<u32>("Description: %s"); field_str8<u32>("Description: %s");
u64 extra_size = size - (cur_field_off - start_off);
if (extra_size > 0)
range("Unknown", extra_size);
}, HoverSec_HideIfNotHovered); }, HoverSec_HideIfNotHovered);
} }
void column_desc(const char *title) void column_desc(const char *title)
{ {
titled_section(title, [this, title] { frame<Frame_Record>(title, [this] {
u64 start_off = cur_field_off;
u64 size;
Frame_Type ftype = frame_header(size);
if (ftype != Frame_Record)
return;
// DEBUG
if (size > 100000) {
printf("read column_desc_size = %lu at offset 0x%lX!\n", size, start + cur_field_off);
// ended = true;
return;
}
field<u16>("Column type: %s", [](Arena *arena, String8_Node *prev, const char *fmt, u16 val) { field<u16>("Column type: %s", [](Arena *arena, String8_Node *prev, const char *fmt, u16 val) {
const char *readable_col_type = get_column_type_name(val); const char *readable_col_type = get_column_type_name(val);
return push_str8_node_child(arena, prev, fmt, readable_col_type); return push_str8_node_child(arena, prev, fmt, readable_col_type);
@ -436,56 +400,21 @@ struct Sec_Hover_Fn {
if (flags & RNTupleSerializer::kFlagDeferredColumn) { if (flags & RNTupleSerializer::kFlagDeferredColumn) {
field_le<u64>("First element: %" PRIu64); field_le<u64>("First element: %" PRIu64);
} }
if (flags & RNTupleSerializer::kFlagHasValueRange) { // if (flags & RNTupleSerializer::kFlagHasValueRange) {
field_le<double>("Value Min: %f"); // field_le<double>("Value Min: %f");
field_le<double>("Value Max: %f"); // field_le<double>("Value Max: %f");
} // }
assert(cur_field_off >= start_off);
if (size < cur_field_off - start_off) {
printf("column_desc(%s) should be of size %lu but we allocated %lu bytes for it?\n", title, size, cur_field_off - start_off);
return;
}
u64 extra_size = size - (cur_field_off - start_off);
printf("extra size: %lu - %lu = %lu\n", size, cur_field_off - start_off, extra_size);
if (extra_size > 0)
range("Unknown", extra_size);
}, HoverSec_HideIfNotHovered); }, HoverSec_HideIfNotHovered);
} }
template <typename F>
void list_frame(const char *title, F &&per_elem_fn)
{
if (ended)
return;
u64 size;
u32 n_elems;
Frame_Type ftype = frame_header(size, &n_elems, title);
if (ftype != Frame_List)
return;
// DEBUG
if (n_elems > 100000) {
printf("read n_elems = %u at offset 0x%lX!\n", n_elems, start + cur_field_off);
// ended = true;
return;
}
for (u32 i = 0; i < n_elems; ++i) {
per_elem_fn();
if (ended)
break;
}
}
void schema_description(const char *title) void schema_description(const char *title)
{ {
titled_section(title, [this] { titled_section(title, [this] {
// TODO: Columns and alias columns are not the same // TODO: Columns and alias columns are not the same
list_frame("Fields", [this] { field_desc(); }); frame<Frame_List>("Fields", [this] (u32 idx) { field_desc(push_str8f(arena, "Field %u", idx).c()); });
list_frame("Columns", [this] { column_desc("Column"); }); frame<Frame_List>("Columns", [this] (u32 idx) { column_desc(push_str8f(arena, "Column %u", idx).c()); });
list_frame("Alias Columns", [this] { column_desc("Alias Column"); }); frame<Frame_List>("Alias Columns", [this] (u32 idx) { column_desc(push_str8f(arena, "Alias Column %u", idx).c()); });
list_frame("Extra Type Infos", [this] { frame<Frame_List>("Extra Type Infos", [this] (u32) {
field_le<u32>("Content identifier: %lu"); field_le<u32>("Content identifier: %lu");
field_le<u32>("Type version from: %lu"); field_le<u32>("Type version from: %lu");
field_le<u32>("Type version to: %lu"); field_le<u32>("Type version to: %lu");
@ -503,18 +432,12 @@ struct Sec_Hover_Fn {
void cluster_group() void cluster_group()
{ {
titled_section("Cluster Group", [this] { frame<Frame_List>("Cluster Group", [this] (u32) {
u64 size; field_le<u64>("Min Entry: %" PRIu64);
u32 n_items; field_le<u64>("Entry Span: %" PRIu64);
Frame_Type ftype = frame_header(size, &n_items); field_le<u32>("N Clusters: %u");
assert(ftype == Frame_List); field_le<u64>("Env.Link Len: %" PRIu64);
for (u32 i = 0; i < n_items; ++i) { locator("Env.Link Locator");
field_le<u64>("Min Entry: %" PRIu64);
field_le<u64>("Entry Span: %" PRIu64);
field_le<u32>("N Clusters: %u");
field_le<u64>("Env.Link Len: %" PRIu64);
locator("Env.Link Locator");
}
}); });
} }
@ -592,9 +515,6 @@ struct Sec_Hover_Fn {
// so they're always occupying only 8 bytes. // so they're always occupying only 8 bytes.
field_le<u64>("Flags: 0x%" PRIX64); field_le<u64>("Flags: 0x%" PRIX64);
field_le<u64>("Header checksum: 0x%" PRIX64); field_le<u64>("Header checksum: 0x%" PRIX64);
u64 size;
Frame_Type ftype = frame_header(size);
assert(ftype == Frame_Record);
schema_description("Schema Extension"); schema_description("Schema Extension");
// - list of column group record frames (TODO) // - list of column group record frames (TODO)
//frame_header("Column Groups"); //frame_header("Column Groups");
@ -607,6 +527,84 @@ 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;
}
void page_list() void page_list()
{ {
titled_section("Page List", [this] { titled_section("Page List", [this] {
@ -620,7 +618,10 @@ struct Sec_Hover_Fn {
range("Payload", section.range.len - section.post_size - sizeof(u64) - 1); range("Payload", section.range.len - section.post_size - sizeof(u64) - 1);
field_le<u64>("Checksum: 0x%" PRIX64); field_le<u64>("Checksum: 0x%" PRIX64);
} else { } else {
// TODO envelope_preamble();
field_le<u64>("Header checksum: 0x%" PRIX64);
frame<Frame_List>("Cluster Summaries", [this] (u32) { cluster_summary(); });
frame<Frame_List>("Clusters", [this] (u32) { cluster(); });
} }
}, HoverSec_HideIfNotHovered); }, HoverSec_HideIfNotHovered);
}); });
@ -632,41 +633,33 @@ struct Sec_Hover_Fn {
u32 root_version_be; u32 root_version_be;
memcpy(&root_version_be, data + start + 4, sizeof(u32)); memcpy(&root_version_be, data + start + 4, sizeof(u32));
u32 root_version = bswap(root_version_be); u32 root_version = bswap(root_version_be);
b8 is_big = root_version > 1000000; 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) { if (is_big) {
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 -= 1000000;
return push_str8_node_child(arena, prev, fmt, x);
});
field_be<u32>("fBEGIN: 0x%" PRIX64);
field_be<u64>("fEND: 0x%" PRIX64); field_be<u64>("fEND: 0x%" PRIX64);
field_be<u64>("Seek Free: 0x%" PRIX64); field_be<u64>("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");
field_be<u64>("Seek Info: 0x%" PRIX64);
field_be<u32>("NBytes Info: %u");
range("Padding", section.post_size);
} else { } else {
field_be<u32>("ROOT magic number");
field_be<u32>("ROOT version: %u");
field_be<u32>("fBEGIN: 0x%" PRIX64);
field_be<u32>("fEND: 0x%" PRIX64); field_be<u32>("fEND: 0x%" PRIX64);
field_be<u32>("Seek Free: 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");
field_be<u32>("Seek Info: 0x%" PRIX64);
field_be<u32>("NBytes Info: %u");
range("Padding", section.post_size);
} }
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);
}); });
} }
@ -682,33 +675,75 @@ struct Sec_Hover_Fn {
u16 version = bswap(version_be); u16 version = bswap(version_be);
b8 is_big = version > 1000; 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) { if (is_big) {
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
x = bswap(x);
x -= 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");
field_be<u64>("Seek Dir: 0x%" PRIX64) ; field_be<u64>("Seek Dir: 0x%" PRIX64) ;
field_be<u64>("Seek Parent: 0x%" PRIX64) ; field_be<u64>("Seek Parent: 0x%" PRIX64) ;
field_be<u64>("Seek Keys: 0x%" PRIX64) ; field_be<u64>("Seek Keys: 0x%" PRIX64) ;
field_be<u16>("UUID Vers.Class: %u");
field_le<u16>("UUID: %u");
} else { } else {
field_be<u16>("Version: %u");
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");
field_be<u32>("Seek Dir: 0x%" PRIX64) ; field_be<u32>("Seek Dir: 0x%" PRIX64) ;
field_be<u32>("Seek Parent: 0x%" PRIX64) ; field_be<u32>("Seek Parent: 0x%" PRIX64) ;
field_be<u32>("Seek Keys: 0x%" PRIX64) ; field_be<u32>("Seek Keys: 0x%" PRIX64) ;
field_be<u16>("UUID Vers.Class: %u"); }
field_le<u16>("UUID: %u"); field_be<u16>("UUID Vers.Class: %u");
field_le<u16>("UUID: %u");
if (!is_big)
range("Padding", 3 * sizeof(u32)); 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");
} }
}); });
} }
@ -778,50 +813,14 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
} break; } break;
case Sec_TFile_Info: { case Sec_TFile_Info: {
hover.tkey() hover.tfile_info();
hover.maybe_rootzip()
// || hover.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);
// })
// || hover.field_be<u16>("Version: %u")
// || hover_try_object(hover)
// || hover.field_be<u8>("Name: %u")
// || hover.field_be<u32>("N Objects: %u")
|| hover.range("Payload", section.range.len) // TODO: improve
;
} break;
case Sec_TFile_FreeList: {
if (!hover.tkey()) {
u16 version_be;
memcpy(&version_be, data + start + hover.cur_field_off, sizeof(u16));
u32 version = bswap(version_be);
b8 is_big = version > 1000;
if (is_big) {
hover.field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
x = bswap(x);
x -= 1000;
return push_str8_node_child(arena, prev, fmt, x);
})
|| hover.field_be<u64>("First: 0x%" PRIX64)
|| hover.field_be<u64>("Last: 0x%" PRIX64)
;
} else {
hover.field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
x = bswap(x);
return push_str8_node_child(arena, prev, fmt, x);
})
|| hover.field_be<u32>("First: 0x%X")
|| hover.field_be<u32>("Last: 0x%X")
;
}
}
} break; } break;
#endif #endif
case Sec_TFile_FreeList: {
hover.tfile_freelist();
} break;
default:; default:;
} }