6e8fbca745
match the genesis editor version 1.3.0.653.
265 lines
7.8 KiB
C++
265 lines
7.8 KiB
C++
/****************************************************************************
|
|
Copyright (c) 2009, Radon Labs GmbH
|
|
Copyright (c) 2011-2013,WebJet Business Division,CYOU
|
|
|
|
http://www.genesis-3d.com.cn
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "stdneb.h"
|
|
#include "io/archfs/archivefilesystembase.h"
|
|
#include "io/archfs/archive.h"
|
|
#include "io/assignregistry.h"
|
|
|
|
namespace IO
|
|
{
|
|
__ImplementClass(IO::ArchiveFileSystemBase, 'AFSB', Core::RefCounted);
|
|
__ImplementImageSingleton(IO::ArchiveFileSystemBase);
|
|
|
|
using namespace Util;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
ArchiveFileSystemBase::ArchiveFileSystemBase() :
|
|
isValid(false)
|
|
{
|
|
__ConstructImageSingleton;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
ArchiveFileSystemBase::~ArchiveFileSystemBase()
|
|
{
|
|
if (this->IsValid())
|
|
{
|
|
// make sure that derived method is called
|
|
this->Discard();
|
|
}
|
|
__DestructImageSingleton;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Setup the archive file system. Subclasses may register their
|
|
archive stream classes with the SchemeRegistry here.
|
|
*/
|
|
void
|
|
ArchiveFileSystemBase::Setup()
|
|
{
|
|
n_assert(!this->IsValid());
|
|
this->isValid = true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Discard the archive file system.
|
|
*/
|
|
void
|
|
ArchiveFileSystemBase::Discard()
|
|
{
|
|
n_assert(this->IsValid());
|
|
|
|
// unmount all mounted filesystems
|
|
while (!this->archives.IsEmpty())
|
|
{
|
|
// make sure that derived method is called
|
|
this->Unmount(this->archives.ValueAtIndex(0));
|
|
}
|
|
|
|
this->isValid = false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
This "mounts" an archive file by creating a new Archive object
|
|
and adding it to the archive dictionary. If mounting fails, an invalid
|
|
pointer will be returned!
|
|
*/
|
|
GPtr<Archive>
|
|
ArchiveFileSystemBase::Mount(const URI& uri)
|
|
{
|
|
n_assert(!this->IsMounted(uri));
|
|
String path = AssignRegistry::Instance()->ResolveAssigns(uri).LocalPath();
|
|
GPtr<Archive> newArchive = Archive::Create();
|
|
if (newArchive->Setup(uri))
|
|
{
|
|
this->critSect.Enter();
|
|
this->archives.Add(path, newArchive);
|
|
this->critSect.Leave();
|
|
}
|
|
else
|
|
{
|
|
newArchive = 0;
|
|
}
|
|
return newArchive;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Unmount a zip archive, this will remove the archive from the internal
|
|
archive registry, and call the Discard() method on it.
|
|
*/
|
|
void
|
|
ArchiveFileSystemBase::Unmount(const GPtr<Archive>& archive)
|
|
{
|
|
n_assert(this->IsMounted(archive->GetURI()));
|
|
archive->Discard();
|
|
String path = AssignRegistry::Instance()->ResolveAssigns(archive->GetURI()).LocalPath();
|
|
|
|
this->critSect.Enter();
|
|
this->archives.Erase(path);
|
|
this->critSect.Leave();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Unmount an archive by the archive's URI.
|
|
*/
|
|
void
|
|
ArchiveFileSystemBase::Unmount(const URI& uri)
|
|
{
|
|
n_assert(this->IsMounted(uri));
|
|
String path = AssignRegistry::Instance()->ResolveAssigns(uri).LocalPath();
|
|
GPtr<Archive> archive = this->archives[path];
|
|
archive->Discard();
|
|
|
|
this->critSect.Enter();
|
|
this->archives.Erase(path);
|
|
this->critSect.Leave();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Return all currently mounted archives.
|
|
*/
|
|
Array<GPtr<Archive> >
|
|
ArchiveFileSystemBase::GetMountedArchives() const
|
|
{
|
|
this->critSect.Enter();
|
|
Array<GPtr<Archive> > archiveArray = this->archives.ValuesAsArray();
|
|
this->critSect.Leave();
|
|
return archiveArray;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Resolve an archive path into an Archive pointer. Returns 0
|
|
if no archive with that name exists. The filename will be resolved into
|
|
an absolute path internally before the lookup happens.
|
|
*/
|
|
GPtr<Archive>
|
|
ArchiveFileSystemBase::FindArchive(const URI& uri) const
|
|
{
|
|
String path = AssignRegistry::Instance()->ResolveAssigns(uri).LocalPath();
|
|
GPtr<Archive> result;
|
|
|
|
this->critSect.Enter();
|
|
IndexT index = this->archives.FindIndex(path);
|
|
if (InvalidIndex != index)
|
|
{
|
|
result = this->archives.ValueAtIndex(index);
|
|
}
|
|
this->critSect.Leave();
|
|
return result;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
bool
|
|
ArchiveFileSystemBase::IsMounted(const URI& uri) const
|
|
{
|
|
String path = AssignRegistry::Instance()->ResolveAssigns(uri).LocalPath();
|
|
this->critSect.Enter();
|
|
bool result = this->archives.Contains(path);
|
|
this->critSect.Leave();
|
|
return result;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
This method should return the archive which contains the provided
|
|
file URI. Override this method in a derived class!
|
|
*/
|
|
GPtr<Archive>
|
|
ArchiveFileSystemBase::FindArchiveWithFile(const URI& uri) const
|
|
{
|
|
return GPtr<Archive>();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
This method should return the archive which contains the
|
|
provided directory URI. Override this method in a derived class!
|
|
*/
|
|
GPtr<Archive>
|
|
ArchiveFileSystemBase::FindArchiveWithDir(const URI& uri) const
|
|
{
|
|
return GPtr<Archive>();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
This method should check if the provided URI is located in any
|
|
of the mounted archives, and if yes, return a converted the URI
|
|
which describes how the file in the archive is accessed.
|
|
|
|
This method must be overriden in a subclass, the base class implementation
|
|
will always return the original URI!
|
|
*/
|
|
URI
|
|
ArchiveFileSystemBase::ConvertFileToArchiveURIIfExists(const URI& uri) const
|
|
{
|
|
if (uri.Scheme() == "file")
|
|
{
|
|
// make sure that derived method is called
|
|
GPtr<Archive> archive = this->FindArchiveWithFile(uri);
|
|
if (archive.isvalid())
|
|
{
|
|
return archive->ConvertToArchiveURI(uri);
|
|
}
|
|
}
|
|
// fallthrough: no match, return original uri
|
|
return uri;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
This method is the directory version of ConvertFileToArchiveURIIfExists().
|
|
*/
|
|
URI
|
|
ArchiveFileSystemBase::ConvertDirToArchiveURIIfExists(const URI& uri) const
|
|
{
|
|
if (uri.Scheme() == "file")
|
|
{
|
|
GPtr<Archive> archive = this->FindArchiveWithDir(uri);
|
|
if (archive.isvalid())
|
|
{
|
|
return archive->ConvertToArchiveURI(uri);
|
|
}
|
|
}
|
|
// fallthrough: no match, return original uri
|
|
return uri;
|
|
}
|
|
|
|
} // namespace IO
|