1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-02-03 18:14:01 +00:00

ttvfs update

This commit is contained in:
fgenesis 2014-04-15 15:04:33 +02:00
parent 87bc46abf6
commit 3cf3ac7659
13 changed files with 220 additions and 120 deletions

View file

@ -11,10 +11,12 @@ VFSBase::VFSBase()
{ {
} }
VFSBase::~VFSBase()
{
}
void VFSBase::_setName(const char *n) void VFSBase::_setName(const char *n)
{ {
if(!n)
return;
_fullname = n; _fullname = n;
FixPath(_fullname); FixPath(_fullname);
_name = GetBaseNameFromPath(_fullname.c_str()); _name = GetBaseNameFromPath(_fullname.c_str());

View file

@ -14,7 +14,7 @@ VFS_NAMESPACE_START
class VFSBase : public Refcounted class VFSBase : public Refcounted
{ {
public: public:
virtual ~VFSBase() {} virtual ~VFSBase();
/** Returns the plain file name. Never NULL. */ /** Returns the plain file name. Never NULL. */
inline const char *name() const { return _name; } inline const char *name() const { return _name; }

View file

@ -18,7 +18,7 @@
// (no sane programmer should do this, anyway). // (no sane programmer should do this, anyway).
// However, on non-windows systems this will decrease performance when checking for files // However, on non-windows systems this will decrease performance when checking for files
// on disk (see VFSLoader.cpp). // on disk (see VFSLoader.cpp).
#define VFS_IGNORE_CASE //#define VFS_IGNORE_CASE
/* --- End of config section --- */ /* --- End of config section --- */

View file

@ -10,6 +10,8 @@
#include "VFSDirView.h" #include "VFSDirView.h"
#include "VFSLoader.h" #include "VFSLoader.h"
//#include <stdio.h>
VFS_NAMESPACE_START VFS_NAMESPACE_START
DirBase::DirBase(const char *fullpath) DirBase::DirBase(const char *fullpath)
@ -30,23 +32,34 @@ File *DirBase::getFile(const char *fn)
if(!slashpos) if(!slashpos)
return getFileByName(fn, true); return getFileByName(fn, true);
const size_t len = slashpos - fn; size_t copysize = std::max<size_t>(slashpos - fn, 1); // always copy the '/' if it's the first char
char *dirname = (char*)VFS_STACK_ALLOC(len + 1); char * const dirname = (char*)VFS_STACK_ALLOC(copysize + 1);
memcpy(dirname, fn, len); memcpy(dirname, fn, copysize);
dirname[len] = 0; dirname[copysize] = 0;
File *f = getFileFromSubdir(dirname, slashpos + 1); File *f = getFileFromSubdir(dirname, slashpos + 1);
VFS_STACK_FREE(dirname); VFS_STACK_FREE(dirname);
return f; 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); SkipSelfPath(subdir);
if(!subdir[0]) if(!subdir[0])
return this; return std::make_pair(this, this);
DirBase *ret = NULL; DirBase *ret = NULL;
DirBase *last = NULL;
char *slashpos = (char *)strchr(subdir, '/'); char *slashpos = (char *)strchr(subdir, '/');
// if there is a '/' in the string, descend into subdir and continue there // if there is a '/' in the string, descend into subdir and continue there
@ -54,74 +67,93 @@ DirBase *DirBase::getDir(const char *subdir, bool forceCreate /* = false */, boo
{ {
// from a/b/c, cut out the a, without the trailing '/'. // from a/b/c, cut out the a, without the trailing '/'.
const char *sub = slashpos + 1; 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); char * const t = (char*)VFS_STACK_ALLOC(copysize + 1);
memcpy(t, subdir, copysize); memcpy(t, subdir, copysize);
t[copysize] = 0; t[copysize] = 0;
if(DirBase *dir = getDirByName(t, lazyLoad, useSubtrees)) if(DirBase *dir = getDirByName(t, lazyLoad, useSubtrees))
{ {
// TODO: get rid of recursion std::pair<DirBase*, DirBase*> subpair = dir->_getDirEx(sub, fullpath, forceCreate, lazyLoad); // descend into subdirs
ret = dir->getDir(sub, forceCreate, lazyLoad); // descend into subdirs ret = subpair.first;
}
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
} }
} }
else else
{ {
if(DirBase *dir = getDirByName(subdir, lazyLoad, useSubtrees)) if(DirBase *dir = getDirByName(subdir, lazyLoad, useSubtrees))
ret = dir; 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(); size_t subdirLen = strlen(subdir);
if(fullLen) 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 // -> newname = fullname() + '/' + subdir
size_t fullLen = fullnameLen();
size_t subdirLen = strlen(subdir); size_t subdirLen = strlen(subdir);
char * const newname = (char*)VFS_STACK_ALLOC(fullLen + subdirLen + 2); char * const newname = (char*)VFS_STACK_ALLOC(fullLen + subdirLen + 2);
char *ptr = newname; char *ptr = newname;
if(fullLen)
{
memcpy(ptr, fullname(), fullLen); memcpy(ptr, fullname(), fullLen);
ptr += fullLen; ptr += fullLen;
if(ptr[-1] != '/')
*ptr++ = '/'; *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); VFS_STACK_FREE(newname);
}
else
{
ret = createNew(subdir);
}
_subdirs[ret->name()] = ret;
}
}
return ret; return ret;
} }
static void _iterDirs(Dirs &m, DirEnumCallback f, void *user) static void _iterDirs(Dirs &m, DirEnumCallback f, void *user)
{ {
for(Dirs::iterator it = m.begin(); it != m.end(); ++it) for(Dirs::iterator it = m.begin(); it != m.end(); ++it)
@ -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 */) 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); Dirs::iterator it = _subdirs.find(dn);
return it != _subdirs.end() ? it->second : NULL; 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); _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) 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. // prefixLen == 0 is invalid, prefixLen == 1 is just a single '/', which will be stripped away below.
// in both cases, just use 'this'. // in both cases, just use 'this'.
// FIXME: will this be a problem for absolute paths?
if(prefixLen > 1) if(prefixLen > 1)
{ {
char *dirname = (char*)VFS_STACK_ALLOC(prefixLen); char *dirname = (char*)VFS_STACK_ALLOC(prefixLen);
--prefixLen; // -1 to strip the trailing '/'. That's the position where to put the terminating null byte. --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 memcpy(dirname, f->fullname() + skip, prefixLen); // copy trailing null byte
dirname[prefixLen] = 0; dirname[prefixLen] = 0;
vdir = safecastNonNull<Dir*>(getDir(dirname, true)); vdir = safecastNonNull<Dir*>(_getDirEx(dirname, dirname, true, true).first);
VFS_STACK_FREE(dirname); VFS_STACK_FREE(dirname);
} }
} }
@ -271,12 +314,19 @@ DirBase *Dir::getDirByName(const char *dn, bool lazyLoad /* = true */, bool useS
if(!lazyLoad || !_loader) if(!lazyLoad || !_loader)
return NULL; 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 // Lazy-load file if it's not in the tree yet
// TODO: get rid of alloc // TODO: get rid of alloc
std::string fn2 = joinPath(fullname(), dn); std::string fn2 = joinPath(fullname(), dn);
sub = _loader->LoadDir(fn2.c_str(), fn2.c_str()); sub = _loader->LoadDir(fn2.c_str(), fn2.c_str());
if(sub) if(sub)
{
_subdirs[sub->name()] = sub; _subdirs[sub->name()] = sub;
//printf("Lazy loaded: [%s]\n", sub->fullname());
}
return sub; return sub;
} }

