1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-04-08 07:37:07 +00:00

Update inlcuded ttvfs

This commit is contained in:
fgenesis 2017-01-12 23:52:59 +01:00
parent fe0a91129f
commit ffa26e4105
22 changed files with 327 additions and 153 deletions

View file

@ -4,6 +4,8 @@ set(ttvfs_SRC
VFSArchiveLoader.h
VFSBase.cpp
VFSBase.h
VFSDebug.cpp
VFSDebug.h
VFSDefines.h
VFSDir.cpp
VFSDir.h
@ -28,3 +30,8 @@ set(ttvfs_SRC
)
add_library(ttvfs ${ttvfs_SRC})
install(TARGETS ttvfs DESTINATION lib)
install(DIRECTORY ./ DESTINATION include/ttvfs
FILES_MATCHING PATTERN "*.h")

View file

@ -0,0 +1,72 @@
#include "VFSDebug.h"
#include "VFSInternal.h"
#include "VFSRoot.h"
#include "VFSDir.h"
#include "VFSFile.h"
#include "VFSTools.h"
#include <iostream>
#include <set>
VFS_NAMESPACE_START
namespace debug {
struct _DbgParams
{
_DbgParams(std::ostream& os_, const std::string& path, const std::string& sp_)
: os(os_), mypath(path), sp(sp_) {}
std::ostream& os;
std::string mypath;
const std::string& sp;
std::set<std::string> dirnames;
};
static void _DumpFile(File *vf, void *user)
{
_DbgParams& p = *((_DbgParams*)user);
p.os << p.sp << " F:" << vf->fullname() << " [" << vf->getType() << ", ref " << vf->getRefCount() << ", 0x" << vf << "]" << std::endl;
}
static void _DumpDir(DirBase *vd, void *user)
{
_DbgParams& p = *((_DbgParams*)user);
if(!(vd->fullname()[0] == '/' && vd->fullnameLen() == 1)) // don't recurse down the root dir.
p.dirnames.insert(vd->name());
p.os << p.sp << "D : " << vd->fullname() << " [" << vd->getType() << ", ref " << vd->getRefCount() << ", 0x" << vd << "]" << std::endl;
}
static void _DumpTree(_DbgParams& p, Root& vfs, int level)
{
p.os << ">> [" << p.mypath << "]" << std::endl;
vfs.ForEach(p.mypath.c_str(), _DumpFile, _DumpDir);
if(!level)
return;
std::string sub = p.sp + " ";
for(std::set<std::string>::iterator it = p.dirnames.begin(); it != p.dirnames.end(); ++it)
{
_DbgParams recP(p.os, joinPath(p.mypath, it->c_str()), sub);
_DumpTree(recP, vfs, level - 1);
}
}
void dumpTree(Root& root, std::ostream& os, const char *path /* = NULL */, int level /* = -1 */)
{
if(!path)
path = "";
os << ">>> FILE TREE DUMP <<<" << std::endl;
_DbgParams recP(os, path, "");
_DumpTree(recP, root, level);
}
} // end namespace debug
VFS_NAMESPACE_END

View file

@ -0,0 +1,22 @@
#ifndef TTVFS_DEBUG_H
#define TTVFS_DEBUG_H
#include "VFSDefines.h"
#include <iosfwd>
VFS_NAMESPACE_START
class Root;
namespace debug {
/** Dump tree structure with debug information to a stream.
path specifies the subdir to dump; use "" or NULL to dump the whole tree.
Set level to >= 0 to limit the recursion depth.
Level < 0 recurses as deep as the tree goes. */
void dumpTree(Root& root, std::ostream& os, const char *path = NULL, int level = -1);
} // end namespace debug
VFS_NAMESPACE_END
#endif

View file

@ -28,30 +28,39 @@
#define VFS_NAMESPACE_END }
#if !defined(_MSC_VER)
# include <stdint.h>
// Important that this is included outside of the namespace.
// Note that stdint.h is intentionally NOT included if possible,
// because on gcc it pulls in features.h, which in turn checks for
// _FILE_OFFSET_BITS presence. That means to enable 64bit file I/O,
// _FILE_OFFSET_BITS would have to be defined here.
// For the sake of not polluting the includer, use other means to define
// a 64 bit type.
#if !defined(_MSC_VER) && !defined(__GNUC__)
# include <stdint.h> // Hope it works.
#endif
VFS_NAMESPACE_START
#ifdef VFS_LARGEFILE_SUPPORT
# if defined(_MSC_VER)
typedef __int64 vfspos;
# else
# include <stdint.h>
typedef int64_t vfspos;
# endif
// vfspos type (signed 64bit integer if possible, 32bit otherwise)
#if defined(_MSC_VER)
typedef __int64 vfspos;
#elif defined(__GNUC__)
__extension__ // suppress warnings about long long
typedef long long int vfspos;
#elif defined(VFS_LARGEFILE_SUPPORT)
// fallback using stdint. h, but only if necessary
typedef int64_t vfspos;
#else
typedef unsigned int vfspos;
// If all else fails
typedef long int vfspos; // what fseek() uses, no guarantees whether 64 or 32 bits
#endif
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
# define VFS_STRICMP _stricmp
static const vfspos npos = vfspos(-1i64);
#else
# define VFS_STRICMP strcasecmp
static const vfspos npos = vfspos(-1LL);
#endif
static const vfspos npos = ~vfspos(0);
typedef void (*delete_func)(void *);
@ -63,6 +72,12 @@ struct _AbiCheck
int nocase;
};
class File;
class DirBase;
typedef void (*FileEnumCallback)(File *vf, void *user);
typedef void (*DirEnumCallback)(DirBase *vd, void *user);
VFS_NAMESPACE_END

