Compare commits

..

No commits in common. "master" and "grouped" have entirely different histories.

9 changed files with 174 additions and 237 deletions

View file

@ -10,7 +10,8 @@ $ git clone --recurse-submodules <repo_url>
```
### Dependencies
rntviewer currently only fully works on Linux, with the terminal-only version working on MacOS as well.
rntviewer currently only fully works on Linux, with the terminal-only version working
on MacOS as well (PRs welcome).
The dependencies are:
- GLFW3 (`libglfw3-dev` on debian, `glfw-devel` on fedora, `glfw` on arch)
@ -19,7 +20,7 @@ The dependencies are:
Other than those, rntviewer depends on Dear ImGui and GLAD (both included in the source tree).
For the graphical version, the OS must support OpenGL 3.3 or higher.
The machine must support OpenGL 3.3 or higher.
For the terminal-only version you don't need GLFW3, ImGui or OpenGL support.

View file

@ -124,15 +124,12 @@ using Display_Range_Fn = String8_Node *(*)(Arena *, String8_Node *, const char *
enum Hover_Section_Flags {
HoverSec_None = 0,
// Hide = don't show at all, even the title
HoverSec_HideIfNotHovered = 1,
// Collapse = only show the title
HoverSec_CollapseIfNotHovered = 2,
};
// Functor used by get_section_hover_info to describe the structure of a section and print data about it.
struct Sec_Hover_Fn {
u64 off; // the hovered offset relative to the start of `data`
u64 off; // the offset relative to the start of `data`
const u8 *data; // the entire file data
const Section &section;
Arena *arena;
@ -142,20 +139,6 @@ struct Sec_Hover_Fn {
u8 cur_section_nesting = 0;
u8 innermost_section_highlighted = 0;
template <typename T>
b8 read(T *val, u64 offset, u64 *size = nullptr) const
{
u64 nb = size ? *size : sizeof(T);
if (offset + nb > section.range.end()) {
fprintf(stderr, "Trying to read bytes 0x%" PRIX64 "-0x%" PRIX64 " which are past the end of the section 0x%" PRIX64 "!\n",
offset, offset + nb, section.range.end());
return false;
}
memcpy(val, data + offset, nb);
return true;
}
template <typename F>
void titled_section(const char *title, F &&sec_body_fn, u64 flags = 0)
{
@ -167,19 +150,11 @@ struct Sec_Hover_Fn {
sec_body_fn();
// assert(cur_field_off >= sec_start);
if (cur_field_off < sec_start) {// TEMP DEBUG
fprintf(stderr, "Something wrong going on in %s!\n", title);
return;
}
assert(cur_field_off >= sec_start);
b8 hovered = off >= sec_start && off <= cur_field_off;
if (!hovered) {
if (flags & HoverSec_HideIfNotHovered)
if (!hovered & (flags & HoverSec_HideIfNotHovered)) {
pop_str8_node_child(prev_desc, info.desc);
else if (flags & HoverSec_CollapseIfNotHovered)
info.desc->first_child = info.desc->last_child = nullptr;
} else if (display_grouped) {
// if we're in display_grouped mode, we want to highlight the entire range of the section;
u64 sec_len = cur_field_off - sec_start;
@ -211,9 +186,7 @@ struct Sec_Hover_Fn {
b8 hovered = cur_field_off <= off && off < cur_field_off + field_len;
T val;
if (!read(&val, cur_field_off))
return false;
memcpy(&val, (u8 *)data + cur_field_off, field_len);
String8_Node *desc = display_val(arena, info.desc, desc_fmt, val);
if (hovered && !display_grouped)
info.highlighted_desc = desc;
@ -232,9 +205,7 @@ struct Sec_Hover_Fn {
{
// String size can be stored as different types, like u8 (by ROOT I/O) or u32 (by RNTuple).
TStrSize str_size;
if (!read(&str_size, cur_field_off))
return;
memcpy(&str_size, data + cur_field_off, sizeof(TStrSize));
// DEBUG
if (str_size > 1000) {
printf("read str_size = %u at offset 0x%lX!\n", str_size, cur_field_off);
@ -244,10 +215,7 @@ struct Sec_Hover_Fn {
b8 hovered = cur_field_off <= off && off < cur_field_off + field_len;
u8 *buf = arena_push_array_nozero<u8>(arena, str_size + 1);
u64 size_to_read = str_size;
if (!read(buf, cur_field_off + sizeof(TStrSize), &size_to_read))
return;
memcpy(buf, data + cur_field_off + sizeof(TStrSize), str_size);
buf[str_size] = 0;
String8 s = { buf, str_size };
String8_Node *desc = display_val(arena, info.desc, desc_fmt, s);
@ -276,8 +244,6 @@ struct Sec_Hover_Fn {
void range(const char *desc, u64 range_len, Display_Range_Fn display_val = hover_display_generic_range)
{
b8 hovered = cur_field_off <= off && off < cur_field_off + range_len;
if (cur_field_off + range_len > section.range.end())
return;
String8_Node *dsc = display_val(arena, info.desc, desc, data + cur_field_off, range_len);
if (hovered && !display_grouped)
info.highlighted_desc = dsc;
@ -291,15 +257,13 @@ struct Sec_Hover_Fn {
// Returns true if `was_zipped` was read.
b8 maybe_rootzip(b8 *was_zipped = nullptr)
{
// TODO boundary checks
const u64 range_len = 9;
if (cur_field_off + range_len > section.range.end())
return false;
b8 hovered = cur_field_off <= off && off < cur_field_off + range_len;
if (display_val_rootzip(arena, info.desc, "Zipped Block", data + cur_field_off)) {
if (display_grouped || hovered) {
if (was_zipped)
*was_zipped = true;
if (display_grouped || hovered) {
info.rng = { cur_field_off, range_len };
if (hovered)
info.highlighted_desc = info.desc;
@ -316,9 +280,7 @@ struct Sec_Hover_Fn {
{
titled_section(title, [this] {
u16 version_be;
if (!read(&version_be, cur_field_off + 4))
return;
memcpy(&version_be, data + cur_field_off + 4, sizeof(u16));
u32 version = bswap(version_be);
b8 is_big = version > 1000;
@ -356,7 +318,7 @@ struct Sec_Hover_Fn {
range("Envelope size: %s", 6, [] (Arena *arena, String8_Node *prev, const char *fmt, const u8 *payload, u64) {
u64 size;
memcpy(&size, payload, 6);
return push_str8_node_child(arena, prev, fmt, to_pretty_size(arena, size).c());
return push_str8_node_child(arena, prev, fmt, to_pretty_size(arena, size));
});
});
}
@ -364,12 +326,7 @@ struct Sec_Hover_Fn {
enum Frame_Type {
Frame_INVALID,
Frame_Record,
Frame_List,
Frame_COUNT
};
static constexpr const char *frame_type_str[Frame_COUNT] = {
"INVALID", "Record", "List"
Frame_List
};
Frame_Type frame_header(u64 &size, u32 *n_items = nullptr, const char *title = nullptr)
@ -378,11 +335,7 @@ struct Sec_Hover_Fn {
Frame_Type frame_type = Frame_INVALID;
titled_section(titlestr.c(), [this, &frame_type, &frame_size = size, n_items] {
i64 size;
if (!read(&size, cur_field_off)) {
frame_size = 0;
frame_type = Frame_INVALID;
return;
}
memcpy(&size, data + cur_field_off, sizeof(size));
// Sanity check
if (size > 1000000) {
fprintf(stderr, "Frame size read at 0x%" PRIX64 " looks bogus"
@ -404,11 +357,7 @@ struct Sec_Hover_Fn {
frame_type = Frame_INVALID;
} else {
frame_type = Frame_List;
if (!read(n_items, cur_field_off + sizeof(i64))) {
frame_size = 0;
frame_type = Frame_INVALID;
return;
}
memcpy(n_items, data + cur_field_off + sizeof(i64), sizeof(u32));
field<i64>("List frame size: %" PRIi64 " B", hover_display_val_le_abs<i64>);
field_le<u32>("List frame n.items: %u");
}
@ -450,7 +399,7 @@ struct Sec_Hover_Fn {
field_str8<u32>("Type Name: %s");
field_str8<u32>("Type Alias: %s");
field_str8<u32>("Description: %s");
});
}, HoverSec_HideIfNotHovered);
}
void column_desc(const char *title)
@ -475,15 +424,13 @@ struct Sec_Hover_Fn {
field_le<double>("Value Min: %f");
field_le<double>("Value Max: %f");
}
});
}, HoverSec_HideIfNotHovered);
}
void schema_description(const char *title)
{
titled_section(title, [this] {
frame<Frame_List>("Fields", [this] (u32 idx) {
field_desc(push_str8f(arena, "Field %u", idx).c());
});
frame<Frame_List>("Fields", [this] (u32 idx) { field_desc(push_str8f(arena, "Field %u", idx).c()); });
frame<Frame_List>("Columns", [this] (u32 idx) { column_desc(push_str8f(arena, "Column %u", idx).c()); });
frame<Frame_List>("Alias Columns", [this] (u32 idx) {
frame<Frame_Record>(push_str8f(arena, "Alias Column %u", idx).c(), [this] {
@ -557,7 +504,7 @@ struct Sec_Hover_Fn {
void cluster_group()
{
frame<Frame_Record>("Cluster Group", [this] {
frame<Frame_List>("Cluster Group", [this] (u32) {
field_le<u64>("Min Entry: %" PRIu64);
field_le<u64>("Entry Span: %" PRIu64);
field_le<u32>("N Clusters: %u");
@ -598,7 +545,7 @@ struct Sec_Hover_Fn {
b8 has_checksum = n_elems < 0;
push_str8_node_child(arena, info.desc, "Has Checksum: %s", has_checksum ? "yes" : "no");
locator("Element Locator");
});
}, HoverSec_HideIfNotHovered);
}
i64 n_cols;
@ -614,12 +561,12 @@ struct Sec_Hover_Fn {
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 = HoverSec_CollapseIfNotHovered)
void frame(const char *title, F &&frame_body_fn, u64 sec_flags = 0)
{
u64 start_off = cur_field_off;
u64 size;
@ -627,11 +574,8 @@ struct Sec_Hover_Fn {
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) {
fprintf(stderr, "Frame %s was supposed to be of type %s but it's of type %s\n",
title, frame_type_str[FType], frame_type_str[ftype]);
if (ftype != FType)
return;
}
if constexpr (FType == Frame_List) {
// Sadness here.
@ -681,8 +625,7 @@ struct Sec_Hover_Fn {
{
titled_section("TFile Header", [this] {
u32 root_version_be;
if (!read(&root_version_be, cur_field_off + 4))
return;
memcpy(&root_version_be, data + cur_field_off + 4, sizeof(u32));
u32 root_version = bswap(root_version_be);
b8 is_big = root_version > 1000'000;
@ -722,8 +665,7 @@ struct Sec_Hover_Fn {
field_str8<u8>("File Title: %s");
u16 version_be;
if (!read(&version_be, cur_field_off))
return;
memcpy(&version_be, data + cur_field_off, sizeof(u16));
u16 version = bswap(version_be);
b8 is_big = version > 1000;
@ -779,8 +721,7 @@ struct Sec_Hover_Fn {
titled_section("TFile FreeList", [this] {
tkey();
u16 version_be;
if (!read(&version_be, cur_field_off))
return;
memcpy(&version_be, data + cur_field_off, sizeof(u16));
u32 version = bswap(version_be);
b8 is_big = version > 1000;
@ -853,6 +794,7 @@ struct Sec_Hover_Fn {
if (zipped) {
// XXX: why -1?
range("Compressed payload", section.range.len - section.post_size - sizeof(u64) - 1);
field_le<u64>("Checksum: 0x%" PRIX64);
} else {
envelope_preamble();
// NOTE: flags in principle require a more complex handling, but for now they are unused,
@ -862,8 +804,8 @@ struct Sec_Hover_Fn {
field_str8<u32>("Description: %s");
field_str8<u32>("ROOT version: %s");
schema_description("Schema Description");
}
field_le<u64>("Checksum: 0x%" PRIX64);
}
}, HoverSec_HideIfNotHovered);
});
}
@ -880,23 +822,20 @@ struct Sec_Hover_Fn {
if (zipped) {
// XXX: why -1?
range("Payload", section.range.len - section.post_size - sizeof(u64) - 1);
field_le<u64>("Checksum: 0x%" PRIX64);
} else {
envelope_preamble();
// TODO: flags in principle require a more complex handling, but for now they are unused,
// NOTE: flags in principle require a more complex handling, but for now they are unused,
// so they're always occupying only 8 bytes.
field_le<u64>("Flags: 0x%" PRIX64);
field_le<u64>("Header checksum: 0x%" PRIX64);
frame<Frame_Record>("Schema Extension", [this] {
schema_description("Schema Extension");
});
frame<Frame_List>("Column Groups", [this] (u32) {
field_le<u32>("Column Id: %u");
});
frame<Frame_List>("Cluster Groups", [this] (u32) {
cluster_group();
});
}
// NOTE: Column groups are currently unused, so this should always be empty
frame<Frame_List>("Column Groups", [] (u32) {});
frame<Frame_List>("Cluster Groups", [this] (u32) { cluster_group(); });
range("Payload", section.range.len - cur_field_off);
field_le<u64>("Checksum: 0x%" PRIX64);
}
}, HoverSec_HideIfNotHovered);
});
}
@ -924,13 +863,13 @@ struct Sec_Hover_Fn {
if (zipped) {
// XXX: why -1?
range("Payload", section.range.len - section.post_size - sizeof(u64) - 1);
field_le<u64>("Checksum: 0x%" PRIX64);
} else {
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(); });
}
field_le<u64>("Checksum: 0x%" PRIX64);
}, HoverSec_HideIfNotHovered);
});
}
@ -999,7 +938,6 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
break;
case Sec_TKey_List:
printf("0x%lX - 0x%lX (pre %lu)\n", section.range.start, section.range.end(), section.pre_size);
hover.tkey_list();
break;

View file

@ -618,9 +618,7 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
if (rdata.rng_tkeys_list.start <= off && off < rdata.rng_tkeys_list.end()) {
sec.id = Sec_TKey_List;
sec.range = rdata.rng_tkeys_list;
// FIXME!
// sec.range.len += rblob_sz;
// printf("with rblob_sz: 0x%lX\n", sec.range.end());
sec.pre_size = rblob_sz;
return sec;
}