View file

@ -83,7 +83,8 @@ public:
/** Returns a subdir, descends if necessary. If forceCreate is true, /** Returns a subdir, descends if necessary. If forceCreate is true,
create directory tree if it does not exist, and return the originally requested create directory tree if it does not exist, and return the originally requested
subdir. Otherwise return NULL if not found. */ 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. /** Returns a file from this dir's file map.
Expects the actual file name without path - does NOT descend. */ Expects the actual file name without path - does NOT descend. */
@ -102,13 +103,18 @@ public:
virtual void clearGarbage(); virtual void clearGarbage();
virtual bool _addToView(char *path, DirView& view) = 0; virtual bool _addToView(char *path, DirView& view) = 0;
DirBase *_createNewSubdir(const char *name) const;
DirBase *_createAndInsertSubtree(const char *name);
protected: protected:
/** Creates a new dir of the same type to be used as child of this. */ /** Creates a new dir of the same type to be used as child of this. */
virtual DirBase *createNew(const char *dir) const = 0; virtual DirBase *createNew(const char *dir) const = 0;
Dirs _subdirs; Dirs _subdirs;
}; };
class Dir : public DirBase class Dir : public DirBase
@ -131,6 +137,7 @@ public:
virtual void load() = 0; virtual void load() = 0;
void forEachFile(FileEnumCallback f, void *user = NULL, bool safe = false); void forEachFile(FileEnumCallback f, void *user = NULL, bool safe = false);
void forEachDir(DirEnumCallback f, void *user = NULL, bool safe = false);
virtual void clearGarbage(); virtual void clearGarbage();

View file

@ -5,6 +5,8 @@
#include "VFSTools.h" #include "VFSTools.h"
#include <algorithm> #include <algorithm>
//#include <stdio.h>
VFS_NAMESPACE_START 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) bool InternalDir::fillView(const char *path, DirView& view)
{ {
SkipSelfPath(path);
view.init(path); view.init(path);
size_t len = strlen(path) + 1; size_t len = view.fullnameLen() + 1;
char *pathcopy = (char*)VFS_STACK_ALLOC(len); char *pathcopy = (char*)VFS_STACK_ALLOC(len);
memcpy(pathcopy, path, len); memcpy(pathcopy, view.fullname(), len);
bool added = _addToView(pathcopy, view); bool added = _addToView(pathcopy, view);
VFS_STACK_FREE(pathcopy); VFS_STACK_FREE(pathcopy);
return added; return added;
@ -132,6 +133,7 @@ bool InternalDir::fillView(const char *path, DirView& view)
bool InternalDir::_addToView(char *path, DirView& view) bool InternalDir::_addToView(char *path, DirView& view)
{ {
bool added = false; bool added = false;
SkipSelfPath(path);
if(!*path) if(!*path)
{ {
@ -143,14 +145,20 @@ bool InternalDir::_addToView(char *path, DirView& view)
} }
else else
{ {
SkipSelfPath(path);
char dummy = 0; char dummy = 0;
char slash[2] = {'/', 0};
char *slashpos = strchr(path, '/'); char *slashpos = strchr(path, '/');
char *tail = slashpos ? slashpos+1 : &dummy; char *tail = slashpos ? slashpos+1 : &dummy;
// if the first char is a slash, use "/" to lookup
if(slashpos == path)
path = &slash[0];
if(slashpos) if(slashpos)
*slashpos = 0; *slashpos = 0;
//printf("InternalDir::_addToView [%s] [%s]\n", path, tail);
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it) for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
if(DirBase *subdir = (*it)->getDirByName(path)) if(DirBase *subdir = (*it)->getDirByName(path))
added = subdir->_addToView(tail, view) || added; added = subdir->_addToView(tail, view) || added;

View file

@ -7,12 +7,7 @@
#include "VFSDir.h" #include "VFSDir.h"
#include "VFSLoader.h" #include "VFSLoader.h"
VFS_NAMESPACE_START //#include <stdio.h>
VFSLoader::VFSLoader()
: root(NULL)
{
}
#if !defined(_WIN32) && defined(VFS_IGNORE_CASE) #if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
@ -84,6 +79,12 @@ static bool findFileHarder(char *fn)
#endif #endif
VFS_NAMESPACE_START
VFSLoader::VFSLoader()
: root(NULL)
{
}
DiskLoader::DiskLoader() DiskLoader::DiskLoader()
{ {
@ -111,6 +112,8 @@ File *DiskLoader::Load(const char *fn, const char * /*ignored*/)
Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/) Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/)
{ {
//printf("DiskLoader: Trying [%s]...\n", fn);
if(!IsDirectory(fn)) if(!IsDirectory(fn))
return NULL; return NULL;
@ -124,12 +127,19 @@ Dir *DiskLoader::LoadDir(const char *fn, const char * /*ignored*/)
fn = &t[0]; fn = &t[0];
#endif #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) #if !defined(_WIN32) && defined(VFS_IGNORE_CASE)
VFS_STACK_FREE(t); VFS_STACK_FREE(t);
#endif #endif
/*if(ret)
printf("DiskLoader: [%s] OK as [%s]\n", fn, ret->fullname());
else
printf("DiskLoader: [%s] FAILED\n", fn);*/
return ret; return ret;
} }

View file

@ -1,7 +1,7 @@
// VFSRoot.cpp - glues it all together and makes use simple // VFSRoot.cpp - glues it all together and makes use simple
// For conditions of distribution and use, see copyright notice in VFS.h // 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 "VFSInternal.h"
#include "VFSRoot.h" #include "VFSRoot.h"
@ -11,6 +11,9 @@
#include "VFSFile.h" #include "VFSFile.h"
#include "VFSLoader.h" #include "VFSLoader.h"
#include "VFSArchiveLoader.h" #include "VFSArchiveLoader.h"
#include "VFSDirView.h"
//#include <stdio.h>
#ifdef _DEBUG #ifdef _DEBUG
# include <cassert> # include <cassert>
@ -71,7 +74,7 @@ void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */)
{ {
if(!subdir) if(!subdir)
subdir = dir->fullname(); 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); into->_addMountDir(dir);
} }
@ -96,6 +99,7 @@ void Root::AddArchiveLoader(VFSArchiveLoader *ldr)
{ {
archLdrs.push_back(ldr); archLdrs.push_back(ldr);
} }
Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */) Dir *Root::AddArchive(const char *arch, void *opaque /* = NULL */)
{ {
return AddArchive(GetFile(arch), arch, opaque); return AddArchive(GetFile(arch), arch, opaque);
@ -161,7 +165,8 @@ InternalDir *Root::_GetDirByLoader(VFSLoader *ldr, const char *fn, const char *u
InternalDir *ret = NULL; InternalDir *ret = NULL;
if(realdir) 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); ret->_addMountDir(realdir);
} }
return ret; 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 */) DirBase *Root::GetDir(const char* dn, bool create /* = false */)
{ {
//printf("Root ::getDir [%s]\n", dn);
const char *unmangled = dn; const char *unmangled = dn;
std::string fixed = dn; // TODO: get rid of alloc std::string fixed = dn; // TODO: get rid of alloc
FixPath(fixed); FixPath(fixed);
@ -185,7 +191,7 @@ DirBase *Root::GetDir(const char* dn, bool create /* = false */)
break; break;
if(!vd && create) 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); //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) bool Root::FillDirView(const char *path, DirView& view)
{ {
//printf("Root::FillDirView [%s]\n", path);
return merged->fillView(path, view); return merged->fillView(path, view);
} }
@ -213,54 +220,57 @@ void Root::ClearGarbage()
// DEBUG STUFF // DEBUG STUFF
struct _DbgParams struct _DbgParams
{ {
_DbgParams(std::ostream& os_, DirBase *parent_, const std::string& sp_) _DbgParams(std::ostream& os_, const std::string& path, const std::string& sp_)
: os(os_), parent(parent_), sp(sp_) {} : os(os_), mypath(path), sp(sp_) {}
std::ostream& os; std::ostream& os;
DirBase *parent; std::string mypath;
const std::string& sp; const std::string& sp;
std::set<std::string> dirnames;
}; };
static void _DumpFile(File *vf, void *user) static void _DumpFile(File *vf, void *user)
{ {
_DbgParams& p = *((_DbgParams*)user); _DbgParams& p = *((_DbgParams*)user);
p.os << p.sp << " F:" << vf->fullname() << " [" << vf->getType() << ", ref " << vf->getRefCount() << ", 0x" << vf << "]" << std::endl;
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;
} }
static void _DumpTreeRecursive(DirBase *vd, void *user)
static void _DumpDir(DirBase *vd, void *user)
{ {
_DbgParams& p = *((_DbgParams*)user); _DbgParams& p = *((_DbgParams*)user);
if(!(vd->fullname()[0] == '/' && vd->fullnameLen() == 1)) // don't recurse down the root dir.
std::string sub = p.sp + " "; p.dirnames.insert(vd->name());
p.os << p.sp << "D : " << vd->fullname() << " [" << vd->getType() << ", ref " << vd->getRefCount() << ", 0x" << vd << "]" << std::endl;
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);
vd->forEachDir(_DumpTreeRecursive, &recP);
vd->forEachFile(_DumpFile, &recP);
} }
void Root::debugDumpTree(std::ostream& os, Dir *start /* = NULL */) static void _DumpTree(_DbgParams& p, Root& vfs, int level)
{ {
_DbgParams recP(os, NULL, ""); p.os << ">> [" << p.mypath << "]" << std::endl;
DirBase *d = start ? start : GetDirRoot(); DirView view;
_DumpTreeRecursive(d, &recP); vfs.FillDirView(p.mypath.c_str(), view);
view.forEachDir(_DumpDir, &p);
view.forEachFile(_DumpFile, &p);
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, const char *path, int level)
{
os << ">>> FILE TREE DUMP <<<" << std::endl;
_DbgParams recP(os, path, "");
_DumpTree(recP, *this, level);
} }

View file

@ -7,7 +7,7 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <string> #include <string>
#include <iostream> #include <iosfwd>
#include "VFSRefcounted.h" #include "VFSRefcounted.h"
@ -103,7 +103,7 @@ public:
DirBase *GetDir(const char* dn, bool create = false); DirBase *GetDir(const char* dn, bool create = false);
// DEBUG STUFF // DEBUG STUFF
void debugDumpTree(std::ostream& os, Dir *start = NULL); void debugDumpTree(std::ostream& os, const char *path, int level);
protected: protected:

View file

@ -317,8 +317,10 @@ void FixPath(std::string& s)
s.clear(); s.clear();
return; return;
} }
if(s.c_str() != p)
s = p;
size_t len = s.length(); 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]; char end = s[len - 1];
if(end == '/' || end == '\\') // strip trailing '/' if(end == '/' || end == '\\') // strip trailing '/'
@ -354,9 +356,12 @@ void MakeSlashTerminated(std::string& s)
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) const char *GetBaseNameFromPath(const char *str)
{ {
if(str[0] == '/' && !str[1])
return str;
const char *p = strrchr(str, '/'); const char *p = strrchr(str, '/');
return p ? p+1 : str; return p ? p+1 : str;
} }

