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:
parent
fe0a91129f
commit
ffa26e4105
22 changed files with 327 additions and 153 deletions
|
@ -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")
|
||||
|
|
72
ExternalLibs/ttvfs/VFSDebug.cpp
Normal file
72
ExternalLibs/ttvfs/VFSDebug.cpp
Normal 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
|
||||
|
22
ExternalLibs/ttvfs/VFSDebug.h
Normal file
22
ExternalLibs/ttvfs/VFSDebug.h
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
{
|
||||
int val = s_getRef(_refcount);
|
||||
assert(val == 0 && "Object was deleted with refcount != 0");
|
||||
(void)val;
|
||||
}
|
||||
|
||||
inline void incref()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
6
ExternalLibs/ttvfs_zip/ttvfs_zip.h
Normal file
6
ExternalLibs/ttvfs_zip/ttvfs_zip.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef TTVFS_ZIP_INC_H
|
||||
#define TTVFS_ZIP_INC_H
|
||||
|
||||
#include "VFSZipArchiveLoader.h"
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue