some more refactoring

This commit is contained in:
silverweed 2025-01-22 17:33:41 +01:00
parent 8c285b977c
commit 299ee4e695
8 changed files with 111 additions and 162 deletions

View file

@ -36,7 +36,7 @@ struct App_State {
// Cache the last info node selected for faster lookup of offsets // Cache the last info node selected for faster lookup of offsets
const Page_Info_Node *last_pinfo; const Page_Info_Node *last_pinfo;
const Other_Root_Obj_Info *last_other_root_obj; const Section *last_other_root_obj;
}; };
internal internal

View file

@ -901,7 +901,6 @@ struct Sec_Hover_Fn {
u32 version = bswap(version_be); u32 version = bswap(version_be);
b8 is_big = version > 1000; b8 is_big = version > 1000;
// FIXME: this is not correct in all cases
while (cur_field_off < section.range.end()) { while (cur_field_off < section.range.end()) {
titled_section("Free Slot", [this, is_big] { titled_section("Free Slot", [this, is_big] {
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) { field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
@ -1069,8 +1068,8 @@ struct Sec_Hover_Fn {
void other_root_obj() void other_root_obj()
{ {
Other_Root_Obj_Info *info = (Other_Root_Obj_Info *)section.info; String8 *class_name = (String8 *)section.info;
String8 name = (info && info->class_name.size) ? info->class_name : str8("(Unknown)"); String8 name = class_name->size ? *class_name : str8("(Unknown)");
titled_section(name.c(), [this] { titled_section(name.c(), [this] {
tkey(); tkey();
range("Payload", section.range.len - section.post_size); range("Payload", section.range.len - section.post_size);

View file

@ -220,54 +220,6 @@ Page_Info_Node *viewer_jump_to_page(App_State &app, u64 page_idx)
return page; return page;
} }
internal
void viewer_jump_to_page_list(App_State &app, u64 page_list_idx)
{
if (app.rndata.n_cluster_groups == 0)
return;
page_list_idx = (page_list_idx + app.rndata.n_cluster_groups) % app.rndata.n_cluster_groups;
Cluster_Group_Info &cg_info = app.rndata.cluster_groups[page_list_idx];
app.viewer.latest_section_gone_to[Sec_Page_List] = page_list_idx;
viewer_jump_to(app, cg_info.rng_page_list.start);
}
internal
void viewer_jump_to_free_slot(App_State &app, u64 free_slot_idx)
{
u64 n_free_slots = app.tfile_data.sections[Sec_Free_Slot].count;
assert(n_free_slots > 0);
u64 idx = (free_slot_idx + n_free_slots) % n_free_slots;
Section *sec = app.tfile_data.sections[Sec_Free_Slot].head;
for (u64 i = 0; i < idx; ++i) {
sec = sec->next;
assert(sec);
}
app.viewer.latest_section_gone_to[Sec_Free_Slot] = idx;
viewer_jump_to(app, sec->range.start);
}
internal
void viewer_jump_to_other_root_obj(App_State &app, u64 obj_idx)
{
u64 n_other_root_objs = app.tfile_data.tkeys_data.n_other_root_obj;
if (n_other_root_objs == 0)
return;
obj_idx = (obj_idx + n_other_root_objs) % n_other_root_objs;
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_section_gone_to[Sec_Other] = obj_idx;
viewer_jump_to(app, info->section.range.start);
}
internal internal
void viewer_jump_to_cluster(App_State &app, u64 cluster_idx) void viewer_jump_to_cluster(App_State &app, u64 cluster_idx)
{ {
@ -284,6 +236,45 @@ void viewer_jump_to_cluster(App_State &app, u64 cluster_idx)
viewer_jump_to(app, page->range.start); viewer_jump_to(app, page->range.start);
} }
internal
void viewer_jump_to_page_list(App_State &app, u64 page_list_idx)
{
if (app.rndata.n_cluster_groups == 0)
return;
page_list_idx = (page_list_idx + app.rndata.n_cluster_groups) % app.rndata.n_cluster_groups;
Cluster_Group_Info &cg_info = app.rndata.cluster_groups[page_list_idx];
app.viewer.latest_section_gone_to[Sec_Page_List] = page_list_idx;
viewer_jump_to(app, cg_info.rng_page_list.start);
}
internal
void viewer_jump_to_section(App_State &app, Section_Id id, u64 sec_idx)
{
// special cases
if (id == Sec_Page_List) {
viewer_jump_to_page_list(app, sec_idx);
return;
}
const Sections &sections = app.tfile_data.sections[id];
if (sections.count == 0)
return;
Section *sec = sections.head;
assert(sec);
sec_idx = (sec_idx + sections.count) % sections.count;
for (u64 i = 0; i < sec_idx; ++i) {
sec = sec->next;
assert(sec);
}
viewer_jump_to(app, sec->range.start);
}
internal internal
void imgui_render_string_tree(Arena *arena, String8_Node *root, String8_Node *highlighted, u16 indent = 0) void imgui_render_string_tree(Arena *arena, String8_Node *root, String8_Node *highlighted, u16 indent = 0)
{ {
@ -381,7 +372,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
assert(app.base_display_addr < app.inspected_file.size); assert(app.base_display_addr < app.inspected_file.size);
void *content = app.inspected_file.mem + app.base_display_addr; void *content = app.inspected_file.mem + app.base_display_addr;
app.last_pinfo = &invalid_pinfo; app.last_pinfo = &invalid_pinfo;
app.last_other_root_obj = &invalid_other_root_obj_info; app.last_other_root_obj = &invalid_section;
app.viewer.mem_edit.DrawContents(content, content_size, app.base_display_addr); app.viewer.mem_edit.DrawContents(content, content_size, app.base_display_addr);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -391,19 +382,34 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
// ------------------------------- // -------------------------------
// Unique sections: just display a button that jumps to the start of it and show their size // Unique sections: just display a button that jumps to the start of it and show their size
for (u32 i = 0; i < Sec_COUNT; ++i) { for (u32 i = 1; i < Sec_COUNT; ++i) {
u32 sec_idx = 0; if (!app.tfile_data.sections[i].head)
for (Section *sec = app.tfile_data.sections[i].head; sec; sec = sec->next, ++sec_idx) { continue;
if (!sec->range.len) continue;
String8 sec_name = section_names[i]; // TODO: handle pages like other sections
String8 col_label = push_str8f(scratch.arena, "_%s", sec_name.c()); if (i == Sec_Page)
ImGui::ColorEdit3(col_label.c(), app.viewer.col_section[i], edit_flags); continue;
String8 sec_name = section_names[i];
String8 col_label = push_str8f(scratch.arena, "_%s", sec_name.c());
ImGui::ColorEdit3(col_label.c(), app.viewer.col_section[i], edit_flags);
ImGui::SameLine();
if (ImGui::Button(sec_name.c()))
viewer_jump_to_section(app, static_cast<Section_Id>(i), app.viewer.latest_section_gone_to[i]);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.sections[i].tot_size).c());
if (app.tfile_data.sections[i].count > 1) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(push_str8f(scratch.arena, "%s_%u", sec_name.c(), sec_idx).c())) i64 sec_to_go_to = app.viewer.latest_section_gone_to[i];
viewer_jump_to(app, sec->range.start); ImGui::PushItemWidth(80.f);
ImGui::SameLine(); if (ImGui::InputScalar(push_str8f(scratch.arena, "##%s_viewed", sec_name.c()).c(), ImGuiDataType_S64,
ImGui::Text("%s", to_pretty_size(scratch.arena, sec->range.len).c()); &sec_to_go_to, &step_i64, nullptr, "%u")
&& ImGui::IsItemDeactivatedAfterEdit())
{
viewer_jump_to_section(app, static_cast<Section_Id>(i), sec_to_go_to);
}
ImGui::PopItemWidth();
} }
} }
@ -446,62 +452,6 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Checksum")) {} // TODO jump to next checksum if (ImGui::Button("Checksum")) {} // TODO jump to next checksum
ImGui::ColorEdit3("_Page List", app.viewer.col_section[Sec_Page_List], edit_flags);
ImGui::SameLine();
if (ImGui::Button("Page List"))
viewer_jump_to_page_list(app, app.viewer.latest_section_gone_to[Sec_Page_List]);
ImGui::SameLine();
{
i64 page_list_to_go_to = app.viewer.latest_section_gone_to[Sec_Page_List];
ImGui::PushItemWidth(80.f);
if (ImGui::InputScalar("##page_list_viewed", ImGuiDataType_S64, &page_list_to_go_to, &step_i64, nullptr, "%u")
&& ImGui::IsItemDeactivatedAfterEdit())
{
viewer_jump_to_page_list(app, page_list_to_go_to);
}
ImGui::PopItemWidth();
}
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c());
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("Other"))
viewer_jump_to_other_root_obj(app, app.viewer.latest_section_gone_to[Sec_Other]);
ImGui::SameLine();
{
i64 other_root_obj_to_go_to = app.viewer.latest_section_gone_to[Sec_Other];
ImGui::PushItemWidth(80.f);
if (ImGui::InputScalar("##other_root_objviewed", ImGuiDataType_S64, &other_root_obj_to_go_to, &step_i64, nullptr, "%u")
&& ImGui::IsItemDeactivatedAfterEdit())
{
viewer_jump_to_other_root_obj(app, other_root_obj_to_go_to);
}
ImGui::PopItemWidth();
}
}
if (app.tfile_data.sections[Sec_Free_Slot].count) {
ImGui::ColorEdit3("_Free Slot", app.viewer.col_section[Sec_Free_Slot], edit_flags);
ImGui::SameLine();
if (ImGui::Button("Free Slot"))
viewer_jump_to_free_slot(app, app.viewer.latest_section_gone_to[Sec_Free_Slot]);
ImGui::SameLine();
{
i64 free_slot_to_go_to = app.viewer.latest_section_gone_to[Sec_Free_Slot];
ImGui::PushItemWidth(80.f);
if (ImGui::InputScalar("##free_slot_viewed", ImGuiDataType_S64, &free_slot_to_go_to, &step_i64, nullptr, "%u")
&& ImGui::IsItemDeactivatedAfterEdit())
{
viewer_jump_to_free_slot(app, free_slot_to_go_to);
}
ImGui::PopItemWidth();
}
}
// Misc information // Misc information
// ------------------------------- // -------------------------------
ImGui::Separator(); ImGui::Separator();

View file

@ -141,7 +141,7 @@ String8 render_range_bytes_to_string(Arena *arena, App_State &app, Term_Viewer &
// We need to properly initialize this before calling mem_edit_bg_color_fn! // We need to properly initialize this before calling mem_edit_bg_color_fn!
app.last_pinfo = &invalid_pinfo; app.last_pinfo = &invalid_pinfo;
app.last_other_root_obj = &invalid_other_root_obj_info; app.last_other_root_obj = &invalid_section;
const u8 *data = app.inspected_file.mem; const u8 *data = app.inspected_file.mem;
assert(range.start <= max_addr); assert(range.start <= max_addr);

View file

@ -8,6 +8,17 @@ Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id)
return sec; return sec;
} }
internal
void compute_tot_sections_size(Sections *sections)
{
for (u64 i = 0; i < Sec_COUNT; ++i) {
u64 tot_size = 0;
for (Section *sec = sections[i].head; sec; sec = sec->next)
tot_size += sec->range.len;
sections[i].tot_size = tot_size;
}
}
internal internal
b8 rntuple_is_old_version(const ROOT::RNTuple &ntuple) b8 rntuple_is_old_version(const ROOT::RNTuple &ntuple)
{ {
@ -475,7 +486,6 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
{ {
// These are supposed to never be null. If they are invalid, they must be set to `&invalid_pinfo` etc. // These are supposed to never be null. If they are invalid, they must be set to `&invalid_pinfo` etc.
assert(app.last_pinfo); assert(app.last_pinfo);
assert(app.last_other_root_obj);
const RNTuple_Data &rdata = app.rndata; const RNTuple_Data &rdata = app.rndata;
@ -491,8 +501,6 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
u64 rblob_sz = app.tfile_data.sections[Sec_Page].head->pre_size; u64 rblob_sz = app.tfile_data.sections[Sec_Page].head->pre_size;
const TKeys_Data &tdata = app.tfile_data.tkeys_data;
/// Page fast lookup (relative to app.last_pinfo) /// Page fast lookup (relative to app.last_pinfo)
{ {
// fast case: `off` is in the same page info as previous `off`. // fast case: `off` is in the same page info as previous `off`.
@ -567,10 +575,10 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
} }
// Copypasted from the fast page lookup // Copypasted from the fast page lookup
if (tdata.n_other_root_obj > 0) { if (app.tfile_data.sections[Sec_Other].count > 0) {
// fast case: `off` is in the same page info as previous `off`. // fast case: `off` is in the same obj as previous `off`.
for (i32 i = 0; i < 2; ++i) { for (i32 i = 0; i < 2; ++i) {
const Section &other_sec = app.last_other_root_obj->section; const Section &other_sec = *app.last_other_root_obj;
if (other_sec.range.start - other_sec.pre_size < off && off < other_sec.range.end()) { if (other_sec.range.start - other_sec.pre_size < off && off < other_sec.range.end()) {
return other_sec; return other_sec;
} }
@ -582,10 +590,10 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
} }
// Slow linear lookup, ideally only done once per render when last_other_root_obj is invalid. // Slow linear lookup, ideally only done once per render when last_other_root_obj is invalid.
for (Other_Root_Obj_Info *other = tdata.other_root_obj; other; other = other->next) { for (Section *other_sec = app.tfile_data.sections[Sec_Other].head; other_sec; other_sec = other_sec->next) {
if (other->section.range.start - other->section.pre_size <= off && off < other->section.range.end()) { if (other_sec->range.start - other_sec->pre_size <= off && off < other_sec->range.end()) {
app.last_other_root_obj = other; app.last_other_root_obj = other_sec;
return other->section; return *other_sec;
} }
} }
} }

View file

@ -3,12 +3,6 @@ struct Byte_Range {
inline u64 end() const { return start + len; } inline u64 end() const { return start + len; }
}; };
// Used to store location information about stuff like checksums, page lists, etc
struct Range_Seq {
Range_Seq *next;
Byte_Range range;
};
struct Page_Info_Node { struct Page_Info_Node {
Page_Info_Node *next; Page_Info_Node *next;
Page_Info_Node *prev; Page_Info_Node *prev;
@ -32,11 +26,16 @@ struct Page_Info_Node {
static const Page_Info_Node invalid_pinfo {}; static const Page_Info_Node invalid_pinfo {};
// A page group is a grouping of a fixed number of page infos, whose range is equal to the combined ranges
// of its components. It is an acceleration structure used to more quickly find the correct page info
// that an offset belongs to.
struct Page_Info_Group { struct Page_Info_Group {
Byte_Range range; Byte_Range range;
Page_Info_Node *first; Page_Info_Node *first;
}; };
// A page chunk is a grouping of adjacent pages, used to quickly determine if an offset is part
// of a page or not.
struct Page_Info_Chunk { struct Page_Info_Chunk {
Page_Info_Chunk *next; Page_Info_Chunk *next;
Byte_Range range; Byte_Range range;
@ -62,11 +61,11 @@ enum Section_Id {
Sec_TFile_Info, Sec_TFile_Info,
Sec_TFile_FreeList, Sec_TFile_FreeList,
Sec_TKey_List, Sec_TKey_List,
Sec_RNTuple_Anchor,
Sec_RNTuple_Header, Sec_RNTuple_Header,
Sec_RNTuple_Footer, Sec_RNTuple_Footer,
Sec_Page_List, Sec_Page_List,
Sec_Page, Sec_Page,
Sec_RNTuple_Anchor,
Sec_Free_Slot, Sec_Free_Slot,
// any other object stored in a TKey // any other object stored in a TKey
Sec_Other, Sec_Other,
@ -84,9 +83,13 @@ struct Section {
b8 highlighted; b8 highlighted;
// Optional pointer to the specific information for the section. // Optional pointer to the specific information for the section.
// e.g. if the section is a Page this points to the relative Page_Info_Node // Here are the actual types:
// - Sec_RNTuple_Anchor => ROOT::RNTuple
// - Sec_Page => Page_Info_Node (aliased from RNTuple_Data::pages)
// - Sec_Other => String8 (the class name of the object)
const void *info; const void *info;
}; };
static const Section invalid_section {};
// @Volatile with Section_Id // @Volatile with Section_Id
internal const String8 section_names[] = { internal const String8 section_names[] = {
@ -96,11 +99,11 @@ internal const String8 section_names[] = {
str8("TFile Streamer Info"), str8("TFile Streamer Info"),
str8("TFile FreeList"), str8("TFile FreeList"),
str8("TKey List"), str8("TKey List"),
str8("RNTuple Anchor"),
str8("RNTuple Header"), str8("RNTuple Header"),
str8("RNTuple Footer"), str8("RNTuple Footer"),
str8("Page List"), str8("Page List"),
str8("Page"), str8("Page"),
str8("RNTuple Anchor"),
str8("Free Slot"), str8("Free Slot"),
str8("Other"), str8("Other"),
}; };
@ -117,24 +120,15 @@ struct RNTuple_Anchor_Info {
u64 offset_in_file; u64 offset_in_file;
}; };
struct Other_Root_Obj_Info {
Other_Root_Obj_Info *next;
String8 class_name;
Section section;
};
static const Other_Root_Obj_Info invalid_other_root_obj_info {};
struct Sections { struct Sections {
Section *head, *tail; Section *head, *tail;
u32 count; u32 count;
u64 tot_size;
}; };
struct TKeys_Data { struct TKeys_Data {
RNTuple_Anchor_Info *rntuples; RNTuple_Anchor_Info *rntuples;
Byte_Range_Node *rblob_keys; Byte_Range_Node *rblob_keys;
Other_Root_Obj_Info *other_root_obj;
u64 n_other_root_obj;
}; };
struct TFile_Data { struct TFile_Data {

View file

@ -176,6 +176,8 @@ int main(int argc, char **argv)
// else if (success) // else if (success)
app.rndata = get_rntuple_data(arena, app.inspected_file, app.tfile_data, args.extended_info); app.rndata = get_rntuple_data(arena, app.inspected_file, app.tfile_data, args.extended_info);
compute_tot_sections_size(app.tfile_data.sections);
if (args.print_to_terminal) { if (args.print_to_terminal) {
u64 nbytes_displayed = args.nbytes_displayed; u64 nbytes_displayed = args.nbytes_displayed;
if (!nbytes_displayed) if (!nbytes_displayed)

View file

@ -201,7 +201,6 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
cur = pre + tfile_obj_nbytes; cur = pre + tfile_obj_nbytes;
RNTuple_Anchor_Info *rntuple_info_tail = nullptr; RNTuple_Anchor_Info *rntuple_info_tail = nullptr;
Other_Root_Obj_Info *other_root_obj_tail = nullptr;
Sections *sections = tfile_data.sections; Sections *sections = tfile_data.sections;
@ -322,17 +321,14 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
tkeys_data.rblob_keys = rblob_key; tkeys_data.rblob_keys = rblob_key;
} else if (flags & WTK_COLLECT_OTHER_ROOT_OBJS) { } else if (flags & WTK_COLLECT_OTHER_ROOT_OBJS) {
Other_Root_Obj_Info *oth_info = arena_push<Other_Root_Obj_Info>(arena); Section *sec_other = push_section(arena, tfile_data, Sec_Other);
if (cname_len) { String8 *class_name = arena_push<String8>(arena);
oth_info->class_name = str8_from_buf(arena, data + cname_off + 1, cname_len); sec_other->info = class_name;
} if (cname_len)
oth_info->section.id = Sec_Other; *class_name = str8_from_buf(arena, data + cname_off + 1, cname_len);
oth_info->section.info = oth_info; sec_other->range.start = cur + keylen;
oth_info->section.range.start = cur + keylen; sec_other->range.len = n_bytes - keylen;
oth_info->section.range.len = n_bytes - keylen; sec_other->pre_size = keylen;
oth_info->section.pre_size = keylen;
push_to_sll(tkeys_data.other_root_obj, other_root_obj_tail, oth_info);
tkeys_data.n_other_root_obj++;
} }
} }
cur += n_bytes; cur += n_bytes;