mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-01-24 17:26:41 +00:00
ttvfs update
This commit is contained in:
parent
87bc46abf6
commit
3cf3ac7659
13 changed files with 212 additions and 112 deletions
|
@ -11,10 +11,12 @@ VFSBase::VFSBase()
|
|||
{
|
||||
}
|
||||
|
||||
VFSBase::~VFSBase()
|
||||
{
|
||||
}
|
||||
|
||||
void VFSBase::_setName(const char *n)
|
||||
{
|
||||
if(!n)
|
||||
return;
|
||||
_fullname = n;
|
||||
FixPath(_fullname);
|
||||
_name = GetBaseNameFromPath(_fullname.c_str());
|
||||
|
|
|
@ -14,7 +14,7 @@ VFS_NAMESPACE_START
|
|||
class VFSBase : public Refcounted
|
||||
{
|
||||
public:
|
||||
virtual ~VFSBase() {}
|
||||
virtual ~VFSBase();
|
||||
|
||||
/** Returns the plain file name. Never NULL. */
|
||||
inline const char *name() const { return _name; }
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// (no sane programmer should do this, anyway).
|
||||
// However, on non-windows systems this will decrease performance when checking for files
|
||||
// on disk (see VFSLoader.cpp).
|
||||
#define VFS_IGNORE_CASE
|
||||
//#define VFS_IGNORE_CASE
|
||||
|
||||
|
||||
/* --- End of config section --- */
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "VFSDirView.h"
|
||||
#include "VFSLoader.h"
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
VFS_NAMESPACE_START
|
||||
|
||||
DirBase::DirBase(const char *fullpath)
|
||||
|
@ -30,23 +32,34 @@ File *DirBase::getFile(const char *fn)
|
|||
if(!slashpos)
|
||||
return getFileByName(fn, true);
|
||||
|
||||
const size_t len = slashpos - fn;
|
||||
char *dirname = (char*)VFS_STACK_ALLOC(len + 1);
|
||||
memcpy(dirname, fn, len);
|
||||
dirname[len] = 0;
|
||||
size_t copysize = std::max<size_t>(slashpos - fn, 1); // always copy the '/' if it's the first char
|
||||
char * const dirname = (char*)VFS_STACK_ALLOC(copysize + 1);
|
||||
memcpy(dirname, fn, copysize);
|
||||
dirname[copysize] = 0;
|
||||
|
||||
File *f = getFileFromSubdir(dirname, slashpos + 1);
|
||||
VFS_STACK_FREE(dirname);
|
||||
return f;
|
||||
}
|
||||
|
||||
DirBase *DirBase::getDir(const char *subdir, bool forceCreate /* = false */, bool lazyLoad /* = true */, bool useSubtrees /* = true */)
|
||||
DirBase *DirBase::getDir(const char *subdir)
|
||||
{
|
||||
// TODO: get rid of alloc
|
||||
std::string fullpath = joinPath(fullname(), subdir);
|
||||
return _getDirEx(subdir, fullpath.c_str(), false, true, true).first;
|
||||
}
|
||||
|
||||
// returns requested subdir or NULL as first, and last existing subdir in the tree as second.
|
||||
std::pair<DirBase*, DirBase*> DirBase::_getDirEx(const char *subdir, const char * const fullpath,
|
||||
bool forceCreate /* = false */, bool lazyLoad /* = true */, bool useSubtrees /* = true */)
|
||||
{
|
||||
//printf("DirBase::_getDirEx [%s] in [%s]\n", subdir, fullname());
|
||||
SkipSelfPath(subdir);
|
||||
if(!subdir[0])
|
||||
return this;
|
||||
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
|
||||
|
@ -54,73 +67,92 @@ DirBase *DirBase::getDir(const char *subdir, bool forceCreate /* = false */, boo
|
|||
{
|
||||
// from a/b/c, cut out the a, without the trailing '/'.
|
||||
const char *sub = slashpos + 1;
|
||||
size_t copysize = slashpos - subdir;
|
||||
size_t copysize = std::max<size_t>(slashpos - subdir, 1); // always copy the '/' if it's the first char
|
||||
char * const t = (char*)VFS_STACK_ALLOC(copysize + 1);
|
||||
memcpy(t, subdir, copysize);
|
||||
t[copysize] = 0;
|
||||
|
||||
if(DirBase *dir = getDirByName(t, lazyLoad, useSubtrees))
|
||||
{
|
||||
// TODO: get rid of recursion
|
||||
ret = dir->getDir(sub, forceCreate, lazyLoad); // descend into subdirs
|
||||
}
|
||||
else if(forceCreate)
|
||||
{
|
||||
// -> newname = fullname() + '/' + t
|
||||
size_t fullLen = fullnameLen();
|
||||
DirBase *ins;
|
||||
if(fullLen)
|
||||
{
|
||||
char * const newname = (char*)VFS_STACK_ALLOC(fullLen + copysize + 2);
|
||||
char *ptr = newname;
|
||||
memcpy(ptr, fullname(), fullLen);
|
||||
ptr += fullLen;
|
||||
*ptr++ = '/';
|
||||
memcpy(ptr, t, copysize);
|
||||
ptr[copysize] = 0;
|
||||
ins = createNew(newname);
|
||||
VFS_STACK_FREE(newname);
|
||||
}
|
||||
else
|
||||
ins = createNew(t);
|
||||
|
||||
_subdirs[ins->name()] = ins;
|
||||
ret = ins->getDir(sub, true, lazyLoad); // create remaining structure
|
||||
std::pair<DirBase*, DirBase*> subpair = dir->_getDirEx(sub, fullpath, forceCreate, lazyLoad); // descend into subdirs
|
||||
ret = subpair.first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DirBase *dir = getDirByName(subdir, lazyLoad, useSubtrees))
|
||||
ret = dir;
|
||||
else if(forceCreate)
|
||||
}
|
||||
|
||||
if(forceCreate && !ret)
|
||||
ret = _createAndInsertSubtree(subdir);
|
||||
|
||||
return std::make_pair(ret, this);
|
||||
}
|
||||
|
||||
DirBase *DirBase::_createAndInsertSubtree(const char *subdir)
|
||||
{
|
||||
size_t fullLen = fullnameLen();
|
||||
if(fullLen)
|
||||
size_t subdirLen = strlen(subdir);
|
||||
char * const buf = (char*)VFS_STACK_ALLOC(subdirLen + 2);
|
||||
buf[0] = '/';
|
||||
memcpy(buf+1, subdir, subdirLen + 1); //copy terminating \0 too
|
||||
char *s = buf+1;
|
||||
|
||||
DirBase *curdir = this;
|
||||
while(*s)
|
||||
{
|
||||
char *slashpos = strchr(s, '/');
|
||||
if(slashpos)
|
||||
{
|
||||
if(slashpos == buf+1) // only check this in first round
|
||||
{
|
||||
s = buf;
|
||||
//printf("abs buf: [%s]\n", buf);
|
||||
}
|
||||
*slashpos = 0;
|
||||
//printf("_createAndInsertSubtree: [%s]\n", s);
|
||||
}
|
||||
|
||||
DirBase *nextdir = curdir->DirBase::getDirByName(s, false, false); // last 2 params are not relevant
|
||||
if(!nextdir)
|
||||
nextdir = curdir->_createNewSubdir(s);
|
||||
curdir->_subdirs[nextdir->name()] = nextdir;
|
||||
curdir = nextdir;
|
||||
if(!slashpos)
|
||||
break;
|
||||
s = slashpos + 1;
|
||||
}
|
||||
|
||||
VFS_STACK_FREE(buf);
|
||||
return curdir;
|
||||
}
|
||||
|
||||
DirBase *DirBase::_createNewSubdir(const char *subdir) const
|
||||
{
|
||||
assert(*subdir);
|
||||
//printf("_createNewSubdir: [%s]\n", subdir);
|
||||
// -> newname = fullname() + '/' + subdir
|
||||
size_t fullLen = fullnameLen();
|
||||
size_t subdirLen = strlen(subdir);
|
||||
char * const newname = (char*)VFS_STACK_ALLOC(fullLen + subdirLen + 2);
|
||||
char *ptr = newname;
|
||||
if(fullLen)
|
||||
{
|
||||
memcpy(ptr, fullname(), fullLen);
|
||||
ptr += fullLen;
|
||||
if(ptr[-1] != '/')
|
||||
*ptr++ = '/';
|
||||
memcpy(ptr, subdir, subdirLen);
|
||||
ptr[subdirLen] = 0;
|
||||
}
|
||||
|
||||
ret = createNew(newname);
|
||||
memcpy(ptr, subdir, subdirLen + 1); // copy terminating \0 too
|
||||
//printf("_createNewSubdir: newname = [%s]\n", newname);
|
||||
DirBase *ret = createNew(newname);
|
||||
//printf("_createNewSubdir: fullname = [%s]\n", ret->fullname());
|
||||
VFS_STACK_FREE(newname);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = createNew(subdir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
_subdirs[ret->name()] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _iterDirs(Dirs &m, DirEnumCallback f, void *user)
|
||||
{
|
||||
|
@ -141,6 +173,9 @@ void DirBase::forEachDir(DirEnumCallback f, void *user /* = NULL */, bool safe /
|
|||
|
||||
DirBase *DirBase::getDirByName(const char *dn, bool /* unused: lazyLoad = true */, bool useSubtrees /* = true */)
|
||||
{
|
||||
if(!dn[0] || (dn[0] == '.' && !dn[1]))
|
||||
return this;
|
||||
|
||||
Dirs::iterator it = _subdirs.find(dn);
|
||||
return it != _subdirs.end() ? it->second : NULL;
|
||||
}
|
||||
|
@ -197,6 +232,13 @@ void Dir::forEachFile(FileEnumCallback f, void *user /* = NULL */, bool safe /*
|
|||
_iterFiles(_files, f, user);
|
||||
}
|
||||
|
||||
void Dir::forEachDir(DirEnumCallback f, void *user /* = NULL */, bool safe /* = false */)
|
||||
{
|
||||
load();
|
||||
DirBase::forEachDir(f, user, safe);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Dir::add(File *f)
|
||||
{
|
||||
|
@ -231,13 +273,14 @@ bool Dir::addRecursive(File *f, size_t skip /* = 0 */)
|
|||
|
||||
// prefixLen == 0 is invalid, prefixLen == 1 is just a single '/', which will be stripped away below.
|
||||
// in both cases, just use 'this'.
|
||||
// FIXME: will this be a problem for absolute paths?
|
||||
if(prefixLen > 1)
|
||||
{
|
||||
char *dirname = (char*)VFS_STACK_ALLOC(prefixLen);
|
||||
--prefixLen; // -1 to strip the trailing '/'. That's the position where to put the terminating null byte.
|
||||
memcpy(dirname, f->fullname() + skip, prefixLen); // copy trailing null byte
|
||||
dirname[prefixLen] = 0;
|
||||
vdir = safecastNonNull<Dir*>(getDir(dirname, true));
|
||||
vdir = safecastNonNull<Dir*>(_getDirEx(dirname, dirname, true, true).first);
|
||||
VFS_STACK_FREE(dirname);
|
||||
}
|
||||
}
|
||||
|
@ -271,12 +314,19 @@ DirBase *Dir::getDirByName(const char *dn, bool lazyLoad /* = true */, bool useS
|
|||
if(!lazyLoad || !_loader)
|
||||
return NULL;
|
||||
|
||||
// Fix for absolute paths: No dir should have '/' (or any other absolute dirs) as subdir.
|
||||
if(fullnameLen() && dn[0] == '/')
|
||||
return NULL;
|
||||
|
||||
// Lazy-load file if it's not in the tree yet
|
||||
// TODO: get rid of alloc
|
||||
std::string fn2 = joinPath(fullname(), dn);
|
||||
sub = _loader->LoadDir(fn2.c_str(), fn2.c_str());
|
||||
if(sub)
|
||||
{
|
||||
_subdirs[sub->name()] = sub;
|
||||
//printf("Lazy loaded: [%s]\n", sub->fullname());
|
||||
}
|
||||
return sub;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ public:
|
|||
/** Returns a subdir, descends if necessary. If forceCreate is true,
|
||||
create directory tree if it does not exist, and return the originally requested
|
||||
subdir. Otherwise return NULL if not found. */
|
||||
DirBase *getDir(const char *subdir, bool forceCreate = false, bool lazyLoad = true, bool useSubtrees = true);
|
||||
DirBase *getDir(const char *subdir);
|
||||
std::pair<DirBase*, DirBase*> _getDirEx(const char *subdir, const char * const fullpath, bool forceCreate = false, bool lazyLoad = true, bool useSubtrees = true);
|
||||
|
||||
/** Returns a file from this dir's file map.
|
||||
Expects the actual file name without path - does NOT descend. */
|
||||
|
@ -102,13 +103,18 @@ public:
|
|||
virtual void clearGarbage();
|
||||
|
||||
virtual bool _addToView(char *path, DirView& view) = 0;
|
||||
DirBase *_createNewSubdir(const char *name) const;
|
||||
DirBase *_createAndInsertSubtree(const char *name);
|
||||
|
||||
protected:
|
||||
|
||||
/** Creates a new dir of the same type to be used as child of this. */
|
||||
virtual DirBase *createNew(const char *dir) const = 0;
|
||||
|
||||
|
||||
|
||||
Dirs _subdirs;
|
||||
|
||||
};
|
||||
|
||||
class Dir : public DirBase
|
||||
|
@ -131,6 +137,7 @@ public:
|
|||
virtual void load() = 0;
|
||||
|
||||
void forEachFile(FileEnumCallback f, void *user = NULL, bool safe = false);
|
||||
void forEachDir(DirEnumCallback f, void *user = NULL, bool safe = false);
|
||||
|
||||
virtual void clearGarbage();
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "VFSTools.h"
|
||||
#include <algorithm>
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
VFS_NAMESPACE_START
|
||||
|
||||
|
||||
|
@ -119,11 +121,10 @@ void InternalDir::forEachDir(DirEnumCallback f, void *user /* = NULL */, bool sa
|
|||
|
||||
bool InternalDir::fillView(const char *path, DirView& view)
|
||||
{
|
||||
SkipSelfPath(path);
|
||||
view.init(path);
|
||||
size_t len = strlen(path) + 1;
|
||||
size_t len = view.fullnameLen() + 1;
|
||||
char *pathcopy = (char*)VFS_STACK_ALLOC(len);
|
||||
memcpy(pathcopy, path, len);
|
||||
memcpy(pathcopy, view.fullname(), len);
|
||||
bool added = _addToView(pathcopy, view);
|
||||
VFS_STACK_FREE(pathcopy);
|
||||
return added;
|
||||
|
@ -132,6 +133,7 @@ bool InternalDir::fillView(const char *path, DirView& view)
|
|||
bool InternalDir::_addToView(char *path, DirView& view)
|
||||
{
|
||||
bool added = false;
|
||||
SkipSelfPath(path);
|
||||
|
||||
if(!*path)
|
||||
{
|
||||
|
@ -143,14 +145,20 @@ bool InternalDir::_addToView(char *path, DirView& view)
|
|||
}
|
||||
else
|
||||
{
|
||||
SkipSelfPath(path);
|
||||
char dummy = 0;
|
||||
char slash[2] = {'/', 0};
|
||||
char *slashpos = strchr(path, '/');
|
||||
char *tail = slashpos ? slashpos+1 : &dummy;
|
||||
// if the first char is a slash, use "/" to lookup
|
||||
if(slashpos == path)
|
||||
path = &slash[0];
|
||||
|
||||
if(slashpos)
|
||||
*slashpos = 0;
|
||||
|
||||
//printf("InternalDir::_addToView [%s] [%s]\n", path, tail);
|
||||
|
||||
|
||||
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
|
||||
if(DirBase *subdir = (*it)->getDirByName(path))
|
||||
added = subdir->_addToView(tail, view) || added;
|
||||
|
|
|
@ -7,12 +7,7 @@
|
|||
#include "VFSDir.h"
|
||||
#include "VFSLoader.h"
|
||||
|
||||
VFS_NAMESPACE_START
|
||||
|
||||
VFSLoader::VFSLoader()
|
||||
: root(NULL)
|
||||
{
|
||||
}
|
||||
//#include <stdio.h>
|
||||
|
||||
|
||||
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
|
||||
|
@ -84,6 +79,12 @@ static bool findFileHarder(char *fn)
|
|||
#endif
|
||||
|
||||
|
||||
VFS_NAMESPACE_START
|
||||
|
||||
VFSLoader::VFSLoader()
|
||||
: root(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DiskLoader::DiskLoader()
|
||||
{
|
||||
|
@ -111,6 +112,8 @@ File *DiskLoader::Load(const char *fn, const char * /*ignored*/)
|
|||
|
||||
Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/)
|
||||
{
|
||||
//printf("DiskLoader: Trying [%s]...\n", fn);
|
||||
|
||||
if(!IsDirectory(fn))
|
||||
return NULL;
|
||||
|
||||
|
@ -124,12 +127,19 @@ Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/)
|
|||
fn = &t[0];
|
||||
#endif
|
||||
|
||||
ret = safecastNonNull<DiskDir*>(getRoot()->getDir(fn, true, false));
|
||||
assert(getRoot()->_getDirEx(fn, fn, false, false, false).first == NULL); // makes no sense to fire up the loader if it's already in the tree
|
||||
|
||||
ret = safecastNonNull<DiskDir*>(getRoot()->_createAndInsertSubtree(fn));
|
||||
|
||||
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
|
||||
VFS_STACK_FREE(t);
|
||||
#endif
|
||||
|
||||
/*if(ret)
|
||||
printf("DiskLoader: [%s] OK as [%s]\n", fn, ret->fullname());
|
||||
else
|
||||
printf("DiskLoader: [%s] FAILED\n", fn);*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// VFSRoot.cpp - glues it all together and makes use simple
|
||||
// For conditions of distribution and use, see copyright notice in VFS.h
|
||||
|
||||
#include <iostream> // for debug only, see EOF
|
||||
#include <set>
|
||||
|
||||
#include "VFSInternal.h"
|
||||
#include "VFSRoot.h"
|
||||
|
@ -11,6 +11,9 @@
|
|||
#include "VFSFile.h"
|
||||
#include "VFSLoader.h"
|
||||
#include "VFSArchiveLoader.h"
|
||||
#include "VFSDirView.h"
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
# include <cassert>
|
||||
|
@ -71,7 +74,7 @@ void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
|
|||
{
|
||||
if(!subdir)
|
||||
subdir = dir->fullname();
|
||||
InternalDir *into = safecastNonNull<InternalDir*>(merged->getDir(subdir, true, true, false));
|
||||
InternalDir *into = safecastNonNull<InternalDir*>(merged->_getDirEx(subdir, subdir, true, true, false).first);
|
||||
into->_addMountDir(dir);
|
||||
}
|
||||
|
||||
|
@ -96,6 +99,7 @@ void Root::AddArchiveLoader(VFSArchiveLoader *ldr)
|
|||
{
|
||||
archLdrs.push_back(ldr);
|
||||
}
|
||||
|
||||
Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */)
|
||||
{
|
||||
return AddArchive(GetFile(arch), arch, opaque);
|
||||
|
@ -161,7 +165,8 @@ InternalDir *Root::_GetDirByLoader(VFSLoader *ldr, const char *fn, const char *u
|
|||
InternalDir *ret = NULL;
|
||||
if(realdir)
|
||||
{
|
||||
ret = safecastNonNull<InternalDir*>(merged->getDir(fn, true, true, false));
|
||||
//ret = safecastNonNull<InternalDir*>(merged->_getDirEx(fn, fn, true, true, false).first);
|
||||
ret = safecastNonNull<InternalDir*>(merged->_createAndInsertSubtree(fn));
|
||||
ret->_addMountDir(realdir);
|
||||
}
|
||||
return ret;
|
||||
|
@ -169,6 +174,7 @@ InternalDir *Root::_GetDirByLoader(VFSLoader *ldr, const char *fn, const char *u
|
|||
|
||||
DirBase *Root::GetDir(const char* dn, bool create /* = false */)
|
||||
{
|
||||
//printf("Root ::getDir [%s]\n", dn);
|
||||
const char *unmangled = dn;
|
||||
std::string fixed = dn; // TODO: get rid of alloc
|
||||
FixPath(fixed);
|
||||
|
@ -185,7 +191,7 @@ DirBase *Root::GetDir(const char* dn, bool create /* = false */)
|
|||
break;
|
||||
|
||||
if(!vd && create)
|
||||
vd = safecastNonNull<InternalDir*>(merged->getDir(dn, true)); // typecast is for debug checking only
|
||||
vd = safecastNonNull<InternalDir*>(merged->_createAndInsertSubtree(dn)); // typecast is for debug checking only
|
||||
}
|
||||
|
||||
//printf("VFS: GetDir '%s' -> '%s' (%s:%p)\n", dn, vd ? vd->fullname() : "NULL", vd ? vd->getType() : "?", vd);
|
||||
|
@ -200,6 +206,7 @@ DirBase *Root::GetDirRoot()
|
|||
|
||||
bool Root::FillDirView(const char *path, DirView& view)
|
||||
{
|
||||
//printf("Root::FillDirView [%s]\n", path);
|
||||
return merged->fillView(path, view);
|
||||
}
|
||||
|
||||
|
@ -213,54 +220,57 @@ void Root::ClearGarbage()
|
|||
|
||||
// DEBUG STUFF
|
||||
|
||||
|
||||
struct _DbgParams
|
||||
{
|
||||
_DbgParams(std::ostream& os_, DirBase *parent_, const std::string& sp_)
|
||||
: os(os_), parent(parent_), sp(sp_) {}
|
||||
_DbgParams(std::ostream& os_, const std::string& path, const std::string& sp_)
|
||||
: os(os_), mypath(path), sp(sp_) {}
|
||||
|
||||
std::ostream& os;
|
||||
DirBase *parent;
|
||||
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->name() << " [" << vf->getType() << ", ref " << vf->getRefCount() << ", 0x" << vf << "]";
|
||||
|
||||
if(strncmp(p.parent->fullname(), vf->fullname(), p.parent->fullnameLen()))
|
||||
p.os << " <-- {" << vf->fullname() << "} ***********";
|
||||
|
||||
p.os << std::endl;
|
||||
p.os << p.sp << " F:" << vf->fullname() << " [" << vf->getType() << ", ref " << vf->getRefCount() << ", 0x" << vf << "]" << std::endl;
|
||||
}
|
||||
|
||||
static void _DumpTreeRecursive(DirBase *vd, void *user)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string sub = p.sp + " ";
|
||||
|
||||
p.os << p.sp << "d|" << vd->name() << " [" << vd->getType() << ", ref " << vd->getRefCount() << ", 0x" << vd << "]";
|
||||
|
||||
if(p.parent && strncmp(p.parent->fullname(), vd->fullname(), strlen(p.parent->fullname())))
|
||||
p.os << " <-- {" << vd->fullname() << "} ***********";
|
||||
p.os << std::endl;
|
||||
|
||||
_DbgParams recP(p.os, vd, sub);
|
||||
static void _DumpTree(_DbgParams& p, Root& vfs, int level)
|
||||
{
|
||||
p.os << ">> [" << p.mypath << "]" << std::endl;
|
||||
DirView view;
|
||||
vfs.FillDirView(p.mypath.c_str(), view);
|
||||
|
||||
vd->forEachDir(_DumpTreeRecursive, &recP);
|
||||
view.forEachDir(_DumpDir, &p);
|
||||
view.forEachFile(_DumpFile, &p);
|
||||
|
||||
vd->forEachFile(_DumpFile, &recP);
|
||||
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 Root::debugDumpTree(std::ostream& os, Dir *start /* = NULL */)
|
||||
void Root::debugDumpTree(std::ostream& os, const char *path, int level)
|
||||
{
|
||||
_DbgParams recP(os, NULL, "");
|
||||
DirBase *d = start ? start : GetDirRoot();
|
||||
_DumpTreeRecursive(d, &recP);
|
||||
os << ">>> FILE TREE DUMP <<<" << std::endl;
|
||||
_DbgParams recP(os, path, "");
|
||||
_DumpTree(recP, *this, level);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <vector>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iosfwd>
|
||||
|
||||
#include "VFSRefcounted.h"
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
DirBase *GetDir(const char* dn, bool create = false);
|
||||
|
||||
// DEBUG STUFF
|
||||
void debugDumpTree(std::ostream& os, Dir *start = NULL);
|
||||
void debugDumpTree(std::ostream& os, const char *path, int level);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -317,8 +317,10 @@ void FixPath(std::string& s)
|
|||
s.clear();
|
||||
return;
|
||||
}
|
||||
if(s.c_str() != p)
|
||||
s = p;
|
||||
size_t len = s.length();
|
||||
while(len)
|
||||
while(len > 1) // remove all trailing slashes unless the first char is a slash -- leave it there for absolute unix paths
|
||||
{
|
||||
char end = s[len - 1];
|
||||
if(end == '/' || end == '\\') // strip trailing '/'
|
||||
|
@ -354,9 +356,12 @@ void MakeSlashTerminated(std::string& s)
|
|||
s += '/';
|
||||
}
|
||||
|
||||
// extracts the file name from a given path
|
||||
// extracts the file name (part after the last /) from a given path
|
||||
// returns the string "/" as-is.
|
||||
const char *GetBaseNameFromPath(const char *str)
|
||||
{
|
||||
if(str[0] == '/' && !str[1])
|
||||
return str;
|
||||
const char *p = strrchr(str, '/');
|
||||
return p ? p+1 : str;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ttvfs.h>
|
||||
|
||||
namespace ttvfs
|
||||
{
|
||||
class File;
|
||||
class Root;
|
||||
};
|
||||
typedef ttvfs::File VFILE;
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ void ZipDir::load()
|
|||
continue;
|
||||
if(mz_zip_reader_is_file_a_directory(MZ, i))
|
||||
{
|
||||
getDir(fs.m_filename, true);
|
||||
_createAndInsertSubtree(fs.m_filename);
|
||||
continue;
|
||||
}
|
||||
if(getFile(fs.m_filename))
|
||||
|
|
|
@ -114,6 +114,7 @@ size_t ZipFile::read(void *dst, size_t bytes)
|
|||
size_t ZipFile::write(const void *src, size_t bytes)
|
||||
{
|
||||
// TODO: implement actually writing to the underlying Zip file.
|
||||
//printf("NYI: ZipFile::write()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -130,7 +131,10 @@ bool ZipFile::unpack()
|
|||
delete [] _buf;
|
||||
|
||||
if(!_archiveHandle->openRead())
|
||||
{
|
||||
//assert(0 && "ZipFile unpack: Failed to openRead");
|
||||
return false; // can happen if the underlying zip file was deleted
|
||||
}
|
||||
|
||||
// In case of text data, make sure the buffer is always terminated with '\0'.
|
||||
// Won't hurt for binary data, so just do it in all cases.
|
||||
|
@ -141,6 +145,7 @@ bool ZipFile::unpack()
|
|||
|
||||
if(!mz_zip_reader_extract_to_mem(MZ, _fileIdx, _buf, sz, 0))
|
||||
{
|
||||
//assert(0 && "ZipFile unpack: Failed mz_zip_reader_extract_to_mem");
|
||||
delete [] _buf;
|
||||
_buf = NULL;
|
||||
return false; // this should not happen
|
||||
|
|
Loading…
Reference in a new issue