From 3169b16d10ab03a9ebb7fa59c8ad57f4c4015c09 Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev Date: Wed, 11 Jan 2023 09:45:16 +0100 Subject: [PATCH] vfs: refactor VFSNode allocation and handling of backend-specific data VFSNode no longer has the generic void* data1 and data2 fields. Introduced a macro system that allows backends to easily "subclass" VFSNode to add extra fields. --- src/rwops/all.h | 4 - src/rwops/meson.build | 6 - src/rwops/rwops_zipfile.h | 16 --- src/vfs/decompress_wrapper.c | 40 +++--- src/vfs/meson.build | 2 +- src/vfs/nodeapi.c | 10 +- src/vfs/private.c | 16 +-- src/vfs/private.h | 84 +++++++++-- src/vfs/readonly_wrapper.c | 21 +-- src/vfs/syspath.h | 2 +- src/vfs/syspath_posix.c | 54 +++---- src/vfs/syspath_public.c | 9 +- src/vfs/syspath_win32.c | 72 +++++----- src/vfs/union.c | 89 +++++++----- src/vfs/union.h | 2 +- src/vfs/union_public.c | 17 --- src/vfs/vdir.c | 68 +++++---- src/vfs/vdir.h | 3 +- src/vfs/zipfile.c | 135 ++++++++---------- src/vfs/zipfile.h | 2 +- src/vfs/zipfile_impl.h | 25 ++-- src/vfs/zipfile_null.c | 4 +- src/vfs/zipfile_public.c | 5 +- src/vfs/zippath.c | 91 ++++++------ .../rwops_zipfile.c => vfs/zippath_rwops.c} | 45 +++--- 25 files changed, 416 insertions(+), 406 deletions(-) delete mode 100644 src/rwops/rwops_zipfile.h delete mode 100644 src/vfs/union_public.c rename src/{rwops/rwops_zipfile.c => vfs/zippath_rwops.c} (81%) diff --git a/src/rwops/all.h b/src/rwops/all.h index 75961dcf..1602ef6f 100644 --- a/src/rwops/all.h +++ b/src/rwops/all.h @@ -17,10 +17,6 @@ #include "rwops_zlib.h" #include "rwops_zstd.h" -#ifdef TAISEI_BUILDCONF_USE_ZIP -#include "rwops_zipfile.h" -#endif - #ifdef DEBUG #include "rwops_trace.h" #endif diff --git a/src/rwops/meson.build b/src/rwops/meson.build index 698c35e9..1e0b1cbf 100644 --- a/src/rwops/meson.build +++ b/src/rwops/meson.build @@ -11,12 +11,6 @@ rwops_src = files( 'rwops_zstd.c', ) -if dep_zip.found() - rwops_src += files( - 'rwops_zipfile.c', - ) -endif - if is_debug_build rwops_src += files( 'rwops_trace.c', diff --git a/src/rwops/rwops_zipfile.h b/src/rwops/rwops_zipfile.h deleted file mode 100644 index 8fb0f28f..00000000 --- a/src/rwops/rwops_zipfile.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This software is licensed under the terms of the MIT License. - * See COPYING for further information. - * --- - * Copyright (c) 2011-2019, Lukas Weber . - * Copyright (c) 2012-2019, Andrei Alexeyev . - */ - -#pragma once -#include "taisei.h" - -#include - -#include "vfs/zipfile_impl.h" - -SDL_RWops *SDL_RWFromZipFile(VFSNode *znode, VFSZipPathData *pdata) attr_nonnull_all; diff --git a/src/vfs/decompress_wrapper.c b/src/vfs/decompress_wrapper.c index 7d66d26d..1d27b5bf 100644 --- a/src/vfs/decompress_wrapper.c +++ b/src/vfs/decompress_wrapper.c @@ -16,14 +16,14 @@ // NOTE: Largely based on readonly_wrapper. Sorry for the copypasta. // This is currently hardcoded to only support transparent decompression of .zst files. +VFS_NODE_TYPE(VFSDecompNode, { + VFSNode *wrapped; + bool compr_zstd; +}); + #define ZST_SUFFIX ".zst" -#define WRAPPED(n) ((VFSNode*)(n)->data1) -struct decomp_data { - uint compr_zstd : 1; -}; - -static_assert_nomsg(sizeof(struct decomp_data) <= sizeof(void*)); +#define WRAPPED(node) VFS_NODE_CAST(VFSDecompNode, node)->wrapped static char *vfs_decomp_repr(VFSNode *node) { char *wrapped_repr = vfs_node_repr(WRAPPED(node), false); @@ -64,9 +64,8 @@ static bool vfs_decomp_mkdir(VFSNode *parent, const char *subdir) { static VFSNode *vfs_decomp_locate(VFSNode *dirnode, const char *path) { VFSNode *wrapped = WRAPPED(dirnode); VFSNode *child = vfs_node_locate(wrapped, path); - struct decomp_data data = { 0 }; - VFSNode *ochild = NULL; + bool zstd = false; if(child != NULL && !vfs_node_query(child).exists) { ochild = child; @@ -90,7 +89,7 @@ static VFSNode *vfs_decomp_locate(VFSNode *dirnode, const char *path) { vfs_decref(child); child = ochild; } else { - data.compr_zstd = true; + zstd = true; if(ochild) { vfs_decref(ochild); @@ -106,7 +105,10 @@ static VFSNode *vfs_decomp_locate(VFSNode *dirnode, const char *path) { VFSNode *wrapped_child = NOT_NULL(vfs_decomp_wrap(child)); vfs_decref(child); - memcpy(&wrapped_child->data2, &data, sizeof(data)); + + if(zstd) { + VFS_NODE_CAST(VFSDecompNode, wrapped_child)->compr_zstd = true; + } return wrapped_child; } @@ -117,16 +119,13 @@ static SDL_RWops *vfs_decomp_open(VFSNode *filenode, VFSOpenMode mode) { return NULL; } - struct decomp_data data; - memcpy(&data, &filenode->data2, sizeof(data)); - SDL_RWops *raw = vfs_node_open(WRAPPED(filenode), mode); if(!raw) { return NULL; } - if(data.compr_zstd) { + if(VFS_NODE_CAST(VFSDecompNode, filenode)->compr_zstd) { return SDL_RWWrapZstdReaderSeekable(raw, -1, true); } @@ -203,7 +202,7 @@ static void vfs_decomp_iter_stop(VFSNode *node, void **opaque) { } } -static VFSNodeFuncs vfs_funcs_decomp = { +VFS_NODE_FUNCS(VFSDecompNode, { .repr = vfs_decomp_repr, .query = vfs_decomp_query, .free = vfs_decomp_free, @@ -215,7 +214,7 @@ static VFSNodeFuncs vfs_funcs_decomp = { .open = vfs_decomp_open, .mount = vfs_decomp_mount, .unmount = vfs_decomp_unmount, -}; +}); VFSNode *vfs_decomp_wrap(VFSNode *base) { if(base == NULL) { @@ -224,10 +223,9 @@ VFSNode *vfs_decomp_wrap(VFSNode *base) { vfs_incref(base); - VFSNode *wrapper = vfs_alloc(); - wrapper->funcs = &vfs_funcs_decomp; - wrapper->data1 = base; - return wrapper; + return &VFS_ALLOC(VFSDecompNode, { + .wrapped = base, + })->as_generic; } bool vfs_make_decompress_view(const char *path) { @@ -252,7 +250,7 @@ bool vfs_make_decompress_view(const char *path) { return false; } - if(node->funcs == &vfs_funcs_decomp) { + if(VFS_NODE_TRY_CAST(VFSDecompNode, node)) { vfs_decref(node); vfs_decref(parent); return true; diff --git a/src/vfs/meson.build b/src/vfs/meson.build index 3170fa5f..2f9436eb 100644 --- a/src/vfs/meson.build +++ b/src/vfs/meson.build @@ -9,7 +9,6 @@ vfs_src = files( 'readonly_wrapper.c', 'syspath_public.c', 'union.c', - 'union_public.c', 'vdir.c', 'zipfile_public.c', ) @@ -18,6 +17,7 @@ if dep_zip.found() vfs_src += files( 'zipfile.c', 'zippath.c', + 'zippath_rwops.c', ) else vfs_src += files( diff --git a/src/vfs/nodeapi.c b/src/vfs/nodeapi.c index c80a3931..d277a7b5 100644 --- a/src/vfs/nodeapi.c +++ b/src/vfs/nodeapi.c @@ -18,7 +18,7 @@ VFSInfo vfs_node_query(VFSNode *node) { return node->funcs->query(node); } -VFSNode* vfs_node_locate(VFSNode *root, const char *path) { +VFSNode *vfs_node_locate(VFSNode *root, const char *path) { assert(root->funcs != NULL); #ifndef NDEBUG @@ -36,7 +36,7 @@ VFSNode* vfs_node_locate(VFSNode *root, const char *path) { return root->funcs->locate(root, path); } -const char* vfs_node_iter(VFSNode *node, void **opaque) { +const char *vfs_node_iter(VFSNode *node, void **opaque) { assert(node->funcs != NULL); if(node->funcs->iter != NULL) { @@ -56,7 +56,7 @@ void vfs_node_iter_stop(VFSNode *node, void **opaque) { } } -char* vfs_node_syspath(VFSNode *node) { +char *vfs_node_syspath(VFSNode *node) { assert(node->funcs != NULL); if(node->funcs->syspath == NULL) { @@ -67,7 +67,7 @@ char* vfs_node_syspath(VFSNode *node) { return node->funcs->syspath(node); } -char* vfs_node_repr(VFSNode *node, bool try_syspath) { +char *(vfs_node_repr)(VFSNode *node, bool try_syspath) { assert(node->funcs != NULL); assert(node->funcs->repr != NULL); char *r; @@ -122,7 +122,7 @@ bool vfs_node_mkdir(VFSNode *parent, const char *subdir) { return parent->funcs->mkdir(parent, subdir); } -SDL_RWops* vfs_node_open(VFSNode *filenode, VFSOpenMode mode) { +SDL_RWops *vfs_node_open(VFSNode *filenode, VFSOpenMode mode) { assert(filenode->funcs != NULL); if(filenode->funcs->open == NULL) { diff --git a/src/vfs/private.c b/src/vfs/private.c index a344e351..8aa82795 100644 --- a/src/vfs/private.c +++ b/src/vfs/private.c @@ -55,9 +55,7 @@ static vfs_tls_t* vfs_tls_get(void) { } void vfs_init(void) { - vfs_root = vfs_alloc(); - vfs_vdir_init(vfs_root); - + vfs_root = vfs_vdir_create(); vfs_tls_id = SDL_TLSCreate(); if(vfs_tls_id) { @@ -95,12 +93,6 @@ void vfs_hook_on_shutdown(VFSShutdownHandler func, void *arg) { })); } -VFSNode* vfs_alloc(void) { - auto node = ALLOC(VFSNode); - vfs_incref(node); - return node; -} - static void vfs_free(VFSNode *node) { if(!node) { return; @@ -113,11 +105,11 @@ static void vfs_free(VFSNode *node) { mem_free(node); } -void vfs_incref(VFSNode *node) { +void (vfs_incref)(VFSNode *node) { SDL_AtomicIncRef(&node->refcount); } -bool vfs_decref(VFSNode *node) { +bool (vfs_decref)(VFSNode *node) { if(!node) { return true; } @@ -130,7 +122,7 @@ bool vfs_decref(VFSNode *node) { return false; } -VFSNode* vfs_locate(VFSNode *root, const char *path) { +VFSNode *(vfs_locate)(VFSNode *root, const char *path) { if(!*path) { vfs_incref(root); return root; diff --git a/src/vfs/private.h b/src/vfs/private.h index 63611dc3..e9c5a0a4 100644 --- a/src/vfs/private.h +++ b/src/vfs/private.h @@ -38,34 +38,98 @@ struct VFSNodeFuncs { }; struct VFSNode { - VFSNodeFuncs *funcs; + char as_generic[0]; + const VFSNodeFuncs *funcs; SDL_atomic_t refcount; - void *data1; - void *data2; }; +#define VFS_NODE_TYPE_FUNCS_NAME(_typename) _vfs_funcs_##_typename + +#define VFS_NODE_TYPE(_typename, ...) \ + typedef struct _typename { \ + VFSNode as_generic; \ + struct __VA_ARGS__; \ + } _typename; \ + extern const VFSNodeFuncs VFS_NODE_TYPE_FUNCS_NAME(_typename) + +#define VFS_NODE_FUNCS(_typename, ...) \ + const VFSNodeFuncs VFS_NODE_TYPE_FUNCS_NAME(_typename) = __VA_ARGS__ + +#define IS_OF_VFS_NODE_BASE_TYPE(_node) \ + __builtin_types_compatible_p(VFSNode, typeof(*(_node))) + +#define IS_OF_VFS_NODE_DERIVED_TYPE(_node) \ + (__builtin_types_compatible_p(VFSNode, typeof((_node)->as_generic)) \ + && offsetof(typeof(*(_node)), as_generic) == 0) + +#define IS_OF_VFS_NODE_TYPE(_node) \ + IS_OF_VFS_NODE_BASE_TYPE(_node) || IS_OF_VFS_NODE_DERIVED_TYPE(_node) + +#define VFS_NODE_ASSERT_VALID(_node) \ + static_assert(IS_OF_VFS_NODE_TYPE(_node), "Expected a VFSNode or derived type") + +#define VFS_NODE_AS_BASE(_node) ({ \ + VFS_NODE_ASSERT_VALID(_node); \ + __builtin_choose_expr(IS_OF_VFS_NODE_BASE_TYPE(_node), (_node), &(_node)->as_generic); \ +}) + +#define VFS_NODE_TRY_CAST(_typename, _node) ({ \ + VFSNode *_base_node = _node; \ + static_assert(IS_OF_VFS_NODE_DERIVED_TYPE( (&(_typename){}) ), \ + "Typename must be of a VFSNode-derived type"); \ + _typename* _n = UNION_CAST(VFSNode*, _typename*, NOT_NULL(_base_node)); \ + LIKELY(_n->as_generic.funcs == &VFS_NODE_TYPE_FUNCS_NAME(_typename))? _n : NULL; \ +}) + +#define VFS_NODE_CAST(_typename, _node) \ + NOT_NULL(VFS_NODE_TRY_CAST(_typename, _node)) + +#define VFS_ALLOC(_typename, ...) ({ \ + auto _node = ALLOC(_typename, ##__VA_ARGS__); \ + static_assert(IS_OF_VFS_NODE_DERIVED_TYPE(_node), \ + "Typename must be of a VFSNode-derived type"); \ + _node->as_generic.funcs = &VFS_NODE_TYPE_FUNCS_NAME(_typename); \ + vfs_incref(_node); \ + _node; \ +}) + + extern VFSNode *vfs_root; -VFSNode* vfs_alloc(void); void vfs_incref(VFSNode *node) attr_nonnull(1); bool vfs_decref(VFSNode *node); bool vfs_mount(VFSNode *root, const char *mountpoint, VFSNode *subtree) attr_nonnull(1, 3) attr_nodiscard; bool vfs_mount_or_decref(VFSNode *root, const char *mountpoint, VFSNode *subtree) attr_nonnull(1, 3) attr_nodiscard; -VFSNode* vfs_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nodiscard; +VFSNode *vfs_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nodiscard; // Light wrappers around the virtual functions, safe to call even on nodes that // don't implement the corresponding method. "free" is not included, there should // be no reason to call it. It wouldn't do what you'd expect anyway; use vfs_decref. -char* vfs_node_repr(VFSNode *node, bool try_syspath) attr_returns_allocated attr_nonnull(1); +char *vfs_node_repr(VFSNode *node, bool try_syspath) attr_returns_allocated attr_nonnull(1); VFSInfo vfs_node_query(VFSNode *node) attr_nonnull(1) attr_nodiscard attr_nonnull(1); -char* vfs_node_syspath(VFSNode *node) attr_nonnull(1) attr_returns_max_aligned attr_nodiscard attr_nonnull(1); +char *vfs_node_syspath(VFSNode *node) attr_nonnull(1) attr_returns_max_aligned attr_nodiscard attr_nonnull(1); bool vfs_node_mount(VFSNode *mountroot, const char *subname, VFSNode *mountee) attr_nonnull(1, 3); bool vfs_node_unmount(VFSNode *mountroot, const char *subname) attr_nonnull(1); -VFSNode* vfs_node_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nodiscard; -const char* vfs_node_iter(VFSNode *node, void **opaque) attr_nonnull(1); +VFSNode *vfs_node_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nodiscard; +const char *vfs_node_iter(VFSNode *node, void **opaque) attr_nonnull(1); void vfs_node_iter_stop(VFSNode *node, void **opaque) attr_nonnull(1); bool vfs_node_mkdir(VFSNode *parent, const char *subdir) attr_nonnull(1); -SDL_RWops* vfs_node_open(VFSNode *filenode, VFSOpenMode mode) attr_nonnull(1) attr_nodiscard; +SDL_RWops *vfs_node_open(VFSNode *filenode, VFSOpenMode mode) attr_nonnull(1) attr_nodiscard; + +// NOTE: convenience wrappers added on demand + +#define vfs_incref(node) \ + vfs_incref(VFS_NODE_AS_BASE(node)) + +#define vfs_decref(node) \ + vfs_decref(VFS_NODE_AS_BASE(node)) + +#define vfs_locate(root, path) \ + vfs_locate(VFS_NODE_AS_BASE(root), path) + +#define vfs_node_repr(node, try_syspath) \ + vfs_node_repr(VFS_NODE_AS_BASE(node), try_syspath) + void vfs_hook_on_shutdown(VFSShutdownHandler, void *arg); void vfs_print_tree_recurse(SDL_RWops *dest, VFSNode *root, char *prefix, const char *name) attr_nonnull(1, 2, 3, 4); diff --git a/src/vfs/readonly_wrapper.c b/src/vfs/readonly_wrapper.c index 97c3c42d..be2a42ef 100644 --- a/src/vfs/readonly_wrapper.c +++ b/src/vfs/readonly_wrapper.c @@ -12,9 +12,13 @@ #include "private.h" #include "rwops/rwops_ro.h" -#define WRAPPED(n) ((VFSNode*)(n)->data1) +VFS_NODE_TYPE(VFSReadOnlyNode, { + VFSNode *wrapped; +}); -static char* vfs_ro_repr(VFSNode *node) { +#define WRAPPED(n) VFS_NODE_CAST(VFSReadOnlyNode, n)->wrapped + +static char *vfs_ro_repr(VFSNode *node) { char *wrapped_repr = vfs_node_repr(WRAPPED(node), false); char *repr = strjoin("read-only view of ", wrapped_repr, NULL); mem_free(wrapped_repr); @@ -80,7 +84,7 @@ static SDL_RWops* vfs_ro_open(VFSNode *filenode, VFSOpenMode mode) { return SDL_RWWrapReadOnly(vfs_node_open(WRAPPED(filenode), mode), true); } -static VFSNodeFuncs vfs_funcs_ro = { +VFS_NODE_FUNCS(VFSReadOnlyNode, { .repr = vfs_ro_repr, .query = vfs_ro_query, .free = vfs_ro_free, @@ -92,9 +96,9 @@ static VFSNodeFuncs vfs_funcs_ro = { .open = vfs_ro_open, .mount = vfs_ro_mount, .unmount = vfs_ro_unmount, -}; +}); -VFSNode* vfs_ro_wrap(VFSNode *base) { +VFSNode *vfs_ro_wrap(VFSNode *base) { if(base == NULL) { return NULL; } @@ -106,10 +110,9 @@ VFSNode* vfs_ro_wrap(VFSNode *base) { return base; } - VFSNode *wrapper = vfs_alloc(); - wrapper->funcs = &vfs_funcs_ro; - wrapper->data1 = base; - return wrapper; + return &VFS_ALLOC(VFSReadOnlyNode, { + .wrapped = base, + })->as_generic; } bool vfs_make_readonly(const char *path) { diff --git a/src/vfs/syspath.h b/src/vfs/syspath.h index f17b31c4..a3845922 100644 --- a/src/vfs/syspath.h +++ b/src/vfs/syspath.h @@ -13,4 +13,4 @@ #include "syspath_public.h" extern char *vfs_syspath_separators; -bool vfs_syspath_init(VFSNode *node, const char *path); +VFSNode *vfs_syspath_create(const char *path); diff --git a/src/vfs/syspath_posix.c b/src/vfs/syspath_posix.c index ac8d831f..8d7fe139 100644 --- a/src/vfs/syspath_posix.c +++ b/src/vfs/syspath_posix.c @@ -16,21 +16,23 @@ #include "syspath.h" -#define _path_ data1 +VFS_NODE_TYPE(VFSSysPathNode, { + char *path; +}); char *vfs_syspath_separators = "/"; -static void vfs_syspath_init_internal(VFSNode *node, char *path); +static VFSNode *vfs_syspath_create_internal(char *path); static void vfs_syspath_free(VFSNode *node) { - mem_free(node->_path_); + mem_free(VFS_NODE_CAST(VFSSysPathNode, node)->path); } static VFSInfo vfs_syspath_query(VFSNode *node) { struct stat fstat; VFSInfo i = {0}; - if(stat(node->_path_, &fstat) >= 0) { + if(stat(VFS_NODE_CAST(VFSSysPathNode, node)->path, &fstat) >= 0) { i.exists = true; i.is_dir = S_ISDIR(fstat.st_mode); } @@ -38,9 +40,10 @@ static VFSInfo vfs_syspath_query(VFSNode *node) { return i; } -static SDL_RWops* vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { +static SDL_RWops *vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { mode &= VFS_MODE_RWMASK; - SDL_RWops *rwops = SDL_RWFromFile(node->_path_, mode == VFS_MODE_WRITE ? "w" : "r"); + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + SDL_RWops *rwops = SDL_RWFromFile(pnode->path, mode == VFS_MODE_WRITE ? "w" : "r"); if(!rwops) { vfs_set_error_from_sdl(); @@ -49,18 +52,17 @@ static SDL_RWops* vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { return rwops; } -static VFSNode* vfs_syspath_locate(VFSNode *node, const char *path) { - VFSNode *n = vfs_alloc(); - vfs_syspath_init_internal(n, strfmt("%s%c%s", (char*)node->_path_, VFS_PATH_SEPARATOR, path)); - return n; +static VFSNode *vfs_syspath_locate(VFSNode *node, const char *path) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + return vfs_syspath_create_internal(strjoin(pnode->path, "/", path, NULL)); } -static const char* vfs_syspath_iter(VFSNode *node, void **opaque) { +static const char *vfs_syspath_iter(VFSNode *node, void **opaque) { DIR *dir; struct dirent *e; if(!*opaque) { - *opaque = opendir(node->_path_); + *opaque = opendir(VFS_NODE_CAST(VFSSysPathNode, node)->path); } if(!(dir = *opaque)) { @@ -87,12 +89,13 @@ static void vfs_syspath_iter_stop(VFSNode *node, void **opaque) { } } -static char* vfs_syspath_repr(VFSNode *node) { - return strfmt("filesystem path (posix): %s", (char*)node->_path_); +static char *vfs_syspath_repr(VFSNode *node) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + return strfmt("filesystem path (posix): %s", pnode->path); } -static char* vfs_syspath_syspath(VFSNode *node) { - char *p = strdup(node->_path_); +static char *vfs_syspath_syspath(VFSNode *node) { + char *p = strdup(VFS_NODE_CAST(VFSSysPathNode, node)->path); vfs_syspath_normalize_inplace(p); return p; } @@ -102,7 +105,8 @@ static bool vfs_syspath_mkdir(VFSNode *node, const char *subdir) { subdir = ""; } - char *p = strfmt("%s%c%s", (char*)node->_path_, VFS_PATH_SEPARATOR, subdir); + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + char *p = strjoin(pnode->path, VFS_PATH_SEPARATOR_STR, subdir, NULL); bool ok = !mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if(!ok && errno == EEXIST) { @@ -125,7 +129,7 @@ static bool vfs_syspath_mkdir(VFSNode *node, const char *subdir) { return ok; } -static VFSNodeFuncs vfs_funcs_syspath = { +VFS_NODE_FUNCS(VFSSysPathNode, { .repr = vfs_syspath_repr, .query = vfs_syspath_query, .free = vfs_syspath_free, @@ -135,7 +139,7 @@ static VFSNodeFuncs vfs_funcs_syspath = { .iter_stop = vfs_syspath_iter_stop, .mkdir = vfs_syspath_mkdir, .open = vfs_syspath_open, -}; +}); void vfs_syspath_normalize(char *buf, size_t bufsize, const char *path) { char *bufptr = buf; @@ -174,13 +178,13 @@ void vfs_syspath_join(char *buf, size_t bufsize, const char *parent, const char } } -static void vfs_syspath_init_internal(VFSNode *node, char *path) { +static VFSNode *vfs_syspath_create_internal(char *path) { vfs_syspath_normalize_inplace(path); - node->funcs = &vfs_funcs_syspath; - node->_path_ = path; + return &VFS_ALLOC(VFSSysPathNode, { + .path = path, + })->as_generic; } -bool vfs_syspath_init(VFSNode *node, const char *path) { - vfs_syspath_init_internal(node, strdup(path)); - return true; +VFSNode *vfs_syspath_create(const char *path) { + return vfs_syspath_create_internal(strdup(path)); } diff --git a/src/vfs/syspath_public.c b/src/vfs/syspath_public.c index 2eb6b340..58098cbb 100644 --- a/src/vfs/syspath_public.c +++ b/src/vfs/syspath_public.c @@ -41,9 +41,8 @@ static bool mkdir_with_parents(VFSNode *n, const char *fspath) { return false; } - VFSNode *pnode = vfs_alloc(); - if(!vfs_syspath_init(pnode, p)) { - vfs_decref(pnode); + VFSNode *pnode; + if(!(pnode = vfs_syspath_create(p))) { return false; } @@ -53,9 +52,9 @@ static bool mkdir_with_parents(VFSNode *n, const char *fspath) { } bool vfs_mount_syspath(const char *mountpoint, const char *fspath, uint flags) { - VFSNode *rdir = vfs_alloc(); + VFSNode *rdir; - if(!vfs_syspath_init(rdir, fspath)) { + if(!(rdir = vfs_syspath_create(fspath))) { vfs_set_error("Can't initialize path: %s", vfs_get_error()); vfs_decref(rdir); return false; diff --git a/src/vfs/syspath_win32.c b/src/vfs/syspath_win32.c index eefa774f..2ba0436f 100644 --- a/src/vfs/syspath_win32.c +++ b/src/vfs/syspath_win32.c @@ -14,8 +14,10 @@ #include "syspath.h" -#define _path_ data1 -#define _wpath_ data2 +VFS_NODE_TYPE(VFSSysPathNode, { + char *path; + wchar_t *wpath; +}); char *vfs_syspath_separators = "\\/"; @@ -39,11 +41,12 @@ static WCHAR *WIN_UTF8ToString(char *s) { return buf; } -static bool vfs_syspath_init_internal(VFSNode *node, char *path); +static VFSNode *vfs_syspath_create_internal(char *path); static void vfs_syspath_free(VFSNode *node) { - mem_free(node->_path_); - mem_free(node->_wpath_); + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + mem_free(pnode->path); + mem_free(pnode->wpath); } static void _vfs_set_error_win32(const char *file, int line) { @@ -70,14 +73,15 @@ static void _vfs_set_error_win32(const char *file, int line) { #define vfs_set_error_win32() _vfs_set_error_win32(_TAISEI_SRC_FILE, __LINE__) static VFSInfo vfs_syspath_query(VFSNode *node) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); VFSInfo i = {0}; - if(!PathFileExists(node->_wpath_)) { + if(!PathFileExists(pnode->wpath)) { i.exists = false; return i; } - DWORD attrib = GetFileAttributes(node->_wpath_); + DWORD attrib = GetFileAttributes(pnode->wpath); if(attrib == INVALID_FILE_ATTRIBUTES) { vfs_set_error_win32(); @@ -90,9 +94,10 @@ static VFSInfo vfs_syspath_query(VFSNode *node) { return i; } -static SDL_RWops* vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { +static SDL_RWops *vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); mode &= VFS_MODE_RWMASK; - SDL_RWops *rwops = SDL_RWFromFile(node->_path_, mode == VFS_MODE_WRITE ? "w" : "r"); + SDL_RWops *rwops = SDL_RWFromFile(pnode->path, mode == VFS_MODE_WRITE ? "w" : "r"); if(!rwops) { vfs_set_error_from_sdl(); @@ -101,18 +106,9 @@ static SDL_RWops* vfs_syspath_open(VFSNode *node, VFSOpenMode mode) { return rwops; } -static VFSNode* vfs_syspath_locate(VFSNode *node, const char *path) { - VFSNode *n = vfs_alloc(); - char buf[strlen(path)+1], *base, *name; - strcpy(buf, path); - vfs_path_split_right(buf, &base, &name); - - if(!vfs_syspath_init_internal(n, strfmt("%s%c%s", (char*)node->_path_, '\\', path))) { - vfs_decref(n); - return NULL; - } - - return n; +static VFSNode *vfs_syspath_locate(VFSNode *node, const char *path) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + return vfs_syspath_create_internal(strjoin(pnode->path, "\\", path, NULL)); } typedef struct VFSWin32IterData { @@ -121,12 +117,13 @@ typedef struct VFSWin32IterData { } VFSWin32IterData; static const char* vfs_syspath_iter(VFSNode *node, void **opaque) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); VFSWin32IterData *idata; WIN32_FIND_DATA fdata; HANDLE search_handle; if(!*opaque) { - char *pattern = strjoin(node->_path_, "\\*.*", NULL); + char *pattern = strjoin(pnode->path, "\\*.*", NULL); wchar_t *wpattern = WIN_UTF8ToString(pattern); mem_free(pattern); search_handle = FindFirstFile(wpattern, &fdata); @@ -185,21 +182,25 @@ static void vfs_syspath_iter_stop(VFSNode *node, void **opaque) { } static char* vfs_syspath_repr(VFSNode *node) { - return strfmt("filesystem path (win32): %s", (char*)node->_path_); + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + return strfmt("filesystem path (win32): %s", pnode->path); } static char* vfs_syspath_syspath(VFSNode *node) { - char *p = strdup(node->_path_); + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + char *p = strdup(pnode->path); vfs_syspath_normalize_inplace(p); return p; } static bool vfs_syspath_mkdir(VFSNode *node, const char *subdir) { + auto pnode = VFS_NODE_CAST(VFSSysPathNode, node); + if(!subdir) { subdir = ""; } - char *p = strfmt("%s%c%s", (char*)node->_path_, '\\', subdir); + char *p = strjoin(pnode->path, "\\", subdir, NULL); wchar_t *wp = WIN_UTF8ToString(p); bool ok = CreateDirectory(wp, NULL); DWORD err = GetLastError(); @@ -225,7 +226,7 @@ static bool vfs_syspath_mkdir(VFSNode *node, const char *subdir) { return ok; } -static VFSNodeFuncs vfs_funcs_syspath = { +VFS_NODE_FUNCS(VFSSysPathNode, { .repr = vfs_syspath_repr, .query = vfs_syspath_query, .free = vfs_syspath_free, @@ -235,7 +236,7 @@ static VFSNodeFuncs vfs_funcs_syspath = { .iter_stop = vfs_syspath_iter_stop, .mkdir = vfs_syspath_mkdir, .open = vfs_syspath_open, -}; +}); void vfs_syspath_normalize(char *buf, size_t bufsize, const char *path) { // here we just remove redundant separators and convert forward slashes to back slashes. @@ -308,20 +309,19 @@ static bool vfs_syspath_validate(char *path) { return true; } -static bool vfs_syspath_init_internal(VFSNode *node, char *path) { +static VFSNode *vfs_syspath_create_internal(char *path) { vfs_syspath_normalize_inplace(path); if(!vfs_syspath_validate(path)) { - return false; + return NULL; } - node->funcs = &vfs_funcs_syspath; - node->_path_ = path; - node->_wpath_ = WIN_UTF8ToString(path); - - return true; + return &VFS_ALLOC(VFSSysPathNode, { + .path = path, + .wpath = WIN_UTF8ToString(path), + })->as_generic; } -bool vfs_syspath_init(VFSNode *node, const char *path) { - return vfs_syspath_init_internal(node, strdup(path)); +VFSNode *vfs_syspath_create(const char *path) { + return vfs_syspath_create_internal(strdup(path)); } diff --git a/src/vfs/union.c b/src/vfs/union.c index d6e3aca6..cf3b6ee2 100644 --- a/src/vfs/union.c +++ b/src/vfs/union.c @@ -10,12 +10,16 @@ #include "union.h" -#define _members_ data1 -#define _primary_member_ data2 +// TODO rewrite this to use more sensible data structures -static bool vfs_union_mount_internal(VFSNode *unode, const char *mountpoint, VFSNode *mountee, VFSInfo info, bool seterror); +VFS_NODE_TYPE(VFSUnionNode, { + ListContainer *members; + VFSNode *primary_member; +}); -static void* vfs_union_delete_callback(List **list, List *elem, void *arg) { +static bool vfs_union_mount_internal(VFSUnionNode *unode, const char *mountpoint, VFSNode *mountee, VFSInfo info, bool seterror); + +static void *vfs_union_delete_callback(List **list, List *elem, void *arg) { ListContainer *c = (ListContainer*)elem; VFSNode *n = c->data; vfs_decref(n); @@ -24,15 +28,16 @@ static void* vfs_union_delete_callback(List **list, List *elem, void *arg) { } static void vfs_union_free(VFSNode *node) { - list_foreach((ListContainer**)&node->_members_, vfs_union_delete_callback, NULL); + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + list_foreach(&unode->members, vfs_union_delete_callback, NULL); } -static VFSNode* vfs_union_locate(VFSNode *node, const char *path) { - VFSNode *u = vfs_alloc(); - vfs_union_init(u); // uniception! +static VFSNode *vfs_union_locate(VFSNode *node, const char *path) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + auto subunion = VFS_NODE_CAST(VFSUnionNode, vfs_union_create()); VFSInfo prim_info = VFSINFO_ERROR; - ListContainer *first = node->_members_; + ListContainer *first = unode->members; ListContainer *last = first; ListContainer *c; @@ -47,7 +52,7 @@ static VFSNode* vfs_union_locate(VFSNode *node, const char *path) { if(o) { VFSInfo i = vfs_node_query(o); - if(vfs_union_mount_internal(u, NULL, o, i, false)) { + if(vfs_union_mount_internal(subunion, NULL, o, i, false)) { prim_info = i; } else { vfs_decref(o); @@ -55,28 +60,28 @@ static VFSNode* vfs_union_locate(VFSNode *node, const char *path) { } } - if(u->_primary_member_) { - if(!((List*)(u->_members_))->next || !prim_info.is_dir) { + if(subunion->primary_member) { + if(!subunion->members->next || !prim_info.is_dir) { // the temporary union contains just one member, or doesn't represent a directory // in those cases it's just a useless wrapper, so let's just return the primary member directly - VFSNode *n = u->_primary_member_; + VFSNode *n = subunion->primary_member; // incref primary member to keep it alive vfs_incref(n); // destroy the wrapper, also decrefs n - vfs_decref(u); + vfs_decref(subunion); // no need to incref n, vfs_locate did that for us earlier return n; } } else { // all in vain... - vfs_decref(u); - u = NULL; + vfs_decref(subunion); + return NULL; } - return u; + return &subunion->as_generic; } typedef struct VFSUnionIterData { @@ -86,12 +91,13 @@ typedef struct VFSUnionIterData { } VFSUnionIterData; static const char* vfs_union_iter(VFSNode *node, void **opaque) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); VFSUnionIterData *i = *opaque; const char *r = NULL; if(!i) { i = ALLOC(typeof(*i)); - i->current = node->_members_; + i->current = unode->members; i->opaque = NULL; ht_create(&i->visited); *opaque = i; @@ -131,8 +137,10 @@ static void vfs_union_iter_stop(VFSNode *node, void **opaque) { } static VFSInfo vfs_union_query(VFSNode *node) { - if(node->_primary_member_) { - VFSInfo i = vfs_node_query(node->_primary_member_); + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + + if(unode->primary_member) { + VFSInfo i = vfs_node_query(unode->primary_member); // can't trust the primary member here, others might be writable' i.is_readonly = false; return i; @@ -142,7 +150,7 @@ static VFSInfo vfs_union_query(VFSNode *node) { return VFSINFO_ERROR; } -static bool vfs_union_mount_internal(VFSNode *unode, const char *mountpoint, VFSNode *mountee, VFSInfo info, bool seterror) { +static bool vfs_union_mount_internal(VFSUnionNode *unode, const char *mountpoint, VFSNode *mountee, VFSInfo info, bool seterror) { if(!info.exists) { if(seterror) { char *r = vfs_node_repr(mountee, true); @@ -160,13 +168,15 @@ static bool vfs_union_mount_internal(VFSNode *unode, const char *mountpoint, VFS return false; } - list_push((ListContainer**)&unode->_members_, list_wrap_container(mountee)); - unode->_primary_member_ = mountee; + list_push(&unode->members, list_wrap_container(mountee)); + unode->primary_member = mountee; return true; } -static bool vfs_union_mount(VFSNode *unode, const char *mountpoint, VFSNode *mountee) { +static bool vfs_union_mount(VFSNode *node, const char *mountpoint, VFSNode *mountee) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + if(mountpoint) { vfs_set_error("Attempted to use a named mountpoint '%s' on a union", mountpoint); return false; @@ -175,8 +185,9 @@ static bool vfs_union_mount(VFSNode *unode, const char *mountpoint, VFSNode *mou return vfs_union_mount_internal(unode, NULL, mountee, vfs_node_query(mountee), true); } -static SDL_RWops* vfs_union_open(VFSNode *unode, VFSOpenMode mode) { - VFSNode *n = unode->_primary_member_; +static SDL_RWops* vfs_union_open(VFSNode *node, VFSOpenMode mode) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + VFSNode *n = unode->primary_member; if(n) { return vfs_node_open(n, mode); @@ -187,10 +198,11 @@ static SDL_RWops* vfs_union_open(VFSNode *unode, VFSOpenMode mode) { return NULL; } -static char* vfs_union_repr(VFSNode *node) { +static char *vfs_union_repr(VFSNode *node) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); char *mlist = strdup("union: "), *r; - for(ListContainer *c = node->_members_; c; c = c->next) { + for(ListContainer *c = unode->members; c; c = c->next) { VFSNode *n = c->data; strappend(&mlist, r = vfs_node_repr(n, false)); @@ -204,8 +216,9 @@ static char* vfs_union_repr(VFSNode *node) { return mlist; } -static char* vfs_union_syspath(VFSNode *node) { - VFSNode *n = node->_primary_member_; +static char *vfs_union_syspath(VFSNode *node) { + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + VFSNode *n = unode->primary_member; if(n) { return vfs_node_syspath(n); @@ -216,7 +229,8 @@ static char* vfs_union_syspath(VFSNode *node) { } static bool vfs_union_mkdir(VFSNode *node, const char *subdir) { - VFSNode *n = node->_primary_member_; + auto unode = VFS_NODE_CAST(VFSUnionNode, node); + VFSNode *n = unode->primary_member; if(n) { return vfs_node_mkdir(n, subdir); @@ -226,7 +240,7 @@ static bool vfs_union_mkdir(VFSNode *node, const char *subdir) { return false; } -static VFSNodeFuncs vfs_funcs_union = { +VFS_NODE_FUNCS(VFSUnionNode, { .repr = vfs_union_repr, .query = vfs_union_query, .free = vfs_union_free, @@ -237,9 +251,12 @@ static VFSNodeFuncs vfs_funcs_union = { .iter_stop = vfs_union_iter_stop, .mkdir = vfs_union_mkdir, .open = vfs_union_open, -}; +}); -void vfs_union_init(VFSNode *node) { - node->funcs = &vfs_funcs_union; - node->data1 = node->data2 = NULL; +VFSNode *vfs_union_create(void) { + return &VFS_ALLOC(VFSUnionNode)->as_generic; +} + +bool vfs_create_union_mountpoint(const char *mountpoint) { + return vfs_mount_or_decref(vfs_root, mountpoint, vfs_union_create()); } diff --git a/src/vfs/union.h b/src/vfs/union.h index 62de95f7..168b244c 100644 --- a/src/vfs/union.h +++ b/src/vfs/union.h @@ -12,4 +12,4 @@ #include "private.h" #include "union_public.h" -void vfs_union_init(VFSNode *node); +VFSNode *vfs_union_create(void); diff --git a/src/vfs/union_public.c b/src/vfs/union_public.c deleted file mode 100644 index 9ab4aba1..00000000 --- a/src/vfs/union_public.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This software is licensed under the terms of the MIT License. - * See COPYING for further information. - * --- - * Copyright (c) 2011-2019, Lukas Weber . - * Copyright (c) 2012-2019, Andrei Alexeyev . - */ - -#include "taisei.h" - -#include "union.h" - -bool vfs_create_union_mountpoint(const char *mountpoint) { - VFSNode *unode = vfs_alloc(); - vfs_union_init(unode); - return vfs_mount_or_decref(vfs_root, mountpoint, unode); -} diff --git a/src/vfs/vdir.c b/src/vfs/vdir.c index a1e693a8..11e6c088 100644 --- a/src/vfs/vdir.c +++ b/src/vfs/vdir.c @@ -10,39 +10,44 @@ #include "vdir.h" -#define VDIR_TABLE(vdir) ((ht_str2ptr_t*)((vdir)->data1)) +VFS_NODE_TYPE(VFSVDirNode, { + ht_str2ptr_t table; +}); -static void vfs_vdir_attach_node(VFSNode *vdir, const char *name, VFSNode *node) { - VFSNode *oldnode = ht_get(VDIR_TABLE(vdir), name, NULL); +static void vfs_vdir_attach_node(VFSNode *node, const char *name, VFSNode *subnode) { + auto vdir = VFS_NODE_CAST(VFSVDirNode, node); + VFSNode *oldnode = ht_get(&vdir->table, name, NULL); if(oldnode) { vfs_decref(oldnode); } - ht_set(VDIR_TABLE(vdir), name, node); + ht_set(&vdir->table, name, subnode); } -static VFSNode* vfs_vdir_locate(VFSNode *vdir, const char *path) { - VFSNode *node; +static VFSNode *vfs_vdir_locate(VFSNode *node, const char *path) { + auto vdir = VFS_NODE_CAST(VFSVDirNode, node); + VFSNode *subnode; char mutpath[strlen(path)+1]; char *primpath, *subpath; strcpy(mutpath, path); vfs_path_split_left(mutpath, &primpath, &subpath); - if((node = ht_get(VDIR_TABLE(vdir), mutpath, NULL))) { - return vfs_locate(node, subpath); + if((subnode = ht_get(&vdir->table, primpath, NULL))) { + return vfs_locate(subnode, subpath); } return NULL; } -static const char* vfs_vdir_iter(VFSNode *vdir, void **opaque) { +static const char *vfs_vdir_iter(VFSNode *node, void **opaque) { + auto vdir = VFS_NODE_CAST(VFSVDirNode, node); ht_str2ptr_iter_t *iter = *opaque; if(!iter) { iter = *opaque = ALLOC(typeof(*iter)); - ht_iter_begin(VDIR_TABLE(vdir), iter); + ht_iter_begin(&vdir->table, iter); } else { ht_iter_next(iter); } @@ -50,7 +55,7 @@ static const char* vfs_vdir_iter(VFSNode *vdir, void **opaque) { return iter->has_data ? iter->key : NULL; } -static void vfs_vdir_iter_stop(VFSNode *vdir, void **opaque) { +static void vfs_vdir_iter_stop(VFSNode *node, void **opaque) { if(*opaque) { ht_iter_end((ht_str2ptr_iter_t*)*opaque); mem_free(*opaque); @@ -58,26 +63,26 @@ static void vfs_vdir_iter_stop(VFSNode *vdir, void **opaque) { } } -static VFSInfo vfs_vdir_query(VFSNode *vdir) { +static VFSInfo vfs_vdir_query(VFSNode *node) { return (VFSInfo) { .exists = true, .is_dir = true, }; } -static void vfs_vdir_free(VFSNode *vdir) { - ht_str2ptr_t *ht = VDIR_TABLE(vdir); +static void vfs_vdir_free(VFSNode *node) { + auto vdir = VFS_NODE_CAST(VFSVDirNode, node); + ht_str2ptr_t *ht = &vdir->table; ht_str2ptr_iter_t iter; ht_iter_begin(ht, &iter); for(; iter.has_data; ht_iter_next(&iter)) { - vfs_decref(iter.value); + vfs_decref((VFSNode*)iter.value); } ht_iter_end(&iter); ht_destroy(ht); - mem_free(ht); } static bool vfs_vdir_mount(VFSNode *vdir, const char *mountpoint, VFSNode *subtree) { @@ -90,37 +95,29 @@ static bool vfs_vdir_mount(VFSNode *vdir, const char *mountpoint, VFSNode *subtr return true; } -static bool vfs_vdir_unmount(VFSNode *vdir, const char *mountpoint) { +static bool vfs_vdir_unmount(VFSNode *node, const char *mountpoint) { + auto vdir = VFS_NODE_CAST(VFSVDirNode, node); VFSNode *mountee; - if(!(mountee = ht_get(VDIR_TABLE(vdir), mountpoint, NULL))) { + if(!(mountee = ht_get(&vdir->table, mountpoint, NULL))) { vfs_set_error("Mountpoint '%s' doesn't exist", mountpoint); return false; } - ht_unset(VDIR_TABLE(vdir), mountpoint); + ht_unset(&vdir->table, mountpoint); vfs_decref(mountee); return true; } static bool vfs_vdir_mkdir(VFSNode *node, const char *subdir) { - if(!subdir) { - vfs_set_error("Virtual directory trying to create itself? How did you even get here?"); - return false; - } - - VFSNode *subnode = vfs_alloc(); - vfs_vdir_init(subnode); - vfs_vdir_mount(node, subdir, subnode); - - return true; + return vfs_vdir_mount(node, NOT_NULL(subdir), vfs_vdir_create()); } -static char* vfs_vdir_repr(VFSNode *node) { +static char *vfs_vdir_repr(VFSNode *node) { return strdup("virtual directory"); } -static VFSNodeFuncs vfs_funcs_vdir = { +VFS_NODE_FUNCS(VFSVDirNode, { .repr = vfs_vdir_repr, .query = vfs_vdir_query, .free = vfs_vdir_free, @@ -130,9 +127,10 @@ static VFSNodeFuncs vfs_funcs_vdir = { .iter = vfs_vdir_iter, .iter_stop = vfs_vdir_iter_stop, .mkdir = vfs_vdir_mkdir, -}; +}); -void vfs_vdir_init(VFSNode *node) { - node->funcs = &vfs_funcs_vdir; - node->data1 = ht_str2ptr_new(); +VFSNode *vfs_vdir_create(void) { + auto vdir = VFS_ALLOC(VFSVDirNode); + ht_create(&vdir->table); + return &vdir->as_generic; } diff --git a/src/vfs/vdir.h b/src/vfs/vdir.h index 6f477ac3..a136804f 100644 --- a/src/vfs/vdir.h +++ b/src/vfs/vdir.h @@ -11,4 +11,5 @@ #include "private.h" -void vfs_vdir_init(VFSNode *node); +VFSNode *vfs_vdir_create(void) + attr_returns_allocated; diff --git a/src/vfs/zipfile.c b/src/vfs/zipfile.c index 65e31f21..7bef6cf9 100644 --- a/src/vfs/zipfile.c +++ b/src/vfs/zipfile.c @@ -14,10 +14,9 @@ #define LOG_SDL_ERROR log_debug("SDL error: %s", SDL_GetError()) static zip_int64_t vfs_zipfile_srcfunc(void *userdata, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { - VFSNode *zipnode = userdata; - VFSZipFileData *zdata = zipnode->data1; + VFSZipNode *zipnode = userdata; VFSZipFileTLS *tls = vfs_zipfile_get_tls(zipnode, false); - VFSNode *source = zdata->source; + VFSNode *source = zipnode->source; zip_int64_t ret = -1; if(!tls) { @@ -134,24 +133,19 @@ static void vfs_zipfile_free_tls(VFSZipFileTLS *tls) { static void vfs_zipfile_free(VFSNode *node) { if(node) { - VFSZipFileData *zdata = node->data1; + auto znode = VFS_NODE_CAST(VFSZipNode, node); + VFSZipFileTLS *tls = SDL_TLSGet(znode->tls_id); - if(zdata) { - SDL_TLSID tls_id = ((VFSZipFileData*)node->data1)->tls_id; - VFSZipFileTLS *tls = SDL_TLSGet(tls_id); - - if(tls) { - vfs_zipfile_free_tls(tls); - SDL_TLSSet(tls_id, NULL, NULL); - } - - if(zdata->source) { - vfs_decref(zdata->source); - } - - ht_destroy(&zdata->pathmap); - mem_free(zdata); + if(tls) { + vfs_zipfile_free_tls(tls); + SDL_TLSSet(znode->tls_id, NULL, NULL); } + + if(znode->source) { + vfs_decref(znode->source); + } + + ht_destroy(&znode->pathmap); } } @@ -163,25 +157,24 @@ static VFSInfo vfs_zipfile_query(VFSNode *node) { }; } -static char* vfs_zipfile_syspath(VFSNode *node) { - VFSZipFileData *zdata = node->data1; - return vfs_node_syspath(zdata->source); +static char *vfs_zipfile_syspath(VFSNode *node) { + return vfs_node_syspath(VFS_NODE_CAST(VFSZipNode, node)->source); } -static char* vfs_zipfile_repr(VFSNode *node) { - VFSZipFileData *zdata = node->data1; - char *srcrepr = vfs_node_repr(zdata->source, false); - char *ziprepr = strfmt("zip archive %s", srcrepr); +static char *vfs_zipfile_repr(VFSNode *node) { + auto znode = VFS_NODE_CAST(VFSZipNode, node); + char *srcrepr = vfs_node_repr(znode->source, false); + char *ziprepr = strjoin("zip archive ", srcrepr, NULL); mem_free(srcrepr); return ziprepr; } -static VFSNode* vfs_zipfile_locate(VFSNode *node, const char *path) { - VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true); - VFSZipFileData *zdata = node->data1; +static VFSNode *vfs_zipfile_locate(VFSNode *node, const char *path) { + auto znode = VFS_NODE_CAST(VFSZipNode, node); + VFSZipFileTLS *tls = vfs_zipfile_get_tls(znode, true); int64_t idx; - if(!ht_lookup(&zdata->pathmap, path, &idx)) { + if(!ht_lookup(&znode->pathmap, path, &idx)) { idx = zip_name_locate(tls->zip, path, 0); } @@ -189,12 +182,10 @@ static VFSNode* vfs_zipfile_locate(VFSNode *node, const char *path) { return NULL; } - VFSNode *n = vfs_alloc(); - vfs_zippath_init(n, node, idx); - return n; + return vfs_zippath_create(znode, idx); } -const char* vfs_zipfile_iter_shared(VFSNode *node, VFSZipFileData *zdata, VFSZipFileIterData *idata, VFSZipFileTLS *tls) { +const char *vfs_zipfile_iter_shared(VFSZipFileIterData *idata, VFSZipFileTLS *tls) { const char *r = NULL; for(; !r && idata->idx < idata->num; ++idata->idx) { @@ -248,17 +239,17 @@ const char* vfs_zipfile_iter_shared(VFSNode *node, VFSZipFileData *zdata, VFSZip return r; } -static const char* vfs_zipfile_iter(VFSNode *node, void **opaque) { - VFSZipFileData *zdata = node->data1; +static const char *vfs_zipfile_iter(VFSNode *node, void **opaque) { + auto znode = VFS_NODE_CAST(VFSZipNode, node); VFSZipFileIterData *idata = *opaque; - VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true); + VFSZipFileTLS *tls = vfs_zipfile_get_tls(znode, true); if(!idata) { *opaque = idata = ALLOC(VFSZipFileIterData); idata->num = zip_get_num_entries(tls->zip, 0); } - return vfs_zipfile_iter_shared(node, zdata, idata, tls); + return vfs_zipfile_iter_shared(idata, tls); } void vfs_zipfile_iter_stop(VFSNode *node, void **opaque) { @@ -271,7 +262,7 @@ void vfs_zipfile_iter_stop(VFSNode *node, void **opaque) { } } -static VFSNodeFuncs vfs_funcs_zipfile = { +VFS_NODE_FUNCS(VFSZipNode, { .repr = vfs_zipfile_repr, .query = vfs_zipfile_query, .free = vfs_zipfile_free, @@ -282,14 +273,18 @@ static VFSNodeFuncs vfs_funcs_zipfile = { .iter_stop = vfs_zipfile_iter_stop, //.mkdir = vfs_zipfile_mkdir, //.open = vfs_zipfile_open, -}; +}); + +static bool vfs_zipfile_init_pathmap(VFSZipNode *znode) { + VFSZipFileTLS *tls = vfs_zipfile_get_tls(znode, true); + + if(!tls) { + return false; + } -static void vfs_zipfile_init_pathmap(VFSNode *node) { - VFSZipFileData *zdata = node->data1; - VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true); zip_int64_t num = zip_get_num_entries(tls->zip, 0); - ht_create(&zdata->pathmap); + ht_create(&znode->pathmap); for(zip_int64_t i = 0; i < num; ++i) { const char *original = zip_get_name(tls->zip, i, 0); @@ -297,33 +292,34 @@ static void vfs_zipfile_init_pathmap(VFSNode *node) { vfs_path_normalize(original, normalized); if(strcmp(original, normalized)) { - ht_set(&zdata->pathmap, normalized, i); + ht_set(&znode->pathmap, normalized, i); } } + + return true; } -VFSZipFileTLS* vfs_zipfile_get_tls(VFSNode *node, bool create) { - VFSZipFileData *zdata = node->data1; - VFSZipFileTLS *tls = SDL_TLSGet(zdata->tls_id); +VFSZipFileTLS *vfs_zipfile_get_tls(VFSZipNode *znode, bool create) { + VFSZipFileTLS *tls = SDL_TLSGet(znode->tls_id); if(tls || !create) { return tls; } tls = ALLOC(typeof(*tls)); - SDL_TLSSet(zdata->tls_id, tls, (void(*)(void*))vfs_zipfile_free_tls); + SDL_TLSSet(znode->tls_id, tls, (void(*)(void*))vfs_zipfile_free_tls); - zip_source_t *src = zip_source_function_create(vfs_zipfile_srcfunc, node, &tls->error); + zip_source_t *src = zip_source_function_create(vfs_zipfile_srcfunc, znode, &tls->error); zip_t *zip = tls->zip = zip_open_from_source(src, ZIP_RDONLY, &tls->error); // FIXME: Taisei currently doesn't handle zip files without explicit directory entries correctly (file listing will not work) if(!zip) { - char *r = vfs_node_repr(zdata->source, true); + char *r = vfs_node_repr(znode->source, true); vfs_set_error("Failed to open zip archive '%s': %s", r, zip_error_strerror(&tls->error)); mem_free(r); vfs_zipfile_free_tls(tls); - SDL_TLSSet(zdata->tls_id, 0, NULL); + SDL_TLSSet(znode->tls_id, 0, NULL); zip_source_free(src); return NULL; } @@ -331,33 +327,22 @@ VFSZipFileTLS* vfs_zipfile_get_tls(VFSNode *node, bool create) { return tls; } -bool vfs_zipfile_init(VFSNode *node, VFSNode *source) { - VFSNode backup; - memcpy(&backup, node, sizeof(VFSNode)); +VFSNode *vfs_zipfile_create(VFSNode *source) { + SDL_TLSID tls = SDL_TLSCreate(); - auto zdata = ALLOC(VFSZipFileData, { + if(!tls) { + vfs_set_error("SDL_TLSCreate() failed: %s", SDL_GetError()); + return NULL; + } + + auto znode = VFS_ALLOC(VFSZipNode, { .source = source, - .tls_id = SDL_TLSCreate(), + .tls_id = tls, }); - node->data1 = zdata; - node->funcs = &vfs_funcs_zipfile; - - if(!zdata->tls_id) { - vfs_set_error("SDL_TLSCreate() failed: %s", SDL_GetError()); - goto error; + if(!vfs_zipfile_init_pathmap(znode)) { + vfs_decref(znode); } - if(!vfs_zipfile_get_tls(node, true)) { - goto error; - } - - vfs_zipfile_init_pathmap(node); - return true; - -error: - zdata->source = NULL; // don't decref it - node->funcs->free(node); - memcpy(node, &backup, sizeof(VFSNode)); - return false; + return &znode->as_generic; } diff --git a/src/vfs/zipfile.h b/src/vfs/zipfile.h index 009982b8..504ec2be 100644 --- a/src/vfs/zipfile.h +++ b/src/vfs/zipfile.h @@ -11,4 +11,4 @@ #include "private.h" -bool vfs_zipfile_init(VFSNode *node, VFSNode *source); +VFSNode *vfs_zipfile_create(VFSNode *source); diff --git a/src/vfs/zipfile_impl.h b/src/vfs/zipfile_impl.h index 478ae476..bf45b215 100644 --- a/src/vfs/zipfile_impl.h +++ b/src/vfs/zipfile_impl.h @@ -23,18 +23,18 @@ DIAGNOSTIC_CLANG(pop) /* zipfile */ +VFS_NODE_TYPE(VFSZipNode, { + VFSNode *source; + ht_str2int_t pathmap; + SDL_TLSID tls_id; +}); + typedef struct VFSZipFileTLS { zip_t *zip; SDL_RWops *stream; zip_error_t error; } VFSZipFileTLS; -typedef struct VFSZipFileData { - VFSNode *source; - ht_str2int_t pathmap; - SDL_TLSID tls_id; -} VFSZipFileData; - typedef struct VFSZipFileIterData { zip_int64_t idx; zip_int64_t num; @@ -43,19 +43,20 @@ typedef struct VFSZipFileIterData { char *allocated; } VFSZipFileIterData; -const char* vfs_zipfile_iter_shared(VFSNode *node, VFSZipFileData *zdata, VFSZipFileIterData *idata, VFSZipFileTLS *tls); +const char *vfs_zipfile_iter_shared(VFSZipFileIterData *idata, VFSZipFileTLS *tls); void vfs_zipfile_iter_stop(VFSNode *node, void **opaque); +VFSZipFileTLS *vfs_zipfile_get_tls(VFSZipNode *znode, bool create); /* zippath */ -typedef struct VFSZipPathData { - VFSNode *zipnode; +VFS_NODE_TYPE(VFSZipPathNode, { + VFSZipNode *zipnode; uint64_t index; ssize_t size; ssize_t compressed_size; VFSInfo info; uint16_t compression; -} VFSZipPathData; +}); -void vfs_zippath_init(VFSNode *node, VFSNode *zipnode, zip_int64_t idx); -VFSZipFileTLS* vfs_zipfile_get_tls(VFSNode *node, bool create); +VFSNode *vfs_zippath_create(VFSZipNode *zipnode, zip_int64_t idx); +SDL_RWops *vfs_zippath_make_rwops(VFSZipPathNode *zpnode) attr_nonnull_all; diff --git a/src/vfs/zipfile_null.c b/src/vfs/zipfile_null.c index ba576293..2fdbfdcc 100644 --- a/src/vfs/zipfile_null.c +++ b/src/vfs/zipfile_null.c @@ -10,7 +10,7 @@ #include "zipfile.h" -bool vfs_zipfile_init(VFSNode *node, VFSNode *source) { +VFSNode *vfs_zipfile_create(VFSNode *source) { vfs_set_error("Compiled without ZIP support"); - return false; + return NULL; } diff --git a/src/vfs/zipfile_public.c b/src/vfs/zipfile_public.c index 82a93621..bb8505b6 100644 --- a/src/vfs/zipfile_public.c +++ b/src/vfs/zipfile_public.c @@ -20,10 +20,9 @@ bool vfs_mount_zipfile(const char *mountpoint, const char *zippath) { return false; } - VFSNode *znode = vfs_alloc(); + VFSNode *znode; - if(!vfs_zipfile_init(znode, node)) { - vfs_decref(znode); + if(!(znode = vfs_zipfile_create(node))) { vfs_decref(node); return false; } diff --git a/src/vfs/zippath.c b/src/vfs/zippath.c index 74ac7ee8..323ba2f8 100644 --- a/src/vfs/zippath.c +++ b/src/vfs/zippath.c @@ -13,91 +13,89 @@ #include "syspath.h" #include "rwops/all.h" -#define ZTLS(pdata) vfs_zipfile_get_tls((pdata)->zipnode, true) +#define ZTLS(zpnode) vfs_zipfile_get_tls((zpnode)->zipnode, true) -static const char* vfs_zippath_name(VFSNode *node) { - VFSZipPathData *zdata = node->data1; - return zip_get_name(ZTLS(zdata)->zip, zdata->index, 0); +static const char *vfs_zippath_name(VFSZipPathNode *zpnode) { + return zip_get_name(ZTLS(zpnode)->zip, zpnode->index, 0); } static void vfs_zippath_free(VFSNode *node) { - mem_free(node->data1); + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); + vfs_decref(zpnode->zipnode); } -static char* vfs_zippath_repr(VFSNode *node) { - VFSZipPathData *zdata = node->data1; - char *ziprepr = vfs_node_repr(zdata->zipnode, false); +static char *vfs_zippath_repr(VFSNode *node) { + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); + char *ziprepr = vfs_node_repr(zpnode->zipnode, false); char *zpathrepr = strfmt("%s '%s' in %s", - zdata->info.is_dir ? "directory" : "file", vfs_zippath_name(node), ziprepr); + zpnode->info.is_dir ? "directory" : "file", vfs_zippath_name(zpnode), ziprepr); mem_free(ziprepr); return zpathrepr; } -static char* vfs_zippath_syspath(VFSNode *node) { - VFSZipPathData *zdata = node->data1; - char *zippath = vfs_node_repr(zdata->zipnode, true); - char *subpath = strfmt("%s%c%s", zippath, vfs_syspath_separators[0], vfs_zippath_name(node)); +static char *vfs_zippath_syspath(VFSNode *node) { + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); + char *zippath = vfs_node_repr(zpnode->zipnode, true); + char *subpath = strfmt("%s%c%s", zippath, vfs_syspath_separators[0], vfs_zippath_name(zpnode)); mem_free(zippath); vfs_syspath_normalize_inplace(subpath); return subpath; } static VFSInfo vfs_zippath_query(VFSNode *node) { - VFSZipPathData *zdata = node->data1; - return zdata->info; + return VFS_NODE_CAST(VFSZipPathNode, node)->info; } -static VFSNode* vfs_zippath_locate(VFSNode *node, const char *path) { - VFSZipPathData *zdata = node->data1; - - const char *mypath = vfs_zippath_name(node); +static VFSNode *vfs_zippath_locate(VFSNode *node, const char *path) { + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); + const char *mypath = vfs_zippath_name(zpnode); char fullpath[strlen(mypath) + strlen(path) + 2]; snprintf(fullpath, sizeof(fullpath), "%s%c%s", mypath, VFS_PATH_SEPARATOR, path); vfs_path_normalize_inplace(fullpath); - return vfs_locate(zdata->zipnode, fullpath); + return vfs_locate(zpnode->zipnode, fullpath); } -static const char* vfs_zippath_iter(VFSNode *node, void **opaque) { - VFSZipPathData *zdata = node->data1; +static const char *vfs_zippath_iter(VFSNode *node, void **opaque) { + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); VFSZipFileIterData *idata = *opaque; - if(!zdata->info.is_dir) { + if(!zpnode->info.is_dir) { return NULL; } if(!idata) { idata = ALLOC(typeof(*idata)); - idata->num = zip_get_num_entries(ZTLS(zdata)->zip, 0); - idata->idx = zdata->index; - idata->prefix = vfs_zippath_name(node); + idata->num = zip_get_num_entries(ZTLS(zpnode)->zip, 0); + idata->idx = zpnode->index; + idata->prefix = vfs_zippath_name(zpnode); idata->prefix_len = strlen(idata->prefix); *opaque = idata; } - return vfs_zipfile_iter_shared(node, zdata->zipnode->data1, idata, ZTLS(zdata)); + return vfs_zipfile_iter_shared(idata, ZTLS(zpnode)); } #define vfs_zippath_iter_stop vfs_zipfile_iter_stop -static SDL_RWops* vfs_zippath_open(VFSNode *node, VFSOpenMode mode) { +static SDL_RWops *vfs_zippath_open(VFSNode *node, VFSOpenMode mode) { + auto zpnode = VFS_NODE_CAST(VFSZipPathNode, node); + if(mode & VFS_MODE_WRITE) { vfs_set_error("ZIP archives are read-only"); return NULL; } - VFSZipPathData *zdata = node->data1; - - if(mode & VFS_MODE_SEEKABLE && zdata->compression != ZIP_CM_STORE) { + if(mode & VFS_MODE_SEEKABLE && zpnode->compression != ZIP_CM_STORE) { char *repr = vfs_node_repr(node, true); log_warn("Opening compressed file '%s' in seekable mode, this is suboptimal. Consider storing this file without compression", repr); mem_free(repr); } - return SDL_RWFromZipFile(node, zdata); + return vfs_zippath_make_rwops(zpnode); } -static VFSNodeFuncs vfs_funcs_zippath = { +VFS_NODE_FUNCS(VFSZipPathNode, { .repr = vfs_zippath_repr, .query = vfs_zippath_query, .free = vfs_zippath_free, @@ -108,10 +106,10 @@ static VFSNodeFuncs vfs_funcs_zippath = { .iter_stop = vfs_zippath_iter_stop, //.mkdir = vfs_zippath_mkdir, .open = vfs_zippath_open, -}; +}); -void vfs_zippath_init(VFSNode *node, VFSNode *zipnode, zip_int64_t idx) { - auto zdata = ALLOC(VFSZipPathData, { +VFSNode *vfs_zippath_create(VFSZipNode *zipnode, zip_int64_t idx) { + auto zpnode = VFS_ALLOC(VFSZipPathNode, { .zipnode = zipnode, .index = idx, .size = -1, @@ -123,31 +121,26 @@ void vfs_zippath_init(VFSNode *node, VFSNode *zipnode, zip_int64_t idx) { }, }); - node->data1 = zdata; - zdata->info.is_dir = ('/' == *(strchr(vfs_zippath_name(node), 0) - 1)); + zpnode->info.is_dir = ('/' == *(strchr(vfs_zippath_name(zpnode), 0) - 1)); zip_stat_t zstat; - if(zip_stat_index(ZTLS(zdata)->zip, zdata->index, 0, &zstat) < 0) { - log_warn("zip_stat_index(%"PRIi64") failed: %s", idx, zip_error_strerror(&ZTLS(zdata)->error)); + if(zip_stat_index(ZTLS(zpnode)->zip, zpnode->index, 0, &zstat) < 0) { + log_warn("zip_stat_index(%"PRIi64") failed: %s", idx, zip_error_strerror(&ZTLS(zpnode)->error)); } else { if(zstat.valid & ZIP_STAT_SIZE) { - zdata->size = zstat.size; + zpnode->size = zstat.size; } if(zstat.valid & ZIP_STAT_COMP_SIZE) { - zdata->compressed_size = zstat.comp_size; + zpnode->compressed_size = zstat.comp_size; } if(zstat.valid & ZIP_STAT_COMP_METHOD) { - zdata->compression = zstat.comp_method; + zpnode->compression = zstat.comp_method; } } - node->funcs = &vfs_funcs_zippath; - - const char *path = vfs_zippath_name(node); - char buf[strlen(path)+1], *base, *name; - strcpy(buf, path); - vfs_path_split_right(buf, &base, &name); + vfs_incref(zipnode); + return &zpnode->as_generic; } diff --git a/src/rwops/rwops_zipfile.c b/src/vfs/zippath_rwops.c similarity index 81% rename from src/rwops/rwops_zipfile.c rename to src/vfs/zippath_rwops.c index 15a7baa9..69c9f2ff 100644 --- a/src/rwops/rwops_zipfile.c +++ b/src/vfs/zippath_rwops.c @@ -8,12 +8,12 @@ #include "taisei.h" -#include "rwops_zipfile.h" -#include "rwops_util.h" -#include "rwops_zstd.h" +#include "zipfile_impl.h" + +#include "rwops/rwops_util.h" +#include "rwops/rwops_zstd.h" #include "util.h" -#include "util/libzip_compat.h" #define FORCE_MANUAL_DECOMPRESSION (0) @@ -22,7 +22,6 @@ #endif typedef struct ZipRWData { - VFSNode *node; zip_file_t *file; int64_t pos; int64_t size; @@ -33,13 +32,13 @@ typedef struct ZipRWData { static int ziprw_reopen(SDL_RWops *rw) { ZipRWData *rwdata = rw->hidden.unknown.data1; - VFSZipPathData *pdata = rw->hidden.unknown.data2; + VFSZipPathNode *zpnode = rw->hidden.unknown.data2; if(rwdata->file) { zip_fclose(rwdata->file); } - rwdata->file = zip_fopen_index(ZTLS(pdata)->zip, pdata->index, rwdata->open_flags); + rwdata->file = zip_fopen_index(ZTLS(zpnode)->zip, zpnode->index, rwdata->open_flags); rwdata->pos = 0; return rwdata->file ? 0 : -1; @@ -47,11 +46,11 @@ static int ziprw_reopen(SDL_RWops *rw) { static zip_file_t *ziprw_get_zipfile(SDL_RWops *rw) { ZipRWData *rwdata = rw->hidden.unknown.data1; - VFSZipPathData *pdata = rw->hidden.unknown.data2; + VFSZipPathNode *zpnode = rw->hidden.unknown.data2; int64_t pos = rwdata->pos; - if(!vfs_zipfile_get_tls((pdata)->zipnode, false) && rwdata->file) { + if(!vfs_zipfile_get_tls(zpnode->zipnode, false) && rwdata->file) { zip_fclose(rwdata->file); rwdata->file = NULL; } @@ -67,12 +66,13 @@ static zip_file_t *ziprw_get_zipfile(SDL_RWops *rw) { static int ziprw_close(SDL_RWops *rw) { if(rw) { ZipRWData *rwdata = rw->hidden.unknown.data1; + VFSZipPathNode *zpnode = rw->hidden.unknown.data2; if(rwdata->file) { zip_fclose(rwdata->file); } - vfs_decref(rwdata->node); + vfs_decref(zpnode); mem_free(rwdata); SDL_FreeRW(rw); } @@ -164,7 +164,7 @@ static size_t ziprw_write(SDL_RWops *rw, const void *ptr, size_t size, size_t ma return -1; } -SDL_RWops *SDL_RWFromZipFile(VFSNode *znode, VFSZipPathData *pdata) { +SDL_RWops *vfs_zippath_make_rwops(VFSZipPathNode *zpnode) { SDL_RWops *rw = SDL_AllocRW(); if(UNLIKELY(!rw)) { @@ -174,14 +174,13 @@ SDL_RWops *SDL_RWFromZipFile(VFSNode *znode, VFSZipPathData *pdata) { memset(rw, 0, sizeof(SDL_RWops)); auto rwdata = ALLOC(ZipRWData, { - .node = znode, - .size = pdata->size, + .size = zpnode->size, }); - vfs_incref(znode); + vfs_incref(zpnode); rw->hidden.unknown.data1 = rwdata; - rw->hidden.unknown.data2 = pdata; + rw->hidden.unknown.data2 = zpnode; rw->type = SDL_RWOPS_UNKNOWN; rw->size = ziprw_size; @@ -192,33 +191,33 @@ SDL_RWops *SDL_RWFromZipFile(VFSNode *znode, VFSZipPathData *pdata) { DIAGNOSTIC(push) DIAGNOSTIC(ignored "-Wunreachable-code") - if(pdata->compression == ZIP_CM_STORE) { + if(zpnode->compression == ZIP_CM_STORE) { rw->seek = ziprw_seek; } else if( !FORCE_MANUAL_DECOMPRESSION && - zip_compression_method_supported(pdata->compression, false) + zip_compression_method_supported(zpnode->compression, false) ) { rw->seek = ziprw_seek_emulated; } else { rw->seek = ziprw_seek; - rwdata->size = pdata->compressed_size; + rwdata->size = zpnode->compressed_size; rwdata->open_flags = ZIP_FL_COMPRESSED; - switch(pdata->compression) { + switch(zpnode->compression) { #if FORCE_MANUAL_DECOMPRESSION case ZIP_CM_DEFLATE: - rw = SDL_RWWrapInflateReaderSeekable(rw, pdata->size, imin(4096, pdata->size), true); + rw = SDL_RWWrapInflateReaderSeekable(rw, zpnode->size, imin(4096, pdata->size), true); break; #endif case ZIP_CM_ZSTD: { - rw = SDL_RWWrapZstdReaderSeekable(rw, pdata->size, true); + rw = SDL_RWWrapZstdReaderSeekable(rw, zpnode->size, true); break; } default: { - char *fname = vfs_node_repr(znode, true); - SDL_SetError("%s: unsupported compression method: %i", fname, pdata->compression); + char *fname = vfs_node_repr(zpnode, true); + SDL_SetError("%s: unsupported compression method: %i", fname, zpnode->compression); SDL_RWclose(rw); return NULL; }