improve terminal output, add extended info
This commit is contained in:
parent
d4bd3bbc8a
commit
d1548a467b
6 changed files with 115 additions and 96 deletions
|
@ -4,11 +4,12 @@ void print_help(const char *argv0)
|
|||
fprintf(stderr,
|
||||
"rntviewer v" V_MAJOR "." V_MINOR " by silverweed"
|
||||
"\n"
|
||||
"\nUsage: %s [-t] [-s START] [-l LEN] [-w WIDTH] <ntuple_name> <ntuple_file.root>"
|
||||
"\nUsage: %s [-t] [-s START] [-l LEN] [-w WIDTH] [-e] <ntuple_name> <ntuple_file.root>"
|
||||
"\n\t-t: no graphics, output to terminal"
|
||||
"\n\t-s: set first displayed byte to START"
|
||||
"\n\t-l: display LEN bytes (only in terminal mode)"
|
||||
"\n\t-w: display WIDTH bytes per column"
|
||||
"\n\t-e: display some extended info (may slow down the startup)"
|
||||
"\n"
|
||||
, argv0);
|
||||
}
|
||||
|
@ -19,6 +20,7 @@ struct Cmdline_Args {
|
|||
u64 start_addr;
|
||||
u64 nbytes_displayed;
|
||||
u16 n_cols;
|
||||
b8 extended_info;
|
||||
|
||||
String8 ntpl_name;
|
||||
String8 file_name;
|
||||
|
@ -95,15 +97,17 @@ Cmdline_Args parse_args(i32 argc, char **argv)
|
|||
// TODO: refactor this probably
|
||||
for (i32 i = 1; i < argc; ++i) {
|
||||
String8 arg = str8_from_c(argv[i]);
|
||||
if (arg.str[0] == '-') {
|
||||
if (arg[0] == '-') {
|
||||
if (arg.size == 2) {
|
||||
if (arg.str[1] == 't')
|
||||
if (arg[1] == 't')
|
||||
args.print_to_terminal = true;
|
||||
else if (arg.str[1] == 's')
|
||||
else if (arg[1] == 'e')
|
||||
args.extended_info = true;
|
||||
else if (arg[1] == 's')
|
||||
parse_int_arg(i, argc, argv, args.start_addr);
|
||||
else if (arg.str[1] == 'l')
|
||||
else if (arg[1] == 'l')
|
||||
parse_int_arg(i, argc, argv, args.nbytes_displayed);
|
||||
else if (arg.str[1] == 'w') {
|
||||
else if (arg[1] == 'w') {
|
||||
u64 n_cols = 0;
|
||||
parse_int_arg(i, argc, argv, n_cols);
|
||||
args.n_cols = (u16)n_cols;
|
||||
|
|
|
@ -336,7 +336,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
|
|||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_size).c());
|
||||
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_comp_size).c());
|
||||
|
||||
ImGui::ColorEdit3("_Checksum", app.viewer.col_checksum, flags);
|
||||
ImGui::SameLine();
|
||||
|
@ -368,6 +368,11 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
|
|||
ImGui::Text("TFile compression: %u", app.tfile_data.compression);
|
||||
ImGui::Text("Num pages: %lu", app.rndata.n_pages);
|
||||
ImGui::Text("Num elements: %lu", app.rndata.n_elems);
|
||||
if (app.rndata.tot_page_uncomp_size) {
|
||||
ImGui::Text("Pages uncompressed size: %s (comp.ratio = %.3f)",
|
||||
to_pretty_size(scratch.arena, app.rndata.tot_page_uncomp_size).c(),
|
||||
(f32)app.rndata.tot_page_comp_size / app.rndata.tot_page_uncomp_size);
|
||||
}
|
||||
|
||||
{
|
||||
const i64 step_fast_i64 = app.rndata.n_clusters / 100;
|
||||
|
|
|
@ -34,92 +34,67 @@ Ansi_Color ansi_color_for_offset(u64 off, App_State &app, const Term_Viewer &vie
|
|||
}
|
||||
|
||||
internal
|
||||
String8 render_legend_to_string(Arena *arena, const Term_Viewer &viewer, const App_State &app)
|
||||
String8_Node *render_legend_to_string(Arena *arena, const Term_Viewer &viewer, const App_State &app, String8_Node *prev)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
defer { scratch_end(scratch); };
|
||||
|
||||
String8_Node *head = nullptr, *tail = nullptr;
|
||||
String8 color_none = ansi_color_table[ACol_None];
|
||||
u64 tot_len = 0;
|
||||
for (u64 section = 1; section < Sec_COUNT; ++section) {
|
||||
Ansi_Color color = viewer.col_section[section];
|
||||
String8 color_str = ansi_color_table[color];
|
||||
String8 sec_name = section_names[section];
|
||||
Byte_Range range = get_section_range(app, static_cast<Section_Id>(section));
|
||||
String8 s;
|
||||
if (range.len)
|
||||
s = push_str8f(scratch.arena, "%s%20s %s0x%lX - 0x%lX [%s]\n",
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s0x%lX - 0x%lX [%s]\n",
|
||||
color_str.c(), sec_name.c(), color_none.c(),
|
||||
range.start, range.end(), to_pretty_size(scratch.arena, range.len).c());
|
||||
range.start, range.end(), to_pretty_size(arena, range.len).c());
|
||||
else if (section == Sec_Page)
|
||||
s = push_str8f(scratch.arena, "%s%20s %s(%lu) [%s] \n",
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s(%lu) [%s] \n",
|
||||
color_str.c(), sec_name.c(), color_none.c(), app.rndata.n_pages,
|
||||
to_pretty_size(scratch.arena, app.rndata.tot_page_size).c());
|
||||
to_pretty_size(arena, app.rndata.tot_page_comp_size).c());
|
||||
else if (section == Sec_Page_List)
|
||||
s = push_str8f(scratch.arena, "%s%20s %s(%lu) [%s]\n",
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s(%lu) [%s]\n",
|
||||
color_str.c(), sec_name.c(), color_none.c(), app.rndata.n_cluster_groups,
|
||||
to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c());
|
||||
String8_Node *node = arena_push<String8_Node>(scratch.arena);
|
||||
node->str = s;
|
||||
if (!tail) {
|
||||
head = node;
|
||||
} else {
|
||||
tail->next = node;
|
||||
to_pretty_size(arena, app.rndata.tot_page_list_size).c());
|
||||
if (!head) {
|
||||
head = tail;
|
||||
if (prev)
|
||||
prev->next = head;
|
||||
}
|
||||
tail = node;
|
||||
tot_len += s.size;
|
||||
}
|
||||
|
||||
{
|
||||
String8_Node *node = arena_push<String8_Node>(scratch.arena);
|
||||
node->str = push_str8f(scratch.arena, "%s%20s %s\n", ansi_color_table[viewer.col_checksum].c(), "Checksum", color_none);
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
tot_len += node->str.size;
|
||||
}
|
||||
{
|
||||
String8_Node *node = arena_push<String8_Node>(scratch.arena);
|
||||
node->str = push_str8f(scratch.arena, "%s%20s %s\n", ansi_color_table[viewer.col_page_start].c(), "Page Start", color_none);
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
tot_len += node->str.size;
|
||||
}
|
||||
{
|
||||
String8_Node *node = arena_push<String8_Node>(scratch.arena);
|
||||
node->str = push_str8f(scratch.arena, "%s%20s %s\n", ansi_color_table[viewer.col_key].c(), "TKey Header", color_none);
|
||||
tail->next = node;
|
||||
tail = node;
|
||||
tot_len += node->str.size;
|
||||
}
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s\n", ansi_color_table[viewer.col_checksum].c(), "Checksum", color_none);
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s\n", ansi_color_table[viewer.col_page_start].c(), "Page Start", color_none);
|
||||
tail = push_str8_node(arena, tail, "%s%20s %s\n", ansi_color_table[viewer.col_key].c(), "TKey Header", color_none);
|
||||
|
||||
String8 legend { arena_push_array_nozero<u8>(arena, tot_len + 1), tot_len + 1 };
|
||||
legend.str[tot_len] = 0;
|
||||
u64 cur_size = 0;
|
||||
|
||||
for (String8_Node *node = head; node; node = node->next) {
|
||||
memcpy(legend.str + cur_size, node->str.str, node->str.size);
|
||||
cur_size += node->str.size;
|
||||
}
|
||||
|
||||
return legend;
|
||||
return tail;
|
||||
}
|
||||
|
||||
internal
|
||||
String8 render_range_to_string(Arena *arena, App_State &app, u64 len, u64 n_cols)
|
||||
String8_Node *render_info_to_string(Arena *arena, const App_State &app, String8_Node *prev)
|
||||
{
|
||||
Term_Viewer viewer = make_term_viewer();
|
||||
String8_Node *res = push_str8_node(arena, prev,
|
||||
"\n"
|
||||
" ROOT version: %u.%u.%u\n"
|
||||
" TFile compression: %u\n"
|
||||
" Num pages: %lu\n"
|
||||
" Num elements: %lu\n",
|
||||
app.tfile_data.root_version_major, app.tfile_data.root_version_minor, app.tfile_data.root_version_patch,
|
||||
app.tfile_data.compression,
|
||||
app.rndata.n_pages,
|
||||
app.rndata.n_elems);
|
||||
|
||||
String8 legend = render_legend_to_string(arena, viewer, app);
|
||||
if (app.rndata.tot_page_uncomp_size) {
|
||||
res = push_str8_node(arena, res, " Pages uncompressed size: %s (comp.ratio = %.3f)\n",
|
||||
to_pretty_size(arena, app.rndata.tot_page_uncomp_size).c(),
|
||||
(f32)app.rndata.tot_page_comp_size / app.rndata.tot_page_uncomp_size);
|
||||
}
|
||||
|
||||
// scratch must be created after `render_legend_to_string`
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
defer { scratch_end(scratch); };
|
||||
|
||||
String8 ntpl_desc = rntuple_description(scratch.arena, app.rndata);
|
||||
String8 header_str = push_str8f(scratch.arena, "RNTuple '%s' (%s) from file \"%s\"",
|
||||
app.ntpl_name.c(), ntpl_desc.c(), app.inspected_file.name.c());
|
||||
return res;
|
||||
}
|
||||
|
||||
internal
|
||||
String8 render_range_bytes_to_string(Arena *arena, Arena *scratch_arena, App_State &app, Term_Viewer &viewer, u64 len, u64 n_cols)
|
||||
{
|
||||
if (n_cols == 0)
|
||||
n_cols = 32;
|
||||
u64 n_lines = len / n_cols;
|
||||
|
@ -132,19 +107,15 @@ String8 render_range_to_string(Arena *arena, App_State &app, u64 len, u64 n_cols
|
|||
u64 max_addr_len = 1 + ceilf(logf(max_addr + 1) * RECP_LOG_16);
|
||||
const u64 n_spaces_after_line_addr = 3;
|
||||
u64 line_addr_size = (max_addr_len + n_spaces_after_line_addr) * n_lines;
|
||||
String8 line_addr_fmt = push_str8f(scratch.arena, "%%0%dlX:", max_addr_len - 1);
|
||||
String8 line_addr_fmt = push_str8f(scratch_arena, "%%0%dlX:", max_addr_len - 1);
|
||||
|
||||
// NOTE: +3 because we need 2 chars for each byte + 1 whitespace.
|
||||
u64 buf_size = (ACOL_MAX_LEN + 3) * len;
|
||||
u64 buf_size = (ACOL_MAX_LEN + 3) * len; // at most one color per byte
|
||||
buf_size += n_lines; // one newline per line
|
||||
buf_size += n_lines * ACOL_MAX_LEN; // reset color every line
|
||||
buf_size += line_addr_size;
|
||||
buf_size += line_addr_size; // address column
|
||||
buf_size += 1; // initial newline
|
||||
buf_size += header_str.size;
|
||||
buf_size += 2; // two newlines after header
|
||||
buf_size += 2; // two newlines before legend
|
||||
buf_size += legend.size;
|
||||
buf_size += 1; // trailing zero
|
||||
buf_size += 3; // final newlines + trailing zero
|
||||
char *buf = arena_push_array_nozero<char>(arena, buf_size);
|
||||
buf[len] = 0;
|
||||
|
||||
|
@ -160,12 +131,6 @@ String8 render_range_to_string(Arena *arena, App_State &app, u64 len, u64 n_cols
|
|||
char *cur = buf;
|
||||
*cur++ = '\n';
|
||||
|
||||
// header
|
||||
memcpy(cur, header_str.str, header_str.size);
|
||||
cur += header_str.size;
|
||||
*cur++ = '\n';
|
||||
*cur++ = '\n';
|
||||
|
||||
// first line addr
|
||||
cur += sprintf(cur, line_addr_fmt.c(), start);
|
||||
for (u32 i = 0; i < n_spaces_after_line_addr; ++i)
|
||||
|
@ -200,11 +165,36 @@ String8 render_range_to_string(Arena *arena, App_State &app, u64 len, u64 n_cols
|
|||
|
||||
*cur++ = '\n';
|
||||
*cur++ = '\n';
|
||||
memcpy(cur, legend.str, legend.size);
|
||||
cur += legend.size;
|
||||
u64 real_buf_size = cur - buf;
|
||||
assert(real_buf_size <= buf_size);
|
||||
*cur = 0;
|
||||
|
||||
*cur++ = 0;
|
||||
u64 len_used = (u64)(cur - buf);
|
||||
|
||||
return { (u8 *)buf, len_used };
|
||||
return { (u8 *)buf, real_buf_size };
|
||||
}
|
||||
|
||||
internal
|
||||
String8_Node *render_range_to_string(Arena *arena, App_State &app, u64 len, u64 n_cols)
|
||||
{
|
||||
Term_Viewer viewer = make_term_viewer();
|
||||
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
defer { scratch_end(scratch); };
|
||||
|
||||
// Header
|
||||
String8 ntpl_desc = rntuple_description(scratch.arena, app.rndata);
|
||||
String8_Node *result = push_str8_node(arena, nullptr, "RNTuple '%s' (%s) from file \"%s\"\n",
|
||||
app.ntpl_name.c(), ntpl_desc.c(), app.inspected_file.name.c());
|
||||
String8_Node *result_tail = result;
|
||||
|
||||
// Bytes view
|
||||
String8_Node *bytes_view = arena_push<String8_Node>(arena);
|
||||
bytes_view->str = render_range_bytes_to_string(arena, scratch.arena, app, viewer, len, n_cols);
|
||||
result_tail->next = bytes_view;
|
||||
result_tail = bytes_view;
|
||||
|
||||
// Footer
|
||||
result_tail = render_legend_to_string(arena, viewer, app, result_tail);
|
||||
result_tail = render_info_to_string(arena, app, result_tail);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ void gather_ntuple_metadata(Arena *arena, RMicroFileReader &reader, const RNTupl
|
|||
|
||||
u64 n_pages = 0;
|
||||
u64 n_elems = 0;
|
||||
u64 tot_page_size = 0;
|
||||
u64 tot_page_comp_size = 0;
|
||||
Page_Info_Node *pinfo_head = nullptr, *pinfo_tail = nullptr;
|
||||
Page_Info_Node *last_inserted_pinfo = nullptr;
|
||||
|
||||
|
@ -186,7 +186,7 @@ void gather_ntuple_metadata(Arena *arena, RMicroFileReader &reader, const RNTupl
|
|||
last_inserted_pinfo = pinfo;
|
||||
|
||||
++n_pages;
|
||||
tot_page_size += pinfo->range.len;
|
||||
tot_page_comp_size += pinfo->range.len;
|
||||
n_elems += page_info.fNElements;
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ void gather_ntuple_metadata(Arena *arena, RMicroFileReader &reader, const RNTupl
|
|||
rndata.n_page_chunks = n_chunks;
|
||||
rndata.n_pages = n_pages;
|
||||
rndata.n_elems = n_elems;
|
||||
rndata.tot_page_size = tot_page_size;
|
||||
rndata.tot_page_comp_size = tot_page_comp_size;
|
||||
rndata.cluster_groups = cluster_groups;
|
||||
rndata.n_cluster_groups = cg_idx;
|
||||
rndata.tot_page_list_size = tot_page_list_size;
|
||||
|
@ -346,7 +346,20 @@ TFile_Data get_tfile_data(const Inspected_File &file, String8 ntpl_name)
|
|||
}
|
||||
|
||||
internal
|
||||
RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, String8 ntpl_name)
|
||||
u64 calc_page_uncomp_size(const u8 *fmem, const Page_Info_Node *page_head)
|
||||
{
|
||||
TIMED_SCOPE();
|
||||
u64 tot_size = 0;
|
||||
for (const Page_Info_Node *pinfo = page_head; pinfo; pinfo = pinfo->next) {
|
||||
const u8 *src = fmem + pinfo->range.start;
|
||||
u32 uncomp_size = src[6] | (src[7] << 8) | (src[8] << 16);
|
||||
tot_size += uncomp_size;
|
||||
}
|
||||
return tot_size;
|
||||
}
|
||||
|
||||
internal
|
||||
RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, String8 ntpl_name, b8 extended_info)
|
||||
{
|
||||
RNTuple_Data rndata {};
|
||||
|
||||
|
@ -371,6 +384,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, String8
|
|||
rndata.rng_tkeys_list.len = file_info.tkeys_list_nbytes;
|
||||
|
||||
gather_ntuple_metadata(arena, file_reader, file_info, rndata);
|
||||
if (extended_info)
|
||||
rndata.tot_page_uncomp_size = calc_page_uncomp_size(file.mem, rndata.pages);
|
||||
}
|
||||
|
||||
return rndata;
|
||||
|
@ -613,6 +628,7 @@ String8_Node *display_val_rootzip(Arena *arena, String8_Node *prev, const char *
|
|||
sn = push_str8_node_child(arena, sn, "Zip method: %s", zip_method.c());
|
||||
sn = push_str8_node(arena, sn, "Compressed size: %s", to_pretty_size(arena, comp_size).c());
|
||||
sn = push_str8_node(arena, sn, "Uncompressed size: %s", to_pretty_size(arena, uncomp_size).c());
|
||||
sn = push_str8_node(arena, sn, "Comp. ratio: %.2f", (f32)comp_size / uncomp_size);
|
||||
|
||||
return sn;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ struct RNTuple_Data {
|
|||
u64 n_pages;
|
||||
// total number of elements of all pages
|
||||
u64 n_elems;
|
||||
u64 tot_page_size;
|
||||
u64 tot_page_comp_size;
|
||||
u64 tot_page_uncomp_size;
|
||||
|
||||
// TODO
|
||||
Range_Seq *checksums;
|
||||
|
|
|
@ -134,14 +134,17 @@ int main(int argc, char **argv)
|
|||
app.ntpl_name = args.ntpl_name;
|
||||
app.base_display_addr = args.start_addr;
|
||||
app.tfile_data = get_tfile_data(app.inspected_file, app.ntpl_name);
|
||||
app.rndata = get_rntuple_data(arena, app.inspected_file, app.ntpl_name);
|
||||
app.rndata = get_rntuple_data(arena, app.inspected_file, app.ntpl_name, args.extended_info);
|
||||
|
||||
if (args.print_to_terminal) {
|
||||
u64 nbytes_displayed = args.nbytes_displayed;
|
||||
if (!nbytes_displayed)
|
||||
nbytes_displayed = 1000;
|
||||
String8 rendered = render_range_to_string(arena, app, nbytes_displayed, args.n_cols);
|
||||
printf("%s\n", rendered.c());
|
||||
String8_Node *rendered = render_range_to_string(arena, app, nbytes_displayed, args.n_cols);
|
||||
printf("\n");
|
||||
for (String8_Node *s = rendered; s; s = s->next)
|
||||
printf("%s", s->str.c());
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue