From 3cf3ac76598085897597cc16277efd4cb3a1cbee Mon Sep 17 00:00:00 2001 From: fgenesis Date: Tue, 15 Apr 2014 15:04:33 +0200 Subject: [PATCH] ttvfs update --- ExternalLibs/ttvfs/VFSBase.cpp | 6 +- ExternalLibs/ttvfs/VFSBase.h | 2 +- ExternalLibs/ttvfs/VFSDefines.h | 2 +- ExternalLibs/ttvfs/VFSDir.cpp | 162 ++++++++++++++-------- ExternalLibs/ttvfs/VFSDir.h | 9 +- ExternalLibs/ttvfs/VFSDirInternal.cpp | 16 ++- ExternalLibs/ttvfs/VFSLoader.cpp | 24 +++- ExternalLibs/ttvfs/VFSRoot.cpp | 72 +++++----- ExternalLibs/ttvfs/VFSRoot.h | 8 +- ExternalLibs/ttvfs/VFSTools.cpp | 9 +- ExternalLibs/ttvfs_cfileapi/ttvfs_stdio.h | 7 +- ExternalLibs/ttvfs_zip/VFSDirZip.cpp | 2 +- ExternalLibs/ttvfs_zip/VFSFileZip.cpp | 5 + 13 files changed, 212 insertions(+), 112 deletions(-) diff --git a/ExternalLibs/ttvfs/VFSBase.cpp b/ExternalLibs/ttvfs/VFSBase.cpp index 548e683..7517099 100644 --- a/ExternalLibs/ttvfs/VFSBase.cpp +++ b/ExternalLibs/ttvfs/VFSBase.cpp @@ -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()); diff --git a/ExternalLibs/ttvfs/VFSBase.h b/ExternalLibs/ttvfs/VFSBase.h index 7aa30e0..6d9ae17 100644 --- a/ExternalLibs/ttvfs/VFSBase.h +++ b/ExternalLibs/ttvfs/VFSBase.h @@ -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; } diff --git a/ExternalLibs/ttvfs/VFSDefines.h b/ExternalLibs/ttvfs/VFSDefines.h index d0cf3cc..2dd3cdd 100644 --- a/ExternalLibs/ttvfs/VFSDefines.h +++ b/ExternalLibs/ttvfs/VFSDefines.h @@ -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 --- */ diff --git a/ExternalLibs/ttvfs/VFSDir.cpp b/ExternalLibs/ttvfs/VFSDir.cpp index 29bec36..9809fa3 100644 --- a/ExternalLibs/ttvfs/VFSDir.cpp +++ b/ExternalLibs/ttvfs/VFSDir.cpp @@ -10,6 +10,8 @@ #include "VFSDirView.h" #include "VFSLoader.h" +//#include + 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(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::_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,74 +67,93 @@ 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(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 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 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) { - size_t fullLen = fullnameLen(); - if(fullLen) + if(slashpos == buf+1) // only check this in first round { - // -> newname = fullname() + '/' + subdir - size_t subdirLen = strlen(subdir); - char * const newname = (char*)VFS_STACK_ALLOC(fullLen + subdirLen + 2); - char *ptr = newname; - memcpy(ptr, fullname(), fullLen); - ptr += fullLen; - *ptr++ = '/'; - memcpy(ptr, subdir, subdirLen); - ptr[subdirLen] = 0; - - ret = createNew(newname); - VFS_STACK_FREE(newname); + s = buf; + //printf("abs buf: [%s]\n", buf); } - else - { - ret = createNew(subdir); - } - - _subdirs[ret->name()] = ret; + *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 + 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); return ret; } + + static void _iterDirs(Dirs &m, DirEnumCallback f, void *user) { 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 */) { + 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) { @@ -222,7 +264,7 @@ bool Dir::addRecursive(File *f, size_t skip /* = 0 */) { if(!f) return false; - + Dir *vdir = this; if(f->fullnameLen() - f->nameLen() > skip) { @@ -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(getDir(dirname, true)); + vdir = safecastNonNull(_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; } diff --git a/ExternalLibs/ttvfs/VFSDir.h b/ExternalLibs/ttvfs/VFSDir.h index 65b4969..395fa90 100644 --- a/ExternalLibs/ttvfs/VFSDir.h +++ b/ExternalLibs/ttvfs/VFSDir.h @@ -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 _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(); diff --git a/ExternalLibs/ttvfs/VFSDirInternal.cpp b/ExternalLibs/ttvfs/VFSDirInternal.cpp index 9ed63ab..01a3c0a 100644 --- a/ExternalLibs/ttvfs/VFSDirInternal.cpp +++ b/ExternalLibs/ttvfs/VFSDirInternal.cpp @@ -5,6 +5,8 @@ #include "VFSTools.h" #include +//#include + 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; diff --git a/ExternalLibs/ttvfs/VFSLoader.cpp b/ExternalLibs/ttvfs/VFSLoader.cpp index 650c4eb..752cad5 100644 --- a/ExternalLibs/ttvfs/VFSLoader.cpp +++ b/ExternalLibs/ttvfs/VFSLoader.cpp @@ -7,12 +7,7 @@ #include "VFSDir.h" #include "VFSLoader.h" -VFS_NAMESPACE_START - -VFSLoader::VFSLoader() -: root(NULL) -{ -} +//#include #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(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(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; } diff --git a/ExternalLibs/ttvfs/VFSRoot.cpp b/ExternalLibs/ttvfs/VFSRoot.cpp index d54f20f..08b951e 100644 --- a/ExternalLibs/ttvfs/VFSRoot.cpp +++ b/ExternalLibs/ttvfs/VFSRoot.cpp @@ -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 // for debug only, see EOF +#include #include "VFSInternal.h" #include "VFSRoot.h" @@ -11,6 +11,9 @@ #include "VFSFile.h" #include "VFSLoader.h" #include "VFSArchiveLoader.h" +#include "VFSDirView.h" + +//#include #ifdef _DEBUG # include @@ -71,7 +74,7 @@ void Root::AddVFSDir(DirBase *dir, const char *subdir /* = NULL */) { if(!subdir) subdir = dir->fullname(); - InternalDir *into = safecastNonNull(merged->getDir(subdir, true, true, false)); + InternalDir *into = safecastNonNull(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(merged->getDir(fn, true, true, false)); + //ret = safecastNonNull(merged->_getDirEx(fn, fn, true, true, false).first); + ret = safecastNonNull(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(merged->getDir(dn, true)); // typecast is for debug checking only + vd = safecastNonNull(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 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::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); } diff --git a/ExternalLibs/ttvfs/VFSRoot.h b/ExternalLibs/ttvfs/VFSRoot.h index 7c46b8f..407e957 100644 --- a/ExternalLibs/ttvfs/VFSRoot.h +++ b/ExternalLibs/ttvfs/VFSRoot.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "VFSRefcounted.h" @@ -43,7 +43,7 @@ public: 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), + /** Drops a directory from the tree. Internally, this calls Reload(false), which is a heavy operation compared to Mount(). Be warned. */ bool Unmount(const char *src, const char *dest); @@ -72,7 +72,7 @@ public: it is sent through each registered loader until one of them can recognize the format and open it. */ void AddArchiveLoader(VFSArchiveLoader *ldr); - + /** 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. */ File *GetFile(const char *fn); @@ -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: diff --git a/ExternalLibs/ttvfs/VFSTools.cpp b/ExternalLibs/ttvfs/VFSTools.cpp index f14022d..2200522 100644 --- a/ExternalLibs/ttvfs/VFSTools.cpp +++ b/ExternalLibs/ttvfs/VFSTools.cpp @@ -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; } diff --git a/ExternalLibs/ttvfs_cfileapi/ttvfs_stdio.h b/ExternalLibs/ttvfs_cfileapi/ttvfs_stdio.h index 3830723..9cddb6c 100644 --- a/ExternalLibs/ttvfs_cfileapi/ttvfs_stdio.h +++ b/ExternalLibs/ttvfs_cfileapi/ttvfs_stdio.h @@ -25,8 +25,11 @@ #include #include -#include - +namespace ttvfs +{ + class File; + class Root; +}; typedef ttvfs::File VFILE; diff --git a/ExternalLibs/ttvfs_zip/VFSDirZip.cpp b/ExternalLibs/ttvfs_zip/VFSDirZip.cpp index 6ab4ef0..2e8c2ef 100644 --- a/ExternalLibs/ttvfs_zip/VFSDirZip.cpp +++ b/ExternalLibs/ttvfs_zip/VFSDirZip.cpp @@ -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)) diff --git a/ExternalLibs/ttvfs_zip/VFSFileZip.cpp b/ExternalLibs/ttvfs_zip/VFSFileZip.cpp index bc76a47..dbc4fa8 100644 --- a/ExternalLibs/ttvfs_zip/VFSFileZip.cpp +++ b/ExternalLibs/ttvfs_zip/VFSFileZip.cpp @@ -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