tar layer refactor
This commit is contained in:
parent
35564cceef
commit
3f2abf5b3e
@ -335,7 +335,7 @@ Global struct {
|
|||||||
struct swapchain *first_free_swapchain;
|
struct swapchain *first_free_swapchain;
|
||||||
|
|
||||||
/* Shader bytecode archive */
|
/* Shader bytecode archive */
|
||||||
struct tar_archive dxc_archive;
|
TAR_Archive dxc_archive;
|
||||||
|
|
||||||
/* Pipeline cache */
|
/* Pipeline cache */
|
||||||
P_Mutex pipelines_mutex;
|
P_Mutex pipelines_mutex;
|
||||||
@ -419,7 +419,7 @@ void gp_startup(void)
|
|||||||
if (embedded_data.len <= 0) {
|
if (embedded_data.len <= 0) {
|
||||||
P_Panic(Lit("No embedded shaders found"));
|
P_Panic(Lit("No embedded shaders found"));
|
||||||
}
|
}
|
||||||
G.dxc_archive = tar_parse(G.pipelines_arena, embedded_data, Lit(""));
|
G.dxc_archive = TAR_ArchiveFromString(G.pipelines_arena, embedded_data, Lit(""));
|
||||||
|
|
||||||
/* Initialize dx12 */
|
/* Initialize dx12 */
|
||||||
/* TODO: Parallelize phases */
|
/* TODO: Parallelize phases */
|
||||||
@ -956,9 +956,9 @@ internal P_JobDef(pipeline_alloc_job, job)
|
|||||||
|
|
||||||
String error_str = ZI;
|
String error_str = ZI;
|
||||||
|
|
||||||
String vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".vs")))->data;
|
String vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".vs")))->data;
|
||||||
String ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".ps")))->data;
|
String ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".ps")))->data;
|
||||||
String cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : tar_get(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".cs")))->data;
|
String cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : TAR_EntryFromName(&G.dxc_archive, CatString(scratch.arena, pipeline_name, Lit(".cs")))->data;
|
||||||
if (success && vs_dxc.len > 0 && ps_dxc.len <= 0) {
|
if (success && vs_dxc.len > 0 && ps_dxc.len <= 0) {
|
||||||
error_str = Lit("Pipeline has vertex shader without pixel shader");
|
error_str = Lit("Pipeline has vertex shader without pixel shader");
|
||||||
success = 0;
|
success = 0;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ R_StartupReceipt R_Startup(void)
|
|||||||
{
|
{
|
||||||
P_Panic(Lit("No embedded resources found"));
|
P_Panic(Lit("No embedded resources found"));
|
||||||
}
|
}
|
||||||
g->archive = tar_parse(g->arena, embedded_data, Lit(""));
|
g->archive = TAR_ArchiveFromString(g->arena, embedded_data, Lit(""));
|
||||||
#else
|
#else
|
||||||
/* Ensure we have the right working directory */
|
/* Ensure we have the right working directory */
|
||||||
if (!P_IsDir(Lit("res")))
|
if (!P_IsDir(Lit("res")))
|
||||||
@ -36,7 +36,7 @@ R_Resource R_OpenResource(String name)
|
|||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
R_SharedState *g = &R_shared_state;
|
R_SharedState *g = &R_shared_state;
|
||||||
R_Resource result = ZI;
|
R_Resource result = ZI;
|
||||||
struct tar_entry *entry = tar_get(&g->archive, name);
|
TAR_Entry *entry = TAR_EntryFromName(&g->archive, name);
|
||||||
result._data = entry->data;
|
result._data = entry->data;
|
||||||
result._name = entry->file_name;
|
result._name = entry->file_name;
|
||||||
result._exists = entry->valid;
|
result._exists = entry->valid;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ Struct(R_SharedState)
|
|||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct tar_archive archive;
|
TAR_Archive archive;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,53 +1,10 @@
|
|||||||
#define ARCHIVE_LOOKUP_TABLE_CAPACITY_FACTOR 2.0
|
Readonly TAR_Entry TAR_nil_entry = ZI;
|
||||||
|
|
||||||
/* File types:
|
u64 TAR_U64FromOctString(String str)
|
||||||
* '0' or (ASCII NUL) Normal file
|
|
||||||
* '1' Hard link
|
|
||||||
* '2' Symbolic link
|
|
||||||
* '3' Character special
|
|
||||||
* '4' Block special
|
|
||||||
* '5' Directory
|
|
||||||
* '6' FIFO
|
|
||||||
* '7' Contiguous file
|
|
||||||
* 'g' Global extended header with meta data(POSIX.1 - 2001)
|
|
||||||
* 'x' Extended header with metadata for the next file in the archive(POSIX.1 - 2001)
|
|
||||||
* 'A'-'Z' Vendor specific extensions(POSIX.1 - 1988)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TAR_TYPE_FILE '0'
|
|
||||||
#define TAR_TYPE_DIRECTORY '5'
|
|
||||||
#define TAR_TYPE_PAX_HEADER_X 'x'
|
|
||||||
#define TAR_TYPE_PAX_HEADER_G 'g'
|
|
||||||
|
|
||||||
Packed(struct tar_header {
|
|
||||||
/* Pre-posix */
|
|
||||||
u8 file_name[100];
|
|
||||||
u8 file_mode[8];
|
|
||||||
u8 owner_id[8];
|
|
||||||
u8 group_id[8];
|
|
||||||
u8 file_size[12];
|
|
||||||
u8 last_modified[12];
|
|
||||||
u8 checksum[8];
|
|
||||||
|
|
||||||
/* Both */
|
|
||||||
u8 file_type;
|
|
||||||
u8 linked_file_name[100];
|
|
||||||
|
|
||||||
/* UStar */
|
|
||||||
u8 ustar_indicator[6];
|
|
||||||
u8 ustar_version[2];
|
|
||||||
u8 owner_user_name[32];
|
|
||||||
u8 owner_group_name[32];
|
|
||||||
u8 device_major_number[8];
|
|
||||||
u8 device_minor_number[8];
|
|
||||||
u8 file_name_prefix[155];
|
|
||||||
u8 padding[12];
|
|
||||||
});
|
|
||||||
|
|
||||||
internal u64 str_oct_to_u64(String str)
|
|
||||||
{
|
{
|
||||||
u64 n = 0;
|
u64 n = 0;
|
||||||
for (u64 i = 0; i < str.len; ++i) {
|
for (u64 i = 0; i < str.len; ++i)
|
||||||
|
{
|
||||||
n *= 8;
|
n *= 8;
|
||||||
n += (u64)(str.text[i]) - '0';
|
n += (u64)(str.text[i]) - '0';
|
||||||
}
|
}
|
||||||
@ -59,27 +16,30 @@ internal u64 str_oct_to_u64(String str)
|
|||||||
* NOTE: The resulting archive merely points into the supplied tar data, no
|
* NOTE: The resulting archive merely points into the supplied tar data, no
|
||||||
* copying is done. Accessing the archive assumes that the data string is still valid.
|
* copying is done. Accessing the archive assumes that the data string is still valid.
|
||||||
*/
|
*/
|
||||||
struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct tar_archive archive = ZI;
|
TAR_Archive archive = ZI;
|
||||||
BB_Buff bb = BitbuffFromString(data);
|
BB_Buff bb = BitbuffFromString(data);
|
||||||
BB_Reader br = BB_ReaderFromBuffNoDebug(&bb);
|
BB_Reader br = BB_ReaderFromBuffNoDebug(&bb);
|
||||||
|
|
||||||
u64 num_files = 0;
|
u64 num_files = 0;
|
||||||
while (BB_NumBytesRemaining(&br) > 1024) {
|
while (BB_NumBytesRemaining(&br) > 1024)
|
||||||
|
{
|
||||||
|
|
||||||
struct tar_header header = ZI;
|
TAR_Header header = ZI;
|
||||||
BB_ReadBytes(&br, StringFromStruct(&header));
|
BB_ReadBytes(&br, StringFromStruct(&header));
|
||||||
|
|
||||||
if (!EqString(StringFromArray(header.ustar_indicator), Lit("ustar\0"))) {
|
if (!EqString(StringFromArray(header.ustar_indicator), Lit("ustar\0")))
|
||||||
|
{
|
||||||
/* Invalid header */
|
/* Invalid header */
|
||||||
Assert(0);
|
Assert(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.file_name_prefix[0] != 0) {
|
if (header.file_name_prefix[0] != 0)
|
||||||
|
{
|
||||||
/* Header file name prefix not supported */
|
/* Header file name prefix not supported */
|
||||||
Assert(0);
|
Assert(0);
|
||||||
continue;
|
continue;
|
||||||
@ -87,9 +47,10 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
|||||||
|
|
||||||
String file_size_oct_str = { .len = 11, .text = header.file_size };
|
String file_size_oct_str = { .len = 11, .text = header.file_size };
|
||||||
|
|
||||||
u64 file_size = str_oct_to_u64(file_size_oct_str);
|
u64 file_size = TAR_U64FromOctString(file_size_oct_str);
|
||||||
u8 *file_data_ptr = BB_ReadBytesRaw(&br, file_size);
|
u8 *file_data_ptr = BB_ReadBytesRaw(&br, file_size);
|
||||||
if (!file_data_ptr) {
|
if (!file_data_ptr)
|
||||||
|
{
|
||||||
file_size = 0;
|
file_size = 0;
|
||||||
}
|
}
|
||||||
String file_data = STRING(file_size, file_data_ptr);
|
String file_data = STRING(file_size, file_data_ptr);
|
||||||
@ -98,23 +59,25 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
|||||||
u64 remaining = (512 - (file_size % 512)) % 512;
|
u64 remaining = (512 - (file_size % 512)) % 512;
|
||||||
BB_SeekBytes(&br, remaining);
|
BB_SeekBytes(&br, remaining);
|
||||||
|
|
||||||
b32 is_dir = header.file_type == TAR_TYPE_DIRECTORY;
|
b32 is_dir = header.file_type == TAR_FileKind_Directory;
|
||||||
if (!is_dir && header.file_type != TAR_TYPE_FILE) {
|
if (!is_dir && header.file_type != TAR_FileKind_File)
|
||||||
|
{
|
||||||
/* Unsupported type */
|
/* Unsupported type */
|
||||||
Assert(header.file_type == TAR_TYPE_PAX_HEADER_X ||
|
Assert(header.file_type == TAR_FileKind_PaxHeaderX ||
|
||||||
header.file_type == TAR_TYPE_PAX_HEADER_G);
|
header.file_type == TAR_FileKind_PaxHeaderG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String file_name_cstr = StringFromCstrNoLimit((char *)header.file_name);
|
String file_name_cstr = StringFromCstrNoLimit((char *)header.file_name);
|
||||||
if (file_name_cstr.len >= 2) {
|
if (file_name_cstr.len >= 2)
|
||||||
|
{
|
||||||
/* Chop off './' prefix */
|
/* Chop off './' prefix */
|
||||||
file_name_cstr.len -= 2;
|
file_name_cstr.len -= 2;
|
||||||
file_name_cstr.text += 2;
|
file_name_cstr.text += 2;
|
||||||
}
|
}
|
||||||
String file_name = CatString(arena, prefix, file_name_cstr);
|
String file_name = CatString(arena, prefix, file_name_cstr);
|
||||||
|
|
||||||
struct tar_entry *entry = PushStruct(arena, struct tar_entry);
|
TAR_Entry *entry = PushStruct(arena, TAR_Entry);
|
||||||
entry->valid = 1;
|
entry->valid = 1;
|
||||||
entry->is_dir = is_dir;
|
entry->is_dir = is_dir;
|
||||||
entry->file_name = file_name;
|
entry->file_name = file_name;
|
||||||
@ -126,8 +89,9 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build lookup table */
|
/* Build lookup table */
|
||||||
archive.lookup = InitDict(arena, (u64)((f64)num_files * ARCHIVE_LOOKUP_TABLE_CAPACITY_FACTOR));
|
archive.lookup = InitDict(arena, (u64)((f64)num_files * TAR_ArchiveLookupTableCapacityFactor));
|
||||||
for (struct tar_entry *entry = archive.head; entry; entry = entry->next) {
|
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
|
||||||
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, entry->file_name);
|
u64 hash = HashFnv64(Fnv64Basis, entry->file_name);
|
||||||
SetDictValue(arena, archive.lookup, hash, (u64)entry);
|
SetDictValue(arena, archive.lookup, hash, (u64)entry);
|
||||||
}
|
}
|
||||||
@ -135,20 +99,25 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
|||||||
/* Build hierarchy */
|
/* Build hierarchy */
|
||||||
/* NOTE: This is a separate pass because tar entry order is not guaranteed
|
/* NOTE: This is a separate pass because tar entry order is not guaranteed
|
||||||
* (IE file entries may be encountered before their parent directory entry) */
|
* (IE file entries may be encountered before their parent directory entry) */
|
||||||
for (struct tar_entry *entry = archive.head; entry; entry = entry->next) {
|
for (TAR_Entry *entry = archive.head; entry; entry = entry->next)
|
||||||
|
{
|
||||||
/* Enter into hierarchy */
|
/* Enter into hierarchy */
|
||||||
if (!entry->is_dir) {
|
if (!entry->is_dir)
|
||||||
|
{
|
||||||
/* Find parent entry */
|
/* Find parent entry */
|
||||||
struct tar_entry *parent_entry = 0;
|
TAR_Entry *parent_entry = 0;
|
||||||
for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len) {
|
for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len)
|
||||||
if (parent_dir_name.text[parent_dir_name.len - 1] == '/') {
|
{
|
||||||
|
if (parent_dir_name.text[parent_dir_name.len - 1] == '/')
|
||||||
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, parent_dir_name);
|
u64 hash = HashFnv64(Fnv64Basis, parent_dir_name);
|
||||||
parent_entry = (struct tar_entry *)DictValueFromHash(archive.lookup, hash);
|
parent_entry = (TAR_Entry *)DictValueFromHash(archive.lookup, hash);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Insert child into parent's list */
|
/* Insert child into parent's list */
|
||||||
if (parent_entry) {
|
if (parent_entry)
|
||||||
|
{
|
||||||
entry->next_child = parent_entry->next_child;
|
entry->next_child = parent_entry->next_child;
|
||||||
parent_entry->next_child = entry;
|
parent_entry->next_child = entry;
|
||||||
}
|
}
|
||||||
@ -158,10 +127,10 @@ struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
|||||||
return archive;
|
return archive;
|
||||||
}
|
}
|
||||||
|
|
||||||
Readonly Global struct tar_entry g_nil_tar_entry = ZI;
|
Readonly Global TAR_Entry g_nil_tar_entry = ZI;
|
||||||
struct tar_entry *tar_get(struct tar_archive *archive, String name)
|
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name)
|
||||||
{
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, name);
|
u64 hash = HashFnv64(Fnv64Basis, name);
|
||||||
struct tar_entry *lookup = (struct tar_entry *)DictValueFromHash(archive->lookup, hash);
|
TAR_Entry *lookup = (TAR_Entry *)DictValueFromHash(archive->lookup, hash);
|
||||||
return lookup ? lookup : &g_nil_tar_entry;
|
return lookup ? lookup : &g_nil_tar_entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,74 @@
|
|||||||
struct tar_entry {
|
////////////////////////////////
|
||||||
|
//~ Archive types
|
||||||
|
|
||||||
|
#define TAR_ArchiveLookupTableCapacityFactor 2.0
|
||||||
|
|
||||||
|
Struct(TAR_Entry)
|
||||||
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
String file_name;
|
String file_name;
|
||||||
String data;
|
String data;
|
||||||
|
|
||||||
b32 is_dir;
|
b32 is_dir;
|
||||||
struct tar_entry *next;
|
TAR_Entry *next;
|
||||||
struct tar_entry *next_child; /* If entry is dir, points to first child. Otherwise points to next sibling. */
|
TAR_Entry *next_child; /* If entry is dir, points to first child. Otherwise points to next sibling. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tar_archive {
|
Struct(TAR_Archive)
|
||||||
|
{
|
||||||
Dict *lookup;
|
Dict *lookup;
|
||||||
struct tar_entry *head;
|
TAR_Entry *head;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tar_archive tar_parse(Arena *arena, String data, String prefix);
|
extern Readonly TAR_Entry TAR_nil_entry;
|
||||||
struct tar_entry *tar_get(struct tar_archive *archive, String name);
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Header types
|
||||||
|
|
||||||
|
typedef u8 TAR_FileKind; enum
|
||||||
|
{
|
||||||
|
TAR_FileKind_File = '0',
|
||||||
|
TAR_FileKind_HardLink = '1',
|
||||||
|
TAR_FileKind_SymLink = '2',
|
||||||
|
TAR_FileKind_CharacterSpecial = '3',
|
||||||
|
TAR_FileKind_BlockSpecial = '4',
|
||||||
|
TAR_FileKind_Directory = '5',
|
||||||
|
TAR_FileKind_Fifo = '6',
|
||||||
|
TAR_FileKind_ContiguousFile = '7',
|
||||||
|
TAR_FileKind_PaxHeaderG = 'g',
|
||||||
|
TAR_FileKind_PaxHeaderX = 'x'
|
||||||
|
};
|
||||||
|
|
||||||
|
Packed(Struct(TAR_Header)
|
||||||
|
{
|
||||||
|
/* Pre-posix */
|
||||||
|
u8 file_name[100];
|
||||||
|
u8 file_mode[8];
|
||||||
|
u8 owner_id[8];
|
||||||
|
u8 group_id[8];
|
||||||
|
u8 file_size[12];
|
||||||
|
u8 last_modified[12];
|
||||||
|
u8 checksum[8];
|
||||||
|
|
||||||
|
/* Both */
|
||||||
|
u8 file_type;
|
||||||
|
u8 linked_file_name[100];
|
||||||
|
|
||||||
|
/* UStar */
|
||||||
|
u8 ustar_indicator[6];
|
||||||
|
u8 ustar_version[2];
|
||||||
|
u8 owner_user_name[32];
|
||||||
|
u8 owner_group_name[32];
|
||||||
|
u8 device_major_number[8];
|
||||||
|
u8 device_minor_number[8];
|
||||||
|
u8 file_name_prefix[155];
|
||||||
|
u8 padding[12];
|
||||||
|
});
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Archive operations
|
||||||
|
|
||||||
|
u64 TAR_U64FromOctString(String str);
|
||||||
|
TAR_Archive TAR_ArchiveFromString(Arena *arena, String data, String prefix);
|
||||||
|
|
||||||
|
TAR_Entry *TAR_EntryFromName(TAR_Archive *archive, String name);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user