1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-26 22:55:50 +00:00
Aquaria/ExternalLibs/ttvfs/VFSDirInternal.cpp

189 lines
4.8 KiB
C++
Raw Normal View History

2014-04-06 17:19:33 +00:00
#include "VFSDirInternal.h"
#include "VFSDirView.h"
#include "VFSInternal.h"
#include "VFSFile.h"
#include "VFSTools.h"
#include <algorithm>
2014-04-15 13:04:33 +00:00
//#include <stdio.h>
2014-04-06 17:19:33 +00:00
VFS_NAMESPACE_START
// Internal class, not to be used outside
InternalDir::InternalDir(const char *fullpath)
: DirBase(fullpath)
{
}
InternalDir::~InternalDir()
{
}
void InternalDir::_clearDirs()
{
_subdirs.clear();
}
void InternalDir::_clearMounts()
{
_mountedDirs.clear();
}
InternalDir *InternalDir::createNew(const char *dir) const
{
return new InternalDir(dir);
}
void InternalDir::close()
{
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
(*it)->close();
}
void InternalDir::_addMountDir(CountedPtr<DirBase> d)
{
2014-04-07 00:25:58 +00:00
if(d.content() == this)
return;
2014-04-06 17:19:33 +00:00
// move to end of vector if already mounted
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
if(*it == d)
{
_mountedDirs.erase(it);
break;
}
_mountedDirs.push_back(d);
}
void InternalDir::_removeMountDir(DirBase *d)
{
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
if(it->content() == d)
{
_mountedDirs.erase(it);
return; // pointers are unique
}
}
File *InternalDir::getFileByName(const char *fn, bool lazyLoad /* = true */)
{
if(_mountedDirs.size())
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)
if(File *f = (*it)->getFileByName(fn, lazyLoad))
return f;
return NULL;
}
DirBase *InternalDir::getDirByName(const char *dn, bool lazyLoad /* = true */, bool useSubtrees /* = true */)
{
DirBase *sub;
if((sub = DirBase::getDirByName(dn, lazyLoad)))
return sub;
if(useSubtrees)
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)
if((sub = (*it)->getDirByName(dn, lazyLoad)))
return sub;
return NULL;
}
static void _addFileCallback(File *f, void *p)
{
((Files*)p)->insert(std::make_pair(f->name(), f)); // only inserts if not exist
}
void InternalDir::forEachFile(FileEnumCallback f, void *user /* = NULL */, bool /*ignored*/)
{
Files flist; // TODO: optimize allocation
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)
(*it)->forEachFile(_addFileCallback, &flist);
for(Files::iterator it = flist.begin(); it != flist.end(); ++it)
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)
(*it)->forEachDir(f, user, safe);
}
bool InternalDir::fillView(const char *path, DirView& view)
{
view.init(path);
2014-04-15 13:04:33 +00:00
size_t len = view.fullnameLen() + 1;
2014-04-06 17:19:33 +00:00
char *pathcopy = (char*)VFS_STACK_ALLOC(len);
2014-04-15 13:04:33 +00:00
memcpy(pathcopy, view.fullname(), len);
2014-04-06 17:19:33 +00:00
bool added = _addToView(pathcopy, view);
VFS_STACK_FREE(pathcopy);
return added;
}
bool InternalDir::_addToView(char *path, DirView& view)
{
bool added = false;
2014-04-15 13:04:33 +00:00
SkipSelfPath(path);
2014-04-06 17:19:33 +00:00
if(!*path)
{
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
{
added = true;
view.add(it->content());
}
}
else
{
char dummy = 0;
2014-04-15 13:04:33 +00:00
char slash[2] = {'/', 0};
2014-04-06 17:19:33 +00:00
char *slashpos = strchr(path, '/');
char *tail = slashpos ? slashpos+1 : &dummy;
2014-04-15 13:04:33 +00:00
// if the first char is a slash, use "/" to lookup
if(slashpos == path)
path = &slash[0];
2014-04-06 17:19:33 +00:00
if(slashpos)
*slashpos = 0;
2014-04-15 13:04:33 +00:00
//printf("InternalDir::_addToView [%s] [%s]\n", path, tail);
2014-04-06 17:19:33 +00:00
for(MountedDirs::iterator it = _mountedDirs.begin(); it != _mountedDirs.end(); ++it)
if(DirBase *subdir = (*it)->getDirByName(path))
added = subdir->_addToView(tail, view) || added;
if(InternalDir *subdir = safecast<InternalDir*>(getDirByName(path, true, false)))
added = subdir->_addToView(tail, view) || added;
if(slashpos)
*slashpos = '/';
}
return added;
}
2014-04-07 00:25:58 +00:00
File *InternalDir::getFileFromSubdir(const char *subdir, const char *file)
{
for(MountedDirs::reverse_iterator it = _mountedDirs.rbegin(); it != _mountedDirs.rend(); ++it)
if(File* f = (*it)->getFileFromSubdir(subdir, file))
return f;
2014-04-06 17:19:33 +00:00
2014-04-07 00:25:58 +00:00
InternalDir *d = safecast<InternalDir*>(DirBase::getDirByName(subdir, false, false)); // vcall not required here
return d ? d->getFile(file) : NULL;
}
2014-04-06 17:19:33 +00:00
VFS_NAMESPACE_END