View file

@ -59,7 +59,6 @@ std::pair<DirBase*, DirBase*> DirBase::_getDirEx(const char *subdir, const char
return std::make_pair(this, this);
DirBase *ret = NULL;
DirBase *last = NULL;
char *slashpos = (char *)strchr(subdir, '/');
// if there is a '/' in the string, descend into subdir and continue there
@ -239,12 +238,13 @@ void Dir::forEachDir(DirEnumCallback f, void *user /* = NULL */, bool safe /* =
}
bool Dir::add(File *f)
{
if(!f)
return false;
return _addRecursiveSkip(f, 0);
}
bool Dir::_addSingle(File *f)
{
Files::iterator it = _files.find(f->name());
if(it != _files.end())
@ -260,11 +260,8 @@ bool Dir::add(File *f)
return true;
}
bool Dir::addRecursive(File *f, size_t skip /* = 0 */)
bool Dir::_addRecursiveSkip(File *f, size_t skip /* = 0 */)
{
if(!f)
return false;
Dir *vdir = this;
if(f->fullnameLen() - f->nameLen() > skip)
{
@ -285,7 +282,7 @@ bool Dir::addRecursive(File *f, size_t skip /* = 0 */)
}
}
return vdir->add(f);
return vdir->_addSingle(f);
}
void Dir::clearGarbage()
@ -374,4 +371,12 @@ void DiskDir::load()
}
}
// ----- MemDir start here -----
MemDir *MemDir::createNew(const char *dir) const
{
return new MemDir(dir);
}
VFS_NAMESPACE_END

View file

@ -59,9 +59,6 @@ class DirView;
class File;
class VFSLoader;
typedef void (*FileEnumCallback)(File *vf, void *user);
typedef void (*DirEnumCallback)(DirBase *vd, void *user);
// Avoid using std::string as key.
// The file names are known to remain constant during each object's lifetime,
@ -125,14 +122,12 @@ public:
virtual ~Dir();
/** Adds a file directly to this directory, allows any name.
If another file with this name already exists, drop the old one out.
Returns whether the file was actually added (false if the same file already existed) */
If the file name contains a path, descend the tree to the target dir.
Not-existing subdirs are created on the way.
If another file with this name already exists, drop the old one out.
Returns whether the file was actually added (false if the same file already existed) */
bool add(File *f);
/** Like add(), but if the file name contains a path, descend the tree to the target dir.
Not-existing subdirs are created on the way. */
bool addRecursive(File *f, size_t skip = 0);
/** Enumerate directory with given path. Clears previously loaded entries. */
virtual void load() = 0;
@ -146,9 +141,12 @@ public:
File *getFileByName(const char *fn, bool lazyLoad = true);
File *getFileFromSubdir(const char *subdir, const char *file);
bool _addRecursiveSkip(File *f, size_t skip = 0);
protected:
bool _addSingle(File *f);
inline VFSLoader *getLoader() const { return _loader; }
Files _files;
@ -162,9 +160,23 @@ class DiskDir : public Dir
public:
DiskDir(const char *path, VFSLoader *ldr);
virtual ~DiskDir() {};
virtual void load();
virtual DiskDir *createNew(const char *dir) const;
virtual const char *getType() const { return "DiskDir"; }
// virtual overloads
void load();
DiskDir *createNew(const char *dir) const;
const char *getType() const { return "DiskDir"; }
};
class MemDir : public Dir
{
public:
MemDir(const char *fullpath) : Dir(fullpath, NULL) {}
virtual ~MemDir() {}
// virtual overloads
void load() {}
MemDir *createNew(const char *dir) const;
const char *getType() const { return "MemDir"; }
};
VFS_NAMESPACE_END

