1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-15 22:19:07 +00:00
Aquaria/ExternalLibs/ttvfs_zip/VFSDirZip.cpp

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