Musa-Cpp-Lib-V2/lib/OS/OS_Filesystem.cpp

122 lines
3.8 KiB
C++

// So NTFS (and most systems) sort the tree by default in lexicographical descending order.
// For lookups, this often isn't that useful if you only know substrings of the path.
// struct BTNode {
// u16 key_count;
// BTNode* keys;
// u16 allocated;
// };
// struct B_Tree {
// BTNode* root;
// Allocator allocator;
// };
// A compact collection of data with sorting indices
// Maybe we can make B+ trees for sorting according to
// size and modtime.
// It really doesn't make sense to store data in memory as a B-tree except
// if we need ordered insertions and deletes.
//
// Returns offset
force_inline u32 AddString_NoCount (Serializer* serializer, u8* data, u8 count) { // #TODO: , bool null_terminate=false
u8* current_point = &serializer->data[serializer->count];
s64 final_count = serializer->allocated + (count * sizeof(u8));
if (serializer->allocated < final_count) {
array_reserve(*serializer, final_count);
}
memcpy(current_point, data, count * sizeof(u8));
serializer->count += count * sizeof(u8);
return (u32)serializer->count;
}
constexpr s64 DFS_Preallocation_Count = 4194304; // 2^22
// template <typename Length_Type>
struct DFS_Array {
Serializer* strings;
ArenaArray<u32>* offsets; // offsets into strings->data
ArenaArray<u8>* lengths; // this type may vary <hmmm> Not sure if I should make it a template argument. Seems yucky.
ArenaArray<u64>* modtimes;
ArenaArray<u64>* sizes;
ArenaArray<s32>* parent_indices;
// s64 index; // current index when inserting;
// #Temporary arrays for linking files/dirs to their parent directory, if present.
ArenaArray<u32>* record_ids;
ArenaArray<u32>* parent_ids;
// #TODO: Sort indices (should these be trees?)
// ArenaArray<s32> indices_sorted_by_modtime;
// ArenaArray<s32> indices_sorted_by_size;
};
s64 item_count (DFS_Array* dfsa) {
return dfsa->offsets->count;
}
void initialize (DFS_Array* dfsa) {
Assert(dfsa != nullptr);
dfsa->strings = new_serializer(Arena_Reserve::Size_2G);
dfsa->offsets = arena_array_new<u32>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->lengths = arena_array_new<u8> (DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->modtimes = arena_array_new<u64>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->sizes = arena_array_new<u64>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->record_ids = arena_array_new<u32>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->parent_ids = arena_array_new<u32>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
dfsa->parent_indices = arena_array_new<s32>(DFS_Preallocation_Count, Arena_Reserve::Size_2G);
// dfsa->index = 0;
}
struct Dense_FS { // Link to OS_Drive
OS_Drive* drive; // backlink for reference.
DFS_Array paths;
DFS_Array files;
ArenaTable<u32, s32> path_table; // <entry_id, array_offset>.
};
void initialize (Dense_FS* dfs, OS_Drive* drive) {
Assert(drive != nullptr); Assert(dfs != nullptr);
// Is there a less stupid way of doing this?
dfs->drive = drive;
drive->data = dfs;
initialize(&dfs->paths);
initialize(&dfs->files);
table_init(&dfs->path_table, 1048576); // 2^20
// dfs->path_table.hash_function = table_hash_function_fnv1a; // default.
dfs->path_table.hash_function = sdbm_hash;
dfs->path_table.compare_function = u32_keys_match;
}
s32 find_previous_index (Dense_FS* dfs, u32 record_id, bool* success) {
s32 result = -1;
(*success) = table_find(&dfs->path_table, record_id, &result);
return result;
}
void cleanup_after_enumeration(Dense_FS* dfs) {
table_release(&dfs->path_table);
reset_struct(&dfs->path_table);
arena_array_free(*dfs->paths.record_ids);
arena_array_free(*dfs->paths.parent_ids);
arena_array_free(*dfs->files.record_ids);
arena_array_free(*dfs->files.parent_ids);
}