View file

@ -106,12 +106,6 @@ void InternalDir::forEachFile(FileEnumCallback f, void *user /* = NULL */, bool
f(it->second, user);
}
static void _iterDirs(Dirs &m, DirEnumCallback f, void *user)
{
for(Dirs::iterator it = m.begin(); it != m.end(); ++it)
f(it->second.content(), user);
}
void InternalDir::forEachDir(DirEnumCallback f, void *user /* = NULL */, bool safe /* = false */)
{
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)

View file

@ -95,7 +95,7 @@ vfspos DiskFile::size()
// ------------- MemFile -----------------------
MemFile::MemFile(const char *name, void *buf, unsigned int size, delete_func delfunc /* = NULL */, DeleteMode delmode /* = ON_CLOSE */)
: File(name), _pos(0), _size(size), _buf(buf), _delfunc(delfunc), _delmode(delmode)
: File(name), _buf(buf), _pos(0), _size(size), _delfunc(delfunc), _delmode(delmode)
{
}

View file

@ -88,13 +88,14 @@ public:
ON_CLOSE,
ON_DESTROY
};
/* Creates a virtual file from a memory buffer. The buffer is passed as-is,
/** Creates a virtual file from a memory buffer. The buffer is passed as-is,
so for text files you should make sure it ends with a \0 character.
A deletor function can be passed optionally, that the buffer will be passed to
when the memory file is destroyed. Pass NULL or leave away to keep the buffer alive. */
MemFile(const char *name, void *buf, unsigned int size, delete_func delfunc = NULL, DeleteMode delmode = ON_CLOSE);
virtual ~MemFile();
virtual bool open(const char *mode = NULL) { return true; }
/** In order not to modify the passed buffer, MemFile does NOT respect the mode parameter. */
virtual bool open(const char *mode = NULL) { return !!_buf; }
virtual bool isopen() const { return !!_buf; } // always open
virtual bool iseof() const { return _pos >= _size; }
virtual void close();

View file

@ -8,10 +8,12 @@ VFS_NAMESPACE_START
// Compile time assertion to make sure things work as expected
#if defined(VFS_LARGEFILE_SUPPORT)
static void _dummy_()
TTVFS_UNUSED static void _dummy_()
{
// Ensure vfspos is 64 bits in largefile mode.
switch(0) { case 0:; case 4: case sizeof(vfspos): ; }
#ifndef _MSC_VER
// Ensure the _FILE_OFFSET_BITS=64 setting in VFSInternal.h is effective
switch(0) { case 0:; case 4: case sizeof(off_t): ; }
#endif
}

View file

@ -37,6 +37,12 @@
# endif
#endif
#ifdef __GNUC__
# define TTVFS_UNUSED __attribute__((unused))
#else
# define TTVFS_UNUSED
#endif
// These are used for small, temporary memory allocations that can remain on the stack.
// If alloca is available, this is the preferred way.
#include <stdlib.h>

View file

@ -37,6 +37,7 @@ public:
{
int val = s_getRef(_refcount);
assert(val == 0 && "Object was deleted with refcount != 0");
(void)val;
}
inline void incref()

View file

@ -1,8 +1,6 @@
// VFSRoot.cpp - glues it all together and makes use simple
// For conditions of distribution and use, see copyright notice in VFS.h
#include <set>
#include "VFSInternal.h"
#include "VFSRoot.h"
#include "VFSTools.h"
@ -13,9 +11,6 @@
#include "VFSArchiveLoader.h"
#include "VFSDirView.h"
//#include <stdio.h>
#include <iostream>
#ifdef _DEBUG
# include <cassert>
# define DEBUG_ASSERT(x) assert(x)
@ -64,11 +59,12 @@ void Root::Clear()
loaders.clear();
archLdrs.clear();
loadersInfo.clear();
}
void Root::Mount(const char *src, const char *dest)
{
AddVFSDir(GetDir(src, true), dest);
return AddVFSDir(GetDir(src, true), dest);
}
void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
@ -79,26 +75,54 @@ void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
into->_addMountDir(dir);
}
bool Root::Unmount(const char *src, const char *dest)
bool Root::RemoveVFSDir(DirBase *dir, const char *subdir /* = NULL */)
{
DirBase *vdsrc = GetDir(src, false);
InternalDir *vddest = safecast<InternalDir*>(GetDir(dest, false));
if(!vdsrc || !vddest)
if(!subdir)
subdir = dir->fullname();
InternalDir *vddest = safecast<InternalDir*>(GetDir(subdir, false));
if(!vddest)
return false;
vddest->_removeMountDir(vdsrc);
vddest->_removeMountDir(dir);
return true;
}
void Root::AddLoader(VFSLoader *ldr, const char *path /* = NULL */)
bool Root::Unmount(const char *src, const char *dest)
{
loaders.push_back(ldr);
AddVFSDir(ldr->getRoot(), path);
DirBase *vdsrc = GetDir(src, false);
if(!vdsrc)
return false;
return RemoveVFSDir(vdsrc, dest);
}
void Root::AddArchiveLoader(VFSArchiveLoader *ldr)
int Root::AddLoader(VFSLoader *ldr, const char *path /* = NULL */)
{
DEBUG_ASSERT(ldr != NULL);
loaders.push_back(ldr);
loadersInfo.push_back(path);
AddVFSDir(ldr->getRoot(), path);
return (int)(loaders.size() - 1);
}
void Root::RemoveLoader(int index, const char *path /* = NULL */)
{
VFSLoader *ldr = loaders[index];
RemoveVFSDir(ldr->getRoot(), loadersInfo[index].getPath());
loaders.erase(loaders.begin() + index);
loadersInfo.erase(loadersInfo.begin() + index);
}
int Root::AddArchiveLoader(VFSArchiveLoader *ldr)
{
DEBUG_ASSERT(ldr != NULL);
archLdrs.push_back(ldr);
return (int)(archLdrs.size() - 1);
}
void Root::RemoveArchiveLoader(int index)
{
archLdrs.erase(archLdrs.begin() + index);
}
Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */)
@ -133,7 +157,7 @@ inline static File *VFSHelper_GetFileByLoader(VFSLoader *ldr, const char *fn, co
return NULL;
File *vf = ldr->Load(fn, unmangled);
if(vf)
ldr->getRoot()->addRecursive(vf);
ldr->getRoot()->add(vf);
return vf;
}
@ -217,62 +241,21 @@ void Root::ClearGarbage()
merged->clearGarbage();
}
// DEBUG STUFF
struct _DbgParams
bool Root::ForEach(const char *path, FileEnumCallback fileCallback /* = NULL */, DirEnumCallback dirCallback /* = NULL */,
void *user /* = NULL */, bool safe /* = false */)
{
_DbgParams(std::ostream& os_, const std::string& path, const std::string& sp_)
: os(os_), mypath(path), sp(sp_) {}
std::ostream& os;
std::string mypath;
const std::string& sp;
std::set<std::string> dirnames;
};
static void _DumpFile(File *vf, void *user)
{
_DbgParams& p = *((_DbgParams*)user);
p.os << p.sp << " F:" << vf->fullname() << " [" << vf->getType() << ", ref " << vf->getRefCount() << ", 0x" << vf << "]" << std::endl;
}
static void _DumpDir(DirBase *vd, void *user)
{
_DbgParams& p = *((_DbgParams*)user);
if(!(vd->fullname()[0] == '/' && vd->fullnameLen() == 1)) // don't recurse down the root dir.
p.dirnames.insert(vd->name());
p.os << p.sp << "D : " << vd->fullname() << " [" << vd->getType() << ", ref " << vd->getRefCount() << ", 0x" << vd << "]" << std::endl;
}
static void _DumpTree(_DbgParams& p, Root& vfs, int level)
{
p.os << ">> [" << p.mypath << "]" << std::endl;
DirView view;
vfs.FillDirView(p.mypath.c_str(), view);
if(!FillDirView(path, view))
return false;
view.forEachDir(_DumpDir, &p);
view.forEachFile(_DumpFile, &p);
if(dirCallback)
view.forEachDir(dirCallback, user, safe);
if(fileCallback)
view.forEachFile(fileCallback, user, safe);
if(!level)
return;
std::string sub = p.sp + " ";
for(std::set<std::string>::iterator it = p.dirnames.begin(); it != p.dirnames.end(); ++it)
{
_DbgParams recP(p.os, joinPath(p.mypath, it->c_str()), sub);
_DumpTree(recP, vfs, level - 1);
}
return true;
}
void Root::debugDumpTree(std::ostream& os, const char *path, int level)
{
os << ">>> FILE TREE DUMP <<<" << std::endl;
_DbgParams recP(os, path, "");
_DumpTree(recP, *this, level);
}
VFS_NAMESPACE_END

View file

@ -7,7 +7,6 @@
#include <vector>
#include <list>
#include <string>
#include <iosfwd>
#include "VFSRefcounted.h"
@ -23,7 +22,12 @@ class VFSArchiveLoader;
class DirView;
/** Root - extensible class to simplify working with the VFS tree */
/** Root - simplify working with the VFS tree.
Everything is reference-counted. If you store pointers to contained objects externally,
use ttvfs::CountedPtr<>.
To enumerate the file tree for debugging, use ttvfs::debug::dumpTree().
*/
class Root
{
public:
@ -31,28 +35,24 @@ public:
virtual ~Root();
/** Reset an instance to its initial state.
Drops all archives, loaders, archive loaders, mount points, internal trees, ...*/
Drops all subdirs, loaders, archive loaders, mount points, ...*/
virtual void Clear();
/** Do cleanups from time to time. For internal classes, this is a no-op.
Extensions may wish to override this method do do cleanup jobs. */
virtual void ClearGarbage();
/** Mount a directory in the tree to a different location. Requires a previous call to Prepare().
This can be imagined like the contents of a directory appearing in a different location.
/** Mount a directory in the tree to a different location.
This means that the contents of src will appear in dest.
Be careful not to create circles! */
void Mount(const char *src, const char *dest);
/** Drops a directory from the tree. Internally, this calls Reload(false),
which is a heavy operation compared to Mount(). Be warned. */
/** Like Mount(), but in reverse.
Returns true if the mount point does not exist after the call,
(that is, if it was removed or it never existed in the first place),
false if src or dst do not exist. */
bool Unmount(const char *src, const char *dest);
/** Adds a Dir object into the merged tree. If subdir is NULL (the default),
add into the subdir stored in the Dir object. The tree will be extended if target dir does not exist.
Files in the tree will be replaced if already existing.
Like with Mount(); be careful not to create cycles. */
void AddVFSDir(DirBase *dir, const char *subdir = NULL);
/** Add an archive file to the tree, which can then be addressed like a folder,
e.g. "path/to/example.zip/file.txt".
Returns a pointer to the actual Dir object that represents the added archive, or NULL if failed.
@ -60,18 +60,31 @@ public:
such as a password to open the file.
Read the comments in VFSArchiveLoader.h for an explanation how it works.
If you have no idea, leave it NULL, because it can easily cause a crash if not used carefully. */
Dir *AddArchive(const char *arch, void *opaque = NULL);
Dir *AddArchive(File *file, const char *path = NULL, void *opaque = NULL);
/** Add an archive by file name. This is a quick convenience method using the method above. */
Dir *AddArchive(const char *arch, void *opaque = NULL);
/** Add a loader that can look for files on demand.
Do not add more then once instance of a loader type. */
void AddLoader(VFSLoader *ldr, const char *path = NULL);
Do not add more than one instance of a loader type.
The optional path parameter is experimental, do not use it.
Returns the index of the added loader, which is required for RemoveLoader().
If the loader will not be removed, ignore the return value.*/
int AddLoader(VFSLoader *ldr, const char *path = NULL);
/** Remove a previously added loader. Use the index returned by AddLoader(). */
void RemoveLoader(int index, const char *path = NULL);
/** Add an archive loader that can open archives of various types.
Whenever an archive file is requested to be opened by AddArchive(),
it is sent through each registered loader until one of them can recognize
the format and open it. */
void AddArchiveLoader(VFSArchiveLoader *ldr);
it is sent through each registered loader until one of them recognizes
the format and can open it.
Returns the index of the added loader, which is required for RemoveArchiveLoader().
If the loader will not be removed, ignore the return value.*/
int AddArchiveLoader(VFSArchiveLoader *ldr);
/** Remove a previously added archive loader. Use the index returned by AddArchiveLoader(). */
void RemoveArchiveLoader(int index);
/** Get a file from the merged tree. Asks loaders if the file is not in the tree.
If found by a loader, the file will be added to the tree. */
@ -79,18 +92,37 @@ public:
/** Fills a DirView object with a list of directories that match the specified path.
This is the preferred way to enumerate directories, as it respects and collects
mount points during traversal. The DirView instance can be re-used until an (un-)mounting
operation takes place. If the content of directories changes, this is reflected in the view.
mount points during traversal. The DirView instance can be re-used until any mount or unmount
operation takes place. If the content of a contained directory changes, this is reflected in the view.
(Added dirs or files will appear, removed ones disappear).
Use DirView::forEachFile() or DirView::forEachDir() to iterate. */
bool FillDirView(const char *path, DirView& view);
/** Convenience method to iterate over all files and subdirs of a given path.
Returns true if the path exists and iteration was successful.
Both callback functions are optional, pass NULL if not interested.
user is an opaque pointer passed to the callbacks.
Set safe = true if the file tree is modified by a callback function. */
bool ForEach(const char *path, FileEnumCallback fileCallback = NULL, DirEnumCallback dirCallback = NULL, void *user = NULL, bool safe = false);
/** Remove a file or directory from the tree */
//bool Remove(File *vf);
//bool Remove(Dir *dir);
//bool Remove(const char *name); // TODO: CODE ME
// --- Less common functions below ---
/** Adds a Dir object into the merged tree. If subdir is NULL (the default),
use the full path of dir. The tree will be extended if target dir does not exist.
Files in the tree will be overridden if already existing.
Like with Mount(); be careful not to create cycles. */
void AddVFSDir(DirBase *dir, const char *subdir = NULL);
/** Removes a dir from a given path previously added to via AddVFSDir().
Returns true if dir does not exist at subdir after the call. */
bool RemoveVFSDir(DirBase *dir, const char *subdir /* = NULL */);
/** Returns the tree root, which is usually the working directory.
Same as GetDir("").
You will most likely not need this function. */
@ -99,25 +131,31 @@ public:
/** Get a directory from the merged tree. If create is true and the directory does not exist,
build the tree structure and return the newly created dir. NULL otherwise.
You will most likely not need this function.
Use FillDirView() on a DirView object to iterate over directory contents. */
Use FillDirView() on a DirView object or ForEach() to iterate over directory contents. */
DirBase *GetDir(const char* dn, bool create = false);
// DEBUG STUFF
void debugDumpTree(std::ostream& os, const char *path, int level);
protected:
InternalDir *_GetDirByLoader(VFSLoader *ldr, const char *fn, const char *unmangled);
class _LoaderInfo
{
public:
_LoaderInfo(const char *path) : isnull(path == NULL), pathstr(path ? path : "") {}
inline const char *getPath() { return isnull ? NULL : pathstr.c_str(); }
private:
bool isnull;
std::string pathstr;
};
typedef std::vector<CountedPtr<VFSLoader> > LoaderArray;
typedef std::vector<CountedPtr<VFSArchiveLoader> > ArchiveLoaderArray;
typedef std::vector<_LoaderInfo> ArchiveLoaderInfoArray;
// If files are not in the tree, maybe one of these is able to find it.
LoaderArray loaders;
LoaderArray loaders; // If files are not in the tree, maybe one of these is able to find it.
CountedPtr<InternalDir> merged; // contains the merged virtual/actual file system tree
ArchiveLoaderArray archLdrs;
ArchiveLoaderInfoArray loadersInfo;
};
VFS_NAMESPACE_END

