some reordering
This commit is contained in:
parent
6468ad1dd7
commit
57bf7675f8
3 changed files with 294 additions and 239 deletions
480
src/hover.cpp
480
src/hover.cpp
|
@ -145,6 +145,9 @@ struct Sec_Hover_Fn {
|
|||
}
|
||||
|
||||
--cur_section_nesting;
|
||||
|
||||
// pop ourselves unless we're the top-level section
|
||||
if (prev_desc)
|
||||
info.desc = prev_desc;
|
||||
}
|
||||
|
||||
|
@ -265,9 +268,9 @@ struct Sec_Hover_Fn {
|
|||
return true;
|
||||
}
|
||||
|
||||
void tkey()
|
||||
void tkey(const char *title = "TKey")
|
||||
{
|
||||
titled_section("TKey", [this] {
|
||||
titled_section(title, [this] {
|
||||
u16 version_be;
|
||||
memcpy(&version_be, data + start + 4, sizeof(u16));
|
||||
u32 version = bswap(version_be);
|
||||
|
@ -441,6 +444,221 @@ struct Sec_Hover_Fn {
|
|||
});
|
||||
}
|
||||
|
||||
void cluster_summary()
|
||||
{
|
||||
frame<Frame_Record>("Cluster Summary", [this] {
|
||||
field_le<u64>("First Entry: %" PRIu64);
|
||||
field<u64>("", [] (Arena *arena, String8_Node *prev, const char *, u64 x) {
|
||||
u64 entries = (x << 8) >> 8;
|
||||
u8 flags = x >> 56;
|
||||
String8_Node *sn = push_str8_node_child(arena, prev, "Entries: %" PRIu64, entries);
|
||||
return push_str8_node(arena, sn, "Flags: 0b%b", flags);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void cluster()
|
||||
{
|
||||
frame<Frame_List>("Cluster", [this] (u32 col_idx) {
|
||||
titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] {
|
||||
frame<Frame_List>("Pages", [this] (u32 page_idx) {
|
||||
titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] {
|
||||
field<i32>("", [] (Arena *arena, String8_Node *prev, const char *, i32 n_elems) {
|
||||
b8 has_checksum = n_elems < 0;
|
||||
String8_Node *sn = push_str8_node_child(arena, prev, "N Elements: %u", std::abs(n_elems));
|
||||
return push_str8_node(arena, sn, "Has Checksum: %s", has_checksum ? "yes" : "no");
|
||||
});
|
||||
locator("Element Locator");
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
|
||||
i64 n_cols;
|
||||
if (!field<i64>("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) {
|
||||
if (n_cols < 0) {
|
||||
return push_str8_node_child(arena, prev, "Element Offset: <suppressed>");
|
||||
}
|
||||
return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols);
|
||||
}, &n_cols))
|
||||
{
|
||||
return;
|
||||
}
|
||||
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 = 0)
|
||||
{
|
||||
u64 start_off = cur_field_off;
|
||||
u64 size;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
if constexpr (FType == Frame_List) {
|
||||
for (u32 i = 0; i < n_items; ++i)
|
||||
frame_body_fn(i);
|
||||
} else {
|
||||
frame_body_fn();
|
||||
}
|
||||
|
||||
assert(cur_field_off >= start_off);
|
||||
u64 allocated_size = cur_field_off - start_off;
|
||||
if (size < allocated_size) {
|
||||
fprintf(stderr, "Frame %s told us its size was %" PRIu64 " but we accounted for %" PRIu64 " bytes!\n",
|
||||
title, size, allocated_size);
|
||||
}
|
||||
|
||||
u64 extra_size = size - allocated_size;
|
||||
if (extra_size > 0)
|
||||
range("Unknown", extra_size);
|
||||
}, sec_flags);
|
||||
|
||||
cur_field_off = start_off + size;
|
||||
}
|
||||
|
||||
// ==============================================================
|
||||
// TOP-LEVEL SECTIONS
|
||||
// ==============================================================
|
||||
void tfile_header()
|
||||
{
|
||||
titled_section("TFile Header", [this] {
|
||||
u32 root_version_be;
|
||||
memcpy(&root_version_be, data + start + 4, sizeof(u32));
|
||||
u32 root_version = bswap(root_version_be);
|
||||
b8 is_big = root_version > 1000'000;
|
||||
|
||||
field_be<u32>("ROOT magic number");
|
||||
field<u32>("ROOT version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000'000) * 1000'000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field_be<u32>("fBEGIN: 0x%" PRIX64);
|
||||
if (is_big) {
|
||||
field_be<u64>("fEND: 0x%" PRIX64);
|
||||
field_be<u64>("Seek Free: 0x%" PRIX64);
|
||||
} else {
|
||||
field_be<u32>("fEND: 0x%" PRIX64);
|
||||
field_be<u32>("Seek Free: 0x%" PRIX64);
|
||||
}
|
||||
field_be<u32>("NBytes Free: %u");
|
||||
field_be<u32>("N Free: %u");
|
||||
field_be<u32>("NBytes Name: %u");
|
||||
field_be<u8>("Units: %u");
|
||||
field_be<u32>("Compression: %u");
|
||||
if (is_big)
|
||||
field_be<u64>("Seek Info: 0x%" PRIX64);
|
||||
else
|
||||
field_be<u32>("Seek Info: 0x%" PRIX64);
|
||||
field_be<u32>("NBytes Info: %u");
|
||||
range("Padding", section.post_size);
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_object()
|
||||
{
|
||||
titled_section("TFile Object", [this] {
|
||||
tkey();
|
||||
field_str8<u8>("File Name: %s");
|
||||
field_str8<u8>("File Title: %s");
|
||||
|
||||
u16 version_be;
|
||||
memcpy(&version_be, data + cur_field_off, sizeof(u16));
|
||||
u16 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000) * 1000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field<u32>("Created: ", hover_display_datetime_str);
|
||||
field<u32>("Modified: ", hover_display_datetime_str);
|
||||
field_be<u32>("NBytes Key: %u");
|
||||
field_be<u32>("NBytes Name: %u");
|
||||
if (is_big) {
|
||||
field_be<u64>("Seek Dir: 0x%" PRIX64) ;
|
||||
field_be<u64>("Seek Parent: 0x%" PRIX64) ;
|
||||
field_be<u64>("Seek Keys: 0x%" PRIX64) ;
|
||||
} else {
|
||||
field_be<u32>("Seek Dir: 0x%" PRIX64) ;
|
||||
field_be<u32>("Seek Parent: 0x%" PRIX64) ;
|
||||
field_be<u32>("Seek Keys: 0x%" PRIX64) ;
|
||||
}
|
||||
field_be<u16>("UUID Vers.Class: %u");
|
||||
field_le<u16>("UUID: %u");
|
||||
if (!is_big)
|
||||
range("Padding", 3 * sizeof(u32));
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_info()
|
||||
{
|
||||
titled_section("TFile Streamer Info", [this] {
|
||||
tkey();
|
||||
b8 zipped;
|
||||
if (!maybe_rootzip(&zipped))
|
||||
return;
|
||||
|
||||
if (zipped) {
|
||||
range("Compressed Payload", section.range.len);
|
||||
} else {
|
||||
field<u32>("Byte Count: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) {
|
||||
x = bswap(x);
|
||||
x -= 0x4000'0000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field_be<u16>("Version: %u");
|
||||
range("TObject Data", section.range.len - 6);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_freelist()
|
||||
{
|
||||
titled_section("TFile FreeList", [this] {
|
||||
tkey();
|
||||
u16 version_be;
|
||||
memcpy(&version_be, data + start + cur_field_off, sizeof(u16));
|
||||
u32 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000) * 1000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
if (is_big) {
|
||||
field_be<u64>("First: 0x%" PRIX64);
|
||||
field_be<u64>("Last: 0x%" PRIX64);
|
||||
} else {
|
||||
field_be<u32>("First: 0x%X");
|
||||
field_be<u32>("Last: 0x%X");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tkey_list()
|
||||
{
|
||||
titled_section("TKey List", [this] {
|
||||
tkey();
|
||||
field_str8<u8>("Empty: %s");
|
||||
field_str8<u8>("File Name: %s");
|
||||
field_str8<u8>("Empty: %s");
|
||||
field_be<u32>("N Keys: %u");
|
||||
tkey("RNTuple Key");
|
||||
field_str8<u8>("RNTuple Class: %s");
|
||||
field_str8<u8>("RNTuple Name: %s");
|
||||
field_str8<u8>("RNTuple Desc: %s");
|
||||
});
|
||||
}
|
||||
|
||||
void rntuple_anchor()
|
||||
{
|
||||
titled_section("RNTuple Anchor", [this] {
|
||||
|
@ -527,82 +745,16 @@ struct Sec_Hover_Fn {
|
|||
});
|
||||
}
|
||||
|
||||
void cluster_summary()
|
||||
{
|
||||
frame<Frame_Record>("Cluster Summary", [this] {
|
||||
field_le<u64>("First Entry: %" PRIu64);
|
||||
field<u64>("", [] (Arena *arena, String8_Node *prev, const char *, u64 x) {
|
||||
u64 entries = (x << 8) >> 8;
|
||||
u8 flags = x >> 56;
|
||||
String8_Node *sn = push_str8_node_child(arena, prev, "Entries: %" PRIu64, entries);
|
||||
return push_str8_node(arena, sn, "Flags: 0b%b", flags);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void cluster()
|
||||
{
|
||||
frame<Frame_List>("Cluster", [this] (u32 col_idx) {
|
||||
titled_section(push_str8f(arena, "Column %u", col_idx).c(), [this] {
|
||||
frame<Frame_List>("Pages", [this] (u32 page_idx) {
|
||||
titled_section(push_str8f(arena, "Page %u", page_idx).c(), [this] {
|
||||
field<i32>("", [] (Arena *arena, String8_Node *prev, const char *, i32 n_elems) {
|
||||
b8 has_checksum = n_elems < 0;
|
||||
String8_Node *sn = push_str8_node_child(arena, prev, "N Elements: %u", std::abs(n_elems));
|
||||
return push_str8_node(arena, sn, "Has Checksum: %s", has_checksum ? "yes" : "no");
|
||||
});
|
||||
locator("Element Locator");
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
|
||||
i64 n_cols;
|
||||
if (!field<i64>("", [] (Arena *arena, String8_Node *prev, const char *, i64 n_cols) {
|
||||
if (n_cols < 0) {
|
||||
return push_str8_node_child(arena, prev, "Element Offset: <suppressed>");
|
||||
}
|
||||
return push_str8_node_child(arena, prev, "Element Offset: %" PRIi64, n_cols);
|
||||
}, &n_cols))
|
||||
void page()
|
||||
{
|
||||
// only try hovering a key if this is the first page of the cluster (<=> pre_size != 0)
|
||||
if (section.pre_size)
|
||||
tkey();
|
||||
b8 zipped;
|
||||
if (!maybe_rootzip(&zipped))
|
||||
return;
|
||||
}
|
||||
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 = 0)
|
||||
{
|
||||
u64 start_off = cur_field_off;
|
||||
u64 size;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
if constexpr (FType == Frame_List) {
|
||||
for (u32 i = 0; i < n_items; ++i)
|
||||
frame_body_fn(i);
|
||||
} else {
|
||||
frame_body_fn();
|
||||
}
|
||||
|
||||
assert(cur_field_off >= start_off);
|
||||
u64 allocated_size = cur_field_off - start_off;
|
||||
if (size < allocated_size) {
|
||||
fprintf(stderr, "Frame %s told us its size was %" PRIu64 " but we accounted for %" PRIu64 " bytes!\n",
|
||||
title, size, allocated_size);
|
||||
}
|
||||
|
||||
u64 extra_size = size - allocated_size;
|
||||
if (extra_size > 0)
|
||||
range("Unknown", extra_size);
|
||||
}, sec_flags);
|
||||
|
||||
cur_field_off = start_off + size;
|
||||
range("Payload", section.range.len - section.post_size); // TODO: improve
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}
|
||||
|
||||
void page_list()
|
||||
|
@ -626,127 +778,6 @@ struct Sec_Hover_Fn {
|
|||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_header()
|
||||
{
|
||||
titled_section("TFile Header", [this] {
|
||||
u32 root_version_be;
|
||||
memcpy(&root_version_be, data + start + 4, sizeof(u32));
|
||||
u32 root_version = bswap(root_version_be);
|
||||
b8 is_big = root_version > 1000'000;
|
||||
|
||||
field_be<u32>("ROOT magic number");
|
||||
field<u32>("ROOT version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000'000) * 1000'000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field_be<u32>("fBEGIN: 0x%" PRIX64);
|
||||
if (is_big) {
|
||||
field_be<u64>("fEND: 0x%" PRIX64);
|
||||
field_be<u64>("Seek Free: 0x%" PRIX64);
|
||||
} else {
|
||||
field_be<u32>("fEND: 0x%" PRIX64);
|
||||
field_be<u32>("Seek Free: 0x%" PRIX64);
|
||||
}
|
||||
field_be<u32>("NBytes Free: %u");
|
||||
field_be<u32>("N Free: %u");
|
||||
field_be<u32>("NBytes Name: %u");
|
||||
field_be<u8>("Units: %u");
|
||||
field_be<u32>("Compression: %u");
|
||||
if (is_big)
|
||||
field_be<u64>("Seek Info: 0x%" PRIX64);
|
||||
else
|
||||
field_be<u32>("Seek Info: 0x%" PRIX64);
|
||||
field_be<u32>("NBytes Info: %u");
|
||||
range("Padding", section.post_size);
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_object()
|
||||
{
|
||||
titled_section("TFile Object", [this] {
|
||||
tkey();
|
||||
field_str8<u8>("File Name: %s");
|
||||
field_str8<u8>("File Title: %s");
|
||||
|
||||
u16 version_be;
|
||||
memcpy(&version_be, data + cur_field_off, sizeof(u16));
|
||||
u16 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000) * 1000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field<u32>("Created: ", hover_display_datetime_str);
|
||||
field<u32>("Modified: ", hover_display_datetime_str);
|
||||
field_be<u32>("NBytes Key: %u");
|
||||
field_be<u32>("NBytes Name: %u");
|
||||
if (is_big) {
|
||||
field_be<u64>("Seek Dir: 0x%" PRIX64) ;
|
||||
field_be<u64>("Seek Parent: 0x%" PRIX64) ;
|
||||
field_be<u64>("Seek Keys: 0x%" PRIX64) ;
|
||||
} else {
|
||||
field_be<u32>("Seek Dir: 0x%" PRIX64) ;
|
||||
field_be<u32>("Seek Parent: 0x%" PRIX64) ;
|
||||
field_be<u32>("Seek Keys: 0x%" PRIX64) ;
|
||||
}
|
||||
field_be<u16>("UUID Vers.Class: %u");
|
||||
field_le<u16>("UUID: %u");
|
||||
if (!is_big)
|
||||
range("Padding", 3 * sizeof(u32));
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_info()
|
||||
{
|
||||
titled_section("TFile Info", [this] {
|
||||
tkey();
|
||||
b8 zipped;
|
||||
if (!maybe_rootzip(&zipped))
|
||||
return;
|
||||
|
||||
if (zipped) {
|
||||
range("Compressed Payload", section.range.len);
|
||||
} else {
|
||||
field<u32>("Byte Count: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u32 x) {
|
||||
x = bswap(x);
|
||||
x -= 0x400000000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
field_be<u16>("Version: %u");
|
||||
// hover_try_object(hover)
|
||||
field_be<u8>("Name: %u");
|
||||
field_be<u32>("N Objects: %u");;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tfile_freelist()
|
||||
{
|
||||
titled_section("TFile FreeList", [this] {
|
||||
tkey();
|
||||
u16 version_be;
|
||||
memcpy(&version_be, data + start + cur_field_off, sizeof(u16));
|
||||
u32 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
field<u16>("Version: %u", [] (Arena *arena, String8_Node *prev, const char *fmt, u16 x) {
|
||||
x = bswap(x);
|
||||
x -= (x > 1000) * 1000;
|
||||
return push_str8_node_child(arena, prev, fmt, x);
|
||||
});
|
||||
if (is_big) {
|
||||
field_be<u64>("First: 0x%" PRIX64);
|
||||
field_be<u64>("Last: 0x%" PRIX64);
|
||||
} else {
|
||||
field_be<u32>("First: 0x%X");
|
||||
field_be<u32>("Last: 0x%X");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// `off` is the absolute offset into `data`.
|
||||
|
@ -769,7 +800,6 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
|
|||
push_str8_node_child(arena, info.desc, "Bits per elem: %u", pinfo->bits_per_elem);
|
||||
push_str8_node_child(arena, info.desc, "-----------");
|
||||
} else {
|
||||
info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c());
|
||||
}
|
||||
|
||||
u64 start = section.range.start - section.pre_size;
|
||||
|
@ -778,52 +808,52 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
|
|||
Sec_Hover_Fn hover { start, roff, data, section, arena, info, cur_field_off, display_grouped };
|
||||
|
||||
switch (section.id) {
|
||||
case Sec_RNTuple_Anchor: {
|
||||
case Sec_RNTuple_Anchor:
|
||||
hover.rntuple_anchor();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Sec_TFile_Header: {
|
||||
case Sec_TFile_Header:
|
||||
hover.tfile_header();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Sec_TFile_Object: {
|
||||
case Sec_TFile_Object:
|
||||
hover.tfile_object();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Sec_RNTuple_Header: {
|
||||
case Sec_RNTuple_Header:
|
||||
hover.rntuple_header();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Sec_RNTuple_Footer: {
|
||||
case Sec_RNTuple_Footer:
|
||||
hover.rntuple_footer();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case Sec_Page_List: {
|
||||
case Sec_Page_List:
|
||||
hover.page_list();
|
||||
} break;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case Sec_Page: {
|
||||
// only try hovering a key if this is the first page of the cluster (<=> pre_size != 0)
|
||||
b8 ok = section.pre_size && hover.tkey();
|
||||
ok = ok || hover.maybe_rootzip()
|
||||
|| hover.range("Payload", section.range.len - section.post_size) // TODO: improve
|
||||
|| hover.field_le<u64>("Checksum: 0x%" PRIX64)
|
||||
;
|
||||
} break;
|
||||
case Sec_Page:
|
||||
hover.page();
|
||||
break;
|
||||
|
||||
case Sec_TFile_Info: {
|
||||
case Sec_TFile_Info:
|
||||
hover.tfile_info();
|
||||
} break;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Sec_TFile_FreeList: {
|
||||
case Sec_TFile_FreeList:
|
||||
hover.tfile_freelist();
|
||||
} break;
|
||||
break;
|
||||
|
||||
default:;
|
||||
case Sec_TKey_List:
|
||||
hover.tkey_list();
|
||||
break;
|
||||
|
||||
default:
|
||||
info.desc = push_str8_node(arena, nullptr, "%s", sec_name.c());
|
||||
}
|
||||
|
||||
assert(info.desc);
|
||||
|
||||
// If we're displaying individual values, only show the ancestry of the highlighted desc and its siblings.
|
||||
// @Speed: there is probably a more efficient way to do this by construction.
|
||||
if (info.highlighted_desc && !display_grouped) {
|
||||
|
|
|
@ -140,7 +140,7 @@ internal const String8 section_names[Sec_COUNT] = {
|
|||
str8("None"),
|
||||
str8("TFile Header"),
|
||||
str8("TFile Object"),
|
||||
str8("TFile Info"),
|
||||
str8("TFile Streamer Info"),
|
||||
str8("TFile FreeList"),
|
||||
str8("TKey List"),
|
||||
str8("RNTuple Anchor"),
|
||||
|
|
47
src/str.cpp
47
src/str.cpp
|
@ -39,14 +39,14 @@ String8 to_pretty_size(Arena *arena, u64 bytes)
|
|||
}
|
||||
|
||||
internal
|
||||
String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, ...)
|
||||
String8_Node *push_str8_node_v(Arena *arena, String8_Node *prev, const char *fmt, va_list args)
|
||||
{
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
|
||||
String8_Node *snode = arena_push<String8_Node>(arena);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
snode->str = push_str8fv(arena, fmt, args);
|
||||
va_end(args);
|
||||
snode->str = push_str8fv(arena, fmt, args2);
|
||||
|
||||
if (prev) {
|
||||
prev->next = snode;
|
||||
|
@ -57,20 +57,34 @@ String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt,
|
|||
}
|
||||
snode->prev = prev;
|
||||
|
||||
va_end(args2);
|
||||
return snode;
|
||||
}
|
||||
|
||||
internal
|
||||
String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const char *fmt, ...)
|
||||
String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, ...)
|
||||
{
|
||||
assert(parent);
|
||||
|
||||
String8_Node *snode = arena_push<String8_Node>(arena);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
snode->str = push_str8fv(arena, fmt, args);
|
||||
String8_Node *snode = push_str8_node_v(arena, prev, fmt, args);
|
||||
va_end(args);
|
||||
return snode;
|
||||
}
|
||||
|
||||
internal
|
||||
String8_Node *push_str8_node_child_v(Arena *arena, String8_Node *parent, const char *fmt, va_list args)
|
||||
{
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
if (!parent) {
|
||||
// If there is no parent, just behave the same as push_str8_node.
|
||||
String8_Node *snode = push_str8_node_v(arena, nullptr, fmt, args2);
|
||||
va_end(args2);
|
||||
return snode;
|
||||
}
|
||||
|
||||
String8_Node *snode = arena_push<String8_Node>(arena);
|
||||
snode->str = push_str8fv(arena, fmt, args2);
|
||||
|
||||
snode->prev = parent->last_child;
|
||||
if (parent->first_child) {
|
||||
|
@ -82,6 +96,17 @@ String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const cha
|
|||
snode->head = parent->head;
|
||||
snode->parent = parent;
|
||||
|
||||
va_end(args2);
|
||||
return snode;
|
||||
}
|
||||
|
||||
internal
|
||||
String8_Node *push_str8_node_child(Arena *arena, String8_Node *parent, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8_Node *snode = push_str8_node_child_v(arena, parent, fmt, args);
|
||||
va_end(args);
|
||||
return snode;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue