mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-25 22:25:46 +00:00
107 lines
No EOL
2.3 KiB
C++
107 lines
No EOL
2.3 KiB
C++
#include "VFSFileZip.h"
|
|
#include "VFSDirZip.h"
|
|
#include "VFSTools.h"
|
|
|
|
#include "VFSInternal.h"
|
|
|
|
#include "miniz.h"
|
|
|
|
VFS_NAMESPACE_START
|
|
|
|
|
|
static size_t zip_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
|
|
{
|
|
VFSFile *vf = (VFSFile*)pOpaque;
|
|
mz_int64 cur_ofs = vf->getpos();
|
|
if((mz_int64)file_ofs < 0)
|
|
return 0;
|
|
if(cur_ofs != (mz_int64)file_ofs && !vf->seek((vfspos)file_ofs))
|
|
return 0;
|
|
return vf->read(pBuf, n);
|
|
}
|
|
|
|
static bool zip_reader_init_vfsfile(mz_zip_archive *pZip, VFSFile *vf, mz_uint32 flags)
|
|
{
|
|
if(!(pZip || vf))
|
|
return false;
|
|
vf->open("rb");
|
|
mz_uint64 file_size = vf->size();
|
|
if(!file_size)
|
|
{
|
|
vf->close();
|
|
return false;
|
|
}
|
|
pZip->m_pRead = zip_read_func;
|
|
pZip->m_pIO_opaque = vf;
|
|
if (!mz_zip_reader_init(pZip, file_size, flags))
|
|
{
|
|
vf->close();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
VFSDirZip::VFSDirZip(VFSFile *zf)
|
|
: VFSDir(zf->fullname()), _zf(zf)
|
|
{
|
|
_zf->ref++;
|
|
_setOrigin(this);
|
|
memset(&_zip, 0, sizeof(_zip));
|
|
}
|
|
|
|
VFSDirZip::~VFSDirZip()
|
|
{
|
|
close();
|
|
_zf->ref--;
|
|
}
|
|
|
|
bool VFSDirZip::close(void)
|
|
{
|
|
mz_zip_reader_end(&_zip);
|
|
_zf->close();
|
|
return true;
|
|
}
|
|
|
|
VFSDir *VFSDirZip::createNew(const char *dir) const
|
|
{
|
|
return VFSDir::createNew(dir); // inside a Zip file; only the base dir can be a real VFSDirZip.
|
|
}
|
|
|
|
unsigned int VFSDirZip::load(bool /*ignored*/)
|
|
{
|
|
close();
|
|
|
|
if(!zip_reader_init_vfsfile(&_zip, _zf, 0))
|
|
return 0;
|
|
|
|
unsigned int files = mz_zip_reader_get_num_files(&_zip);
|
|
|
|
mz_zip_archive_file_stat fs;
|
|
for (unsigned int i = 0; i < files; ++i)
|
|
{
|
|
// FIXME: do we want empty dirs in the tree?
|
|
if(mz_zip_reader_is_file_a_directory(&_zip, i))
|
|
continue;
|
|
if(mz_zip_reader_is_file_encrypted(&_zip, i))
|
|
continue;
|
|
if(!mz_zip_reader_file_stat(&_zip, i, &fs))
|
|
continue;
|
|
if(getFile(fs.m_filename))
|
|
continue;
|
|
|
|
VFSFileZip *vf = new VFSFileZip(&_zip);
|
|
vf->_setOrigin(this);
|
|
memcpy(vf->getZipFileStat(), &fs, sizeof(mz_zip_archive_file_stat));
|
|
vf->_init();
|
|
addRecursive(vf, true, VFSDir::NONE);
|
|
vf->ref--;
|
|
}
|
|
|
|
// Not necessary to keep open all the time, VFSFileZip will re-open the archive if needed
|
|
//close();
|
|
|
|
return files;
|
|
}
|
|
|
|
VFS_NAMESPACE_END |