View file

@ -10,3 +10,7 @@ add_library(ttvfs_cfileapi ${cfileapi_SRC})
target_link_libraries(ttvfs_cfileapi ttvfs)
install(TARGETS ttvfs_cfileapi DESTINATION lib)
install(DIRECTORY ./ DESTINATION include/ttvfs
FILES_MATCHING PATTERN "*.h")

View file

@ -16,12 +16,6 @@ void ttvfs_setroot(ttvfs::Root *root)
VFILE *vfopen(const char *fn, const char *mode)
{
if (strchr(mode, 'w'))
{
assert(0 && "ttvfs_stdio: File writing via VFS not yet supported!");
return NULL;
}
VFILE *vf = vfs->GetFile(fn);
if (!vf || !vf->open(mode))
return NULL;

View file

@ -6,13 +6,14 @@
// * Define VFS_ENABLE_C_API to 1 to use ttvfs overrides.
/*
This file is a minimal wrapper to replace the C API and std::ifstream.
Note that if you have an advanced needs, this wrapper API is not for you.
This file is a poor man's wrapper to replace the C API and std::ifstream.
Note that if you have any advanced needs, this wrapper API is not for you.
To use it, go through your code and rename all FILE* to VFILE*,
and fopen() and related to vfopen() (so just put a 'v' in front).
Instead of std::ifstream, use InStream. If you use std::fstream for reading ONLY,
also use InStream.
Make sure that a FILE* is not opened twice at any time - this is not supported.
Note that the seek and tell functions do not offer 64 bit offsets in this API.
*/
@ -35,6 +36,8 @@ typedef ttvfs::File VFILE;
void ttvfs_setroot(ttvfs::Root *root);
// Note that vfopen() returns the same pointer for the same file name,
// so effectively a file is a singleton object.
VFILE *vfopen(const char *fn, const char *mode);
size_t vfread(void *ptr, size_t size, size_t count, VFILE *vf);
int vfclose(VFILE *vf);

View file

@ -10,8 +10,16 @@ set(ttvfs_zip_SRC
VFSZipArchiveRef.h
miniz.c
miniz.h
ttvfs_zip.h
)
include_directories(${TTVFS_INCLUDE_DIRS})
add_library(ttvfs_zip ${ttvfs_zip_SRC})
install(TARGETS ttvfs_zip DESTINATION lib)
install(FILES miniz.c DESTINATION include/ttvfs)
install(DIRECTORY ./ DESTINATION include/ttvfs
FILES_MATCHING PATTERN "*.h")

View file

@ -65,7 +65,7 @@ void ZipDir::load()
continue;
ZipFile *vf = new ZipFile(fs.m_filename, _archiveHandle, fs.m_file_index);
addRecursive(vf, len);
_addRecursiveSkip(vf, len);
}
_canLoad = false;

