some more refactoring
This commit is contained in:
parent
8c285b977c
commit
299ee4e695
8 changed files with 111 additions and 162 deletions
|
@ -36,7 +36,7 @@ struct App_State {
|
|||
|
||||
// Cache the last info node selected for faster lookup of offsets
|
||||
const Page_Info_Node *last_pinfo;
|
||||
const Other_Root_Obj_Info *last_other_root_obj;
|
||||
const Section *last_other_root_obj;
|
||||
};
|
||||
|
||||
internal
|
||||
|
|
|
@ -901,7 +901,6 @@ struct Sec_Hover_Fn {
|
|||
u32 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
// FIXME: this is not correct in all cases
|
||||
while (cur_field_off < section.range.end()) {
|
||||
titled_section("Free Slot", [this, is_big] {
|
||||
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()
|
||||
{
|
||||
Other_Root_Obj_Info *info = (Other_Root_Obj_Info *)section.info;
|
||||
String8 name = (info && info->class_name.size) ? info->class_name : str8("(Unknown)");
|
||||
String8 *class_name = (String8 *)section.info;
|
||||
String8 name = class_name->size ? *class_name : str8("(Unknown)");
|
||||
titled_section(name.c(), [this] {
|
||||
tkey();
|
||||
range("Payload", section.range.len - section.post_size);
|
||||
|
|
182
src/render.cpp
182
src/render.cpp
|
@ -220,54 +220,6 @@ Page_Info_Node *viewer_jump_to_page(App_State &app, u64 page_idx)
|
|||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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 §ions = 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
|
||||
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);
|
||||
void *content = app.inspected_file.mem + app.base_display_addr;
|
||||
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);
|
||||
|
||||
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
|
||||
for (u32 i = 0; i < Sec_COUNT; ++i) {
|
||||
u32 sec_idx = 0;
|
||||
for (Section *sec = app.tfile_data.sections[i].head; sec; sec = sec->next, ++sec_idx) {
|
||||
if (!sec->range.len) continue;
|
||||
for (u32 i = 1; i < Sec_COUNT; ++i) {
|
||||
if (!app.tfile_data.sections[i].head)
|
||||
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);
|
||||
// TODO: handle pages like other sections
|
||||
if (i == Sec_Page)
|
||||
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();
|
||||
if (ImGui::Button(push_str8f(scratch.arena, "%s_%u", sec_name.c(), sec_idx).c()))
|
||||
viewer_jump_to(app, sec->range.start);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", to_pretty_size(scratch.arena, sec->range.len).c());
|
||||
i64 sec_to_go_to = app.viewer.latest_section_gone_to[i];
|
||||
ImGui::PushItemWidth(80.f);
|
||||
if (ImGui::InputScalar(push_str8f(scratch.arena, "##%s_viewed", sec_name.c()).c(), ImGuiDataType_S64,
|
||||
&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();
|
||||
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
|
||||
// -------------------------------
|
||||
ImGui::Separator();
|
||||
|
|
|
@ -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!
|
||||
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;
|
||||
assert(range.start <= max_addr);
|
||||
|
|
|
@ -8,6 +8,17 @@ Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id)
|
|||
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
|
||||
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.
|
||||
assert(app.last_pinfo);
|
||||
assert(app.last_other_root_obj);
|
||||
|
||||
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;
|
||||
|
||||
const TKeys_Data &tdata = app.tfile_data.tkeys_data;
|
||||
|
||||
/// Page fast lookup (relative to app.last_pinfo)
|
||||
{
|
||||
// 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
|
||||
if (tdata.n_other_root_obj > 0) {
|
||||
// fast case: `off` is in the same page info as previous `off`.
|
||||
if (app.tfile_data.sections[Sec_Other].count > 0) {
|
||||
// fast case: `off` is in the same obj as previous `off`.
|
||||
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()) {
|
||||
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.
|
||||
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()) {
|
||||
app.last_other_root_obj = other;
|
||||
return other->section;
|
||||
for (Section *other_sec = app.tfile_data.sections[Sec_Other].head; other_sec; other_sec = other_sec->next) {
|
||||
if (other_sec->range.start - other_sec->pre_size <= off && off < other_sec->range.end()) {
|
||||
app.last_other_root_obj = other_sec;
|
||||
return *other_sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,6 @@ struct Byte_Range {
|
|||
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 {
|
||||
Page_Info_Node *next;
|
||||
Page_Info_Node *prev;
|
||||
|
@ -32,11 +26,16 @@ struct Page_Info_Node {
|
|||
|
||||
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 {
|
||||
Byte_Range range;
|
||||
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 {
|
||||
Page_Info_Chunk *next;
|
||||
Byte_Range range;
|
||||
|
@ -62,11 +61,11 @@ enum Section_Id {
|
|||
Sec_TFile_Info,
|
||||
Sec_TFile_FreeList,
|
||||
Sec_TKey_List,
|
||||
Sec_RNTuple_Anchor,
|
||||
Sec_RNTuple_Header,
|
||||
Sec_RNTuple_Footer,
|
||||
Sec_Page_List,
|
||||
Sec_Page,
|
||||
Sec_RNTuple_Anchor,
|
||||
Sec_Free_Slot,
|
||||
// any other object stored in a TKey
|
||||
Sec_Other,
|
||||
|
@ -84,9 +83,13 @@ struct Section {
|
|||
b8 highlighted;
|
||||
|
||||
// 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;
|
||||
};
|
||||
static const Section invalid_section {};
|
||||
|
||||
// @Volatile with Section_Id
|
||||
internal const String8 section_names[] = {
|
||||
|
@ -96,11 +99,11 @@ internal const String8 section_names[] = {
|
|||
str8("TFile Streamer Info"),
|
||||
str8("TFile FreeList"),
|
||||
str8("TKey List"),
|
||||
str8("RNTuple Anchor"),
|
||||
str8("RNTuple Header"),
|
||||
str8("RNTuple Footer"),
|
||||
str8("Page List"),
|
||||
str8("Page"),
|
||||
str8("RNTuple Anchor"),
|
||||
str8("Free Slot"),
|
||||
str8("Other"),
|
||||
};
|
||||
|
@ -117,24 +120,15 @@ struct RNTuple_Anchor_Info {
|
|||
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 {
|
||||
Section *head, *tail;
|
||||
u32 count;
|
||||
u64 tot_size;
|
||||
};
|
||||
|
||||
struct TKeys_Data {
|
||||
RNTuple_Anchor_Info *rntuples;
|
||||
Byte_Range_Node *rblob_keys;
|
||||
|
||||
Other_Root_Obj_Info *other_root_obj;
|
||||
u64 n_other_root_obj;
|
||||
};
|
||||
|
||||
struct TFile_Data {
|
||||
|
|
|
@ -176,6 +176,8 @@ int main(int argc, char **argv)
|
|||
// else if (success)
|
||||
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) {
|
||||
u64 nbytes_displayed = args.nbytes_displayed;
|
||||
if (!nbytes_displayed)
|
||||
|
|
|
@ -201,7 +201,6 @@ 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;
|
||||
Other_Root_Obj_Info *other_root_obj_tail = nullptr;
|
||||
|
||||
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;
|
||||
|
||||
} else if (flags & WTK_COLLECT_OTHER_ROOT_OBJS) {
|
||||
Other_Root_Obj_Info *oth_info = arena_push<Other_Root_Obj_Info>(arena);
|
||||
if (cname_len) {
|
||||
oth_info->class_name = str8_from_buf(arena, data + cname_off + 1, cname_len);
|
||||
}
|
||||
oth_info->section.id = Sec_Other;
|
||||
oth_info->section.info = oth_info;
|
||||
oth_info->section.range.start = cur + keylen;
|
||||
oth_info->section.range.len = n_bytes - 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++;
|
||||
Section *sec_other = push_section(arena, tfile_data, Sec_Other);
|
||||
String8 *class_name = arena_push<String8>(arena);
|
||||
sec_other->info = class_name;
|
||||
if (cname_len)
|
||||
*class_name = str8_from_buf(arena, data + cname_off + 1, cname_len);
|
||||
sec_other->range.start = cur + keylen;
|
||||
sec_other->range.len = n_bytes - keylen;
|
||||
sec_other->pre_size = keylen;
|
||||
}
|
||||
}
|
||||
cur += n_bytes;
|
||||
|
|
Loading…
Add table
Reference in a new issue