View file

@ -25,8 +25,11 @@
#include <sstream> #include <sstream>
#include <stdio.h> #include <stdio.h>
#include <ttvfs.h> namespace ttvfs
{
class File;
class Root;
};
typedef ttvfs::File VFILE; typedef ttvfs::File VFILE;

View file

@ -58,7 +58,7 @@ void ZipDir::load()
continue; continue;
if(mz_zip_reader_is_file_a_directory(MZ, i)) if(mz_zip_reader_is_file_a_directory(MZ, i))
{ {
getDir(fs.m_filename, true); _createAndInsertSubtree(fs.m_filename);
continue; continue;
} }
if(getFile(fs.m_filename)) if(getFile(fs.m_filename))

View file

@ -114,6 +114,7 @@ size_t ZipFile::read(void *dst, size_t bytes)
size_t ZipFile::write(const void *src, size_t bytes) size_t ZipFile::write(const void *src, size_t bytes)
{ {
// TODO: implement actually writing to the underlying Zip file. // TODO: implement actually writing to the underlying Zip file.
//printf("NYI: ZipFile::write()");
return 0; return 0;
} }
@ -130,7 +131,10 @@ bool ZipFile::unpack()
delete [] _buf; delete [] _buf;
if(!_archiveHandle->openRead()) if(!_archiveHandle->openRead())
{
//assert(0 && "ZipFile unpack: Failed to openRead");
return false; // can happen if the underlying zip file was deleted 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'. // 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. // 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)) 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; delete [] _buf;
_buf = NULL; _buf = NULL;
return false; // this should not happen return false; // this should not happen