View file

@ -30,6 +30,8 @@ bool ZipFile::open(const char *mode /* = NULL */)
_pos = 0;
if(!mode)
mode = "rb";
else if(strchr(mode, 'w') || strchr(mode, 'a'))
return false; // writing not yet supported
if(_mode != mode)
{
delete [] _buf;
@ -53,7 +55,7 @@ void ZipFile::close()
{
//flush(); // TODO: write to zip file on close
delete []_buf;
delete [] _buf;
_buf = NULL;
_bufSize = 0;
}
@ -143,16 +145,15 @@ bool ZipFile::unpack()
close(); // delete the buffer
const vfspos sz = size(); // will reopen the file
if(sz < 0)
if(sz == npos)
return false;
_buf = new char[sz + 1];
_buf = new char[size_t(sz) + 1];
if(!_buf)
return false;
if(!mz_zip_reader_extract_to_mem(MZ, _fileIdx, _buf, sz, 0))
if(!mz_zip_reader_extract_to_mem(MZ, _fileIdx, _buf, (size_t)sz, 0))
{
//assert(0 && "ZipFile unpack: Failed mz_zip_reader_extract_to_mem");
delete [] _buf;
_buf = NULL;
return false; // this should not happen

View file

@ -144,7 +144,7 @@
// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
#define MINIZ_NO_STDIO
//#define MINIZ_NO_STDIO
// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
// get/set file times.

View file

@ -0,0 +1,6 @@
#ifndef TTVFS_ZIP_INC_H
#define TTVFS_ZIP_INC_H
#include "VFSZipArchiveLoader.h"
#endif