read any other ROOT obj as a blob, rather than just TBaskets

This commit is contained in:
silverweed 2024-11-19 15:27:11 +01:00
parent a9109144a6
commit 885ef4ae3c
8 changed files with 59 additions and 51 deletions

View file

@ -5,7 +5,7 @@ void print_help(const char *argv0)
"rntviewer v" V_MAJOR "." V_MINOR " by silverweed"
"\n"
"\nUsage: %s [-Behkntv] [-s START] [-l LEN] [-w WIDTH] <ntuple_file.root> [ntuple_name]"
"\n\t-B: disable highlighting of TBaskets"
"\n\t-R: disable highlighting of non-RNTuple ROOT objects"
"\n\t-e: display some extended info(*) (may slow down the startup)"
"\n\t-h: display this help and exit"
"\n\t-l: display LEN bytes (only in terminal mode)"
@ -76,7 +76,7 @@ struct Cmdline_Args {
b8 extended_info;
b8 only_print_rntuple_names;
b8 print_keys_info;
b8 disable_tbaskets;
b8 dont_collect_other_root_objs;
String8 ntpl_name;
String8 file_name;
@ -169,8 +169,8 @@ Cmdline_Args parse_args(i32 argc, char **argv)
args.show_version_and_exit = true;
else if (arg[1] == 'k')
args.print_keys_info = true;
else if (arg[1] == 'B')
args.disable_tbaskets = true;
else if (arg[1] == 'R')
args.dont_collect_other_root_objs = true;
else if (arg[1] == 'w') {
u64 n_cols = 0;
parse_int_arg(i, argc, argv, n_cols);

View file

@ -1060,9 +1060,11 @@ struct Sec_Hover_Fn {
});
}
void basket()
void other_root_obj()
{
titled_section("TBasket", [this] {
Other_Root_Obj_Info *info = (Other_Root_Obj_Info *)section.info;
String8 name = info ? info->class_name : str8("(Unknown)");
titled_section(name.c(), [this] {
tkey();
range("Payload", section.range.len - section.post_size);
});
@ -1104,7 +1106,7 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
case Sec_TFile_Info: hover.tfile_info(); break;
case Sec_TFile_FreeList: hover.tfile_freelist(); break;
case Sec_TKey_List: hover.tkey_list(); break;
case Sec_Basket: hover.basket(); break;
case Sec_Other: hover.other_root_obj(); break;
default:
info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c());
}

View file

@ -115,8 +115,8 @@ u32 mem_edit_bg_color_fn(const u8 *data, u64 off, void *user_data)
return imcol(app->viewer.col_highlight, brighten);
if (section.id == Sec_Page && off == section.range.start)
return imcol(app->viewer.col_page_start, brighten);
if (section.id == Sec_Basket && off == section.range.start)
return imcol(app->viewer.col_basket_start, brighten);
if (section.id == Sec_Other && off == section.range.start)
return imcol(app->viewer.col_other_root_obj_start, brighten);
if (off < section.range.start)
return imcol(app->viewer.col_key, brighten);
if (section.range.end() - section.post_size <= off && off < section.range.end())
@ -145,7 +145,7 @@ void init_viewer(App_State &app, u16 n_cols)
#define COL(c, r, g, b) viewer.c[0] = r/255.0, viewer.c[1] = g/255.0, viewer.c[2] = b/255.0
COL(col_key, 0, 100, 50);
COL(col_page_start, 200, 0, 200);
COL(col_basket_start, 200, 200, 150);
COL(col_other_root_obj_start, 200, 200, 150);
COL(col_checksum, 134, 65, 25);
COL(col_highlight, 190, 190, 190);
#define COL_S(c, r, g, b) viewer.col_section[c][0] = r/255.0, viewer.col_section[c][1] = g/255.0, viewer.col_section[c][2] = b/255.0
@ -159,7 +159,7 @@ void init_viewer(App_State &app, u16 n_cols)
COL_S(Sec_Page, 125, 0, 125);
COL_S(Sec_Page_List, 60, 110, 120);
COL_S(Sec_TKey_List, 100, 140, 100);
COL_S(Sec_Basket, 140, 140, 100);
COL_S(Sec_Other, 140, 140, 100);
#undef COL
#undef COL_S
}
@ -204,20 +204,20 @@ void viewer_jump_to_page_list(App_State &app, u64 page_list_idx)
}
internal
void viewer_jump_to_basket(App_State &app, u64 basket_idx)
void viewer_jump_to_other_root_obj(App_State &app, u64 obj_idx)
{
u64 n_baskets = app.tfile_data.tkeys_data.n_baskets;
if (n_baskets == 0)
u64 n_other_root_objs = app.tfile_data.tkeys_data.n_other_root_obj;
if (n_other_root_objs == 0)
return;
basket_idx = (basket_idx + n_baskets) % n_baskets;
obj_idx = (obj_idx + n_other_root_objs) % n_other_root_objs;
Basket_Info *binfo = app.tfile_data.tkeys_data.baskets;
for (u64 i = 0; i < basket_idx; ++i)
binfo = binfo->next;
Other_Root_Obj_Info *info = app.tfile_data.tkeys_data.other_root_obj;
for (u64 i = 0; i < obj_idx; ++i)
info = info->next;
app.viewer.latest_basket_gone_to = basket_idx;
viewer_jump_to(app, binfo->section.range.start);
app.viewer.latest_root_obj_gone_to = obj_idx;
viewer_jump_to(app, info->section.range.start);
}
internal
@ -409,20 +409,20 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c());
if (app.tfile_data.tkeys_data.n_baskets > 0) {
ImGui::ColorEdit3("_TTree Basket", app.viewer.col_section[Sec_Basket], edit_flags);
if (app.tfile_data.tkeys_data.n_other_root_obj > 0) {
ImGui::ColorEdit3("_Other", app.viewer.col_section[Sec_Other], edit_flags);
ImGui::SameLine();
if (ImGui::Button("TTree Basket"))
viewer_jump_to_basket(app, app.viewer.latest_basket_gone_to);
if (ImGui::Button("Other"))
viewer_jump_to_other_root_obj(app, app.viewer.latest_root_obj_gone_to);
ImGui::SameLine();
{
i64 basket_to_go_to = app.viewer.latest_basket_gone_to;
i64 other_root_obj_to_go_to = app.viewer.latest_root_obj_gone_to;
ImGui::PushItemWidth(80.f);
if (ImGui::InputScalar("##basket_viewed", ImGuiDataType_S64, &basket_to_go_to, &step_i64, nullptr, "%u")
if (ImGui::InputScalar("##other_root_objviewed", ImGuiDataType_S64, &other_root_obj_to_go_to, &step_i64, nullptr, "%u")
&& ImGui::IsItemDeactivatedAfterEdit())
{
viewer_jump_to_basket(app, basket_to_go_to);
viewer_jump_to_other_root_obj(app, other_root_obj_to_go_to);
}
ImGui::PopItemWidth();
}

View file

@ -5,7 +5,7 @@ struct Viewer {
f32 col_checksum[3];
f32 col_highlight[3];
f32 col_page_start[3];
f32 col_basket_start[3];
f32 col_other_root_obj_start[3];
#ifndef RNT_NO_GFX
MemoryEditor mem_edit;
@ -22,7 +22,7 @@ struct Viewer {
u64 latest_key_gone_to;
u64 latest_checksum_gone_to;
u64 latest_page_list_gone_to;
u64 latest_basket_gone_to;
u64 latest_root_obj_gone_to;
Byte_Range hovered_range;

View file

@ -539,9 +539,9 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
}
// @Speed
for (Basket_Info *basket = tdata.baskets; basket; basket = basket->next) {
if (basket->section.range.start - basket->section.pre_size <= off && off < basket->section.range.end()) {
return basket->section;
for (Other_Root_Obj_Info *other = tdata.other_root_obj; other; other = other->next) {
if (other->section.range.start - other->section.pre_size <= off && off < other->section.range.end()) {
return other->section;
}
}

View file

@ -68,7 +68,8 @@ enum Section_Id {
Sec_First_Non_Unique,
Sec_Page = Sec_First_Non_Unique,
Sec_Basket,
// any other object stored in a TKey
Sec_Other,
Sec_COUNT
};
@ -97,7 +98,7 @@ internal const String8 section_names[Sec_COUNT] = {
str8("RNTuple Footer"),
str8("Page List"),
str8("Page"),
str8("Basket"),
str8("Other"),
};
struct Byte_Range_Node {
@ -111,8 +112,9 @@ struct RNTuple_Anchor_Info {
u64 offset_in_file;
};
struct Basket_Info {
Basket_Info *next;
struct Other_Root_Obj_Info {
Other_Root_Obj_Info *next;
String8 class_name;
Section section;
};
@ -122,8 +124,8 @@ struct TKeys_Data {
RNTuple_Anchor_Info *rntuples;
Byte_Range_Node *rblob_keys;
Basket_Info *baskets;
u64 n_baskets;
Other_Root_Obj_Info *other_root_obj;
u64 n_other_root_obj;
};
struct TFile_Data {

View file

@ -82,7 +82,7 @@ using ROOT::Experimental::Internal::RNTupleSerializer;
#endif
#define V_MAJOR "0"
#define V_MINOR "8"
#define V_MINOR "9"
// Internal sources
// --------------------------------------------------
@ -161,8 +161,8 @@ int main(int argc, char **argv)
u32 walk_tkeys_flags = WTK_NONE;
if (args.print_keys_info)
walk_tkeys_flags |= WTK_PRINT_KEYS_INFO;
if (!args.disable_tbaskets)
walk_tkeys_flags |= WTK_COLLECT_BASKETS;
if (!args.dont_collect_other_root_objs)
walk_tkeys_flags |= WTK_COLLECT_OTHER_ROOT_OBJS;
b8 success = get_tfile_data(arena, app.inspected_file, walk_tkeys_flags, app.ntpl_name, app.tfile_data);
if (args.only_print_rntuple_names) {
for (RNTuple_Anchor_Info *info = app.tfile_data.tkeys_data.rntuples; info; info = info->next)

View file

@ -58,7 +58,7 @@ T read_be(const void *data)
enum {
WTK_NONE = 0,
WTK_PRINT_KEYS_INFO = 1,
WTK_COLLECT_BASKETS = 2,
WTK_COLLECT_OTHER_ROOT_OBJS = 2,
};
// Examines the innards of a TFile to get byte range info about the TKeys.
@ -170,7 +170,7 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
cur = pre + tfile_obj_nbytes;
RNTuple_Anchor_Info *rntuple_info_tail = nullptr;
Basket_Info *baskets_tail = nullptr;
Other_Root_Obj_Info *other_root_obj_tail = nullptr;
u32 n_keys = 0;
// Walk through all the TKeys in the file and do two things:
@ -271,19 +271,23 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
rblob_key->next = tkeys_data.rblob_keys;
tkeys_data.rblob_keys = rblob_key;
} else if ((flags & WTK_COLLECT_BASKETS) && key_has_class_name("TBasket")) {
Basket_Info *binfo = arena_push<Basket_Info>(arena);
binfo->section.id = Sec_Basket;
} else if ((flags & WTK_COLLECT_OTHER_ROOT_OBJS)) {
Other_Root_Obj_Info *binfo = arena_push<Other_Root_Obj_Info>(arena);
if (cname_len) {
binfo->class_name = str8_from_buf(arena, data + cname_off + 1, cname_len);
}
binfo->section.id = Sec_Other;
binfo->section.info = binfo;
binfo->section.range.start = cur + keylen;
binfo->section.range.len = n_bytes - keylen;
binfo->section.pre_size = keylen;
if (tkeys_data.baskets) {
baskets_tail->next = binfo;
if (tkeys_data.other_root_obj) {
other_root_obj_tail->next = binfo;
} else {
tkeys_data.baskets = binfo;
tkeys_data.other_root_obj = binfo;
}
baskets_tail = binfo;
tkeys_data.n_baskets++;
other_root_obj_tail = binfo;
tkeys_data.n_other_root_obj++;
}
}
cur += n_bytes;