diff --git a/build.zig b/build.zig index c11cbca..8d12f10 100644 --- a/build.zig +++ b/build.zig @@ -13,6 +13,8 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module { .root_source_file = b.path("src/data.zig"), .target = opts.target, .optimize = opts.optimize, + .strip = if(opts.optimize == .Debug) false else true, + .unwind_tables = if(opts.optimize == .Debug) null else .none, }); dataMod.addCSourceFiles(.{ diff --git a/src/components/filesystem.c b/src/components/filesystem.c index 43bc94e..27c5f3b 100644 --- a/src/components/filesystem.c +++ b/src/components/filesystem.c @@ -48,7 +48,7 @@ nn_bool_t nn_destroyFilesystem(nn_filesystem *fs) { if(!nn_decRef(&fs->refc)) return false; // close all files - for(size_t i = 0; i < NN_MAX_OPEN_FILES; i++) { + for(nn_size_t i = 0; i < NN_MAX_OPEN_FILES; i++) { void *f = fs->files[i]; if(f != NULL) fs->table.close(fs->table.userdata, f); } diff --git a/src/components/volatileFilesystem.c b/src/components/volatileFilesystem.c index f679ffc..53b0641 100644 --- a/src/components/volatileFilesystem.c +++ b/src/components/volatileFilesystem.c @@ -1,5 +1,7 @@ #include "../neonucleus.h" +// Data structures + typedef struct nn_vfnode { struct nn_vfilesystem *fs; struct nn_vfnode *parent; @@ -13,6 +15,7 @@ typedef struct nn_vfnode { }; nn_size_t len; nn_size_t cap; + nn_size_t lastModified; // this is used to block deleting nn_refc handleCount; } nn_vfnode; @@ -36,6 +39,132 @@ typedef struct nn_vfilesystem { nn_vfnode *root; } nn_vfilesystem; -nn_filesystem *nn_volatileFilesystem(nn_Context *context, nn_vfilesystemOptions opts, nn_filesystemControl control) { +// virtual node helpers +nn_size_t nn_vf_now(nn_vfilesystem *fs) { + nn_Clock c = fs->ctx.clock; + double time = c.proc(c.userdata); + double elapsed = time - fs->birthday; + nn_size_t elapsedMS = elapsed * 1000; + return fs->opts.creationTime + elapsedMS; +} + +nn_vfnode *nn_vf_allocFile(nn_vfilesystem *fs, const char *name) { + nn_Alloc *alloc = &fs->ctx.allocator; + nn_vfnode *node = nn_alloc(alloc, sizeof(nn_vfnode)); + if(node == NULL) return NULL; + *node = (nn_vfnode) { + .fs = fs, + .parent = NULL, + .lastModified = nn_vf_now(fs), + .isDirectory = false, + .data = NULL, + .len = 0, + .cap = 0, + .handleCount = 0, + }; + // we pray + nn_strcpy(node->name, name); + return node; +} + +nn_vfnode *nn_vf_allocDirectory(nn_vfilesystem *fs, const char *name) { + nn_Alloc *alloc = &fs->ctx.allocator; + nn_vfnode *node = nn_alloc(alloc, sizeof(nn_vfnode)); + if(node == NULL) return NULL; + nn_vfnode **buffer = nn_alloc(alloc, sizeof(nn_vfnode *)); + if(buffer == NULL) { + nn_dealloc(alloc, node, sizeof(nn_vfnode)); + return NULL; + } + *node = (nn_vfnode) { + .fs = fs, + .parent = NULL, + .lastModified = nn_vf_now(fs), + .isDirectory = false, + .entries = buffer, + .len = 0, + .cap = fs->opts.maxDirEntries, + .handleCount = 0, + }; + // we pray + nn_strcpy(node->name, name); + return node; +} + +void nn_vf_freeNode(nn_vfnode *node) { + nn_Alloc *alloc = &node->fs->ctx.allocator; + + if(node->isDirectory) { + for(nn_size_t i = 0; i < node->len; i++) { + nn_vf_freeNode(node->entries[i]); + } + nn_dealloc(alloc, node->entries, sizeof(nn_vfnode *) * node->cap); + } else { + nn_dealloc(alloc, node->data, node->cap); + } + + nn_dealloc(alloc, node, sizeof(nn_vfnode)); +} + +nn_size_t nn_vf_spaceUsedByNode(nn_vfnode *node) { + if(node->isDirectory) { + nn_size_t sum = 0; + for(nn_size_t i = 0; i < node->len; i++) { + sum = nn_vf_spaceUsedByNode(node->entries[i]); + } + return sum; + } else { + return node->len; + } +} + +// methods + +void nn_vfs_deinit(nn_vfilesystem *fs) { + nn_Context ctx = fs->ctx; + + nn_vf_freeNode(fs->root); + nn_dealloc(&ctx.allocator, fs, sizeof(nn_vfilesystem)); +} + +void nn_vfs_getLabel(nn_vfilesystem *fs, char *buf, nn_size_t *buflen) { + *buflen = fs->opts.labelLen; + nn_memcpy(buf, fs->opts.label, fs->opts.labelLen); +} + +void nn_vfs_setLabel(nn_vfilesystem *fs, const char *buf, nn_size_t buflen) { + nn_memcpy(fs->opts.label, buf, buflen); + fs->opts.labelLen = buflen; +} + +nn_size_t nn_vfs_spaceUsed(nn_vfilesystem *fs) { + return nn_vf_spaceUsedByNode(fs->root); +} + +nn_bool_t nn_vfs_isReadOnly(nn_vfilesystem *fs) { + return fs->opts.isReadOnly; +} + +// main funciton + +nn_filesystem *nn_volatileFilesystem(nn_Context *context, nn_vfilesystemOptions opts, nn_filesystemControl control) { + // TODO: handle OOM + nn_vfilesystem *fs = nn_alloc(&context->allocator, sizeof(nn_vfilesystem)); + nn_Clock c = fs->ctx.clock; + double time = c.proc(c.userdata); + fs->ctx = *context; + fs->birthday = time; + fs->opts = opts; + fs->root = nn_vf_allocDirectory(fs, "/"); + nn_filesystemTable table = { + .userdata = fs, + .deinit = (void *)nn_vfs_deinit, + .getLabel = (void *)nn_vfs_getLabel, + .setLabel = (void *)nn_vfs_setLabel, + .spaceUsed = (void *)nn_vfs_spaceUsed, + .spaceTotal = opts.capacity, + .isReadOnly = (void *)nn_vfs_isReadOnly, + }; + return nn_newFilesystem(context, table, control); }