commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
211
include/modules/io_zip/io_zip.cpp
Normal file
211
include/modules/io_zip/io_zip.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "io_zip/io_zip.h"
|
||||
#include "unzip.h"
|
||||
#include "filesystem/io_handle_segment.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// I/O wrapper for unzip (allows archive access from various I/O systems).
|
||||
static voidpf Zip_open_file_func(voidpf opaque, const char *filename, int mode)
|
||||
{
|
||||
__LOG__ << "ZipOpenFileFunc(); filename: " << filename << ", mode: " << mode << ".\n";
|
||||
if (mode & ZLIB_FILEFUNC_MODE_READ)
|
||||
return GS::Platform::Get().io->Open(filename);
|
||||
if (mode & ZLIB_FILEFUNC_MODE_WRITE)
|
||||
return GS::Platform::Get().io->Open(filename, ModeWrite);
|
||||
return NULL;
|
||||
}
|
||||
static uLong Zip_read_file_func(voidpf opaque, voidpf stream, void *buf, uLong size)
|
||||
{ return ((Handle *)stream)->Read(buf, size); }
|
||||
static uLong Zip_write_file_func(voidpf opaque, voidpf stream, const void *buf, uLong size)
|
||||
{ return ((Handle *)stream)->Write(buf, size); }
|
||||
static int Zip_close_file_func(voidpf opaque, voidpf stream)
|
||||
{
|
||||
__LOG__ << "ZipCloseFileFunc();\n";
|
||||
delete ((Handle *)stream);
|
||||
return UNZ_OK;
|
||||
}
|
||||
static int Zip_testerror_file_func(voidpf opaque, voidpf stream)
|
||||
{ return UNZ_OK; }
|
||||
|
||||
static long Zip_tell_file_func(voidpf opaque, voidpf stream)
|
||||
{ return ((Handle *)stream)->Tell(); }
|
||||
static long Zip_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin)
|
||||
{
|
||||
static Base::SeekRef ref[] = { Base::SeekStart, Base::SeekCurrent, Base::SeekEnd };
|
||||
return ((Handle *)stream)->Seek(offset, ref[origin]) == -1 ? -1 : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static zlib_filefunc_def Zip_filefunc =
|
||||
{ Zip_open_file_func, Zip_read_file_func, Zip_write_file_func, Zip_tell_file_func, Zip_seek_file_func, Zip_close_file_func, Zip_testerror_file_func, 0 };
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Zip::SetArchive(const char *uri, const char *pass)
|
||||
{
|
||||
if (zfile)
|
||||
unzClose(zfile);
|
||||
zfile = NULL;
|
||||
|
||||
if (!uri)
|
||||
return true;
|
||||
|
||||
__LOG_H__ << "Zip::SetArchive() connect to archive '" << uri << "', password: " << (pass ? pass : "(empty)") << ".\n";
|
||||
|
||||
password = pass;
|
||||
return uri ? (zfile = unzOpen2(uri, &Zip_filefunc)) != NULL : false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint Zip::GetCaps() const
|
||||
{ return CanRead | CanSeek| IsCaseSensitive; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Handle *Zip::Open(const char *path, Mode mode)
|
||||
{
|
||||
if (!zfile)
|
||||
__ERR__(__LOG_E__ << "Cannot open file with no archive support.\n", NULL)
|
||||
|
||||
if (mode == ModeWrite)
|
||||
return NULL; // unsupported
|
||||
|
||||
/*
|
||||
Query the memory file system so that multiple accesses to the same
|
||||
compressed file will share a single uncompressed memory buffer.
|
||||
*/
|
||||
bool is_memory_handle = false;
|
||||
Handle *h = memfs->Open(path, mode);
|
||||
|
||||
if (!h)
|
||||
if (unzLocateFile(zfile, path, 1) == UNZ_OK) // case-sensitive
|
||||
{
|
||||
// Get file info.
|
||||
unz_file_info info;
|
||||
unzGetCurrentFileInfo(zfile, &info, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
if (info.compression_method == 0)
|
||||
{
|
||||
unzOpenCurrentFile(zfile);
|
||||
size_t offset = (size_t)unzGetCurrentFileZStreamPos64(zfile);
|
||||
unzCloseCurrentFile(zfile);
|
||||
|
||||
__LOG__ << "Mapping zip segment to '" << path << "' @" << int(offset) << "\n";
|
||||
Handle *zh = (Handle *)unzGetFileStream(zfile);
|
||||
h = new HandleSegment(zh, offset, info.uncompressed_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
__LOG__ << "Mapping unzipped '" << path << "' to memory...\n";
|
||||
|
||||
// Load the whole file into memory.
|
||||
Array <char> data(info.uncompressed_size, Alloc::Filesystem);
|
||||
if (data.GetSize() != info.uncompressed_size)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate decompression space for '" << path << "'.\n", NULL)
|
||||
|
||||
int r = password.IsEmpty() ? unzOpenCurrentFile(zfile) : unzOpenCurrentFilePassword(zfile, password);
|
||||
if (r != UNZ_OK)
|
||||
__ERR__(__LOG_E__ << "Failed to open file '" << path << "'.\n", NULL)
|
||||
if (unzReadCurrentFile(zfile, (voidp)data.c_ptr(), info.uncompressed_size) != (int)info.uncompressed_size)
|
||||
__ERR__(__LOG_E__ << "Failed to read file '" << path << "'.\n", NULL)
|
||||
unzCloseCurrentFile(zfile);
|
||||
|
||||
// Write to the support I/O memory filesystem.
|
||||
AutoPtr <Handle> wh(memfs->Open(path, ModeWrite));
|
||||
if (wh.IsValid())
|
||||
wh->Write(data.c_ptr(), data.GetSize());
|
||||
|
||||
// Open memory based uncompressed file.
|
||||
h = memfs->Open(path, mode);
|
||||
is_memory_handle = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (h)
|
||||
if (ZipHandle *z = new ZipHandle(this))
|
||||
{
|
||||
// Wrap memory I/O handle.
|
||||
if (is_memory_handle)
|
||||
{
|
||||
// Increase refcount for this file.
|
||||
Pair <String, int> *p = refc_map.Get(path);
|
||||
if (!p)
|
||||
p = refc_map.Add(path, 0);
|
||||
++p->value;
|
||||
|
||||
z->p = p;
|
||||
}
|
||||
|
||||
z->h = h;
|
||||
return z;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
void Zip::Close(Handle *h)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
{
|
||||
if (z->p)
|
||||
{
|
||||
// If refcount for this entry reaches 0, drop it from the support I/O.
|
||||
if (--z->p->value == 0)
|
||||
{
|
||||
memfs->Delete(z->p->key);
|
||||
refc_map.Delete(z->p);
|
||||
}
|
||||
z->p = NULL;
|
||||
}
|
||||
z->h = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Zip::Delete(const char *uri)
|
||||
{ return false; }
|
||||
|
||||
size_t Zip::Seek(Handle *h, ptrdiff_t offset, SeekRef ref)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Seek(offset, ref);
|
||||
return (size_t)-1;
|
||||
}
|
||||
size_t Zip::Tell(Handle *h)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Tell();
|
||||
return (size_t)-1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t Zip::Read(Handle *h, void *b, size_t size)
|
||||
{
|
||||
if (ZipHandle *z = (ZipHandle *)h)
|
||||
return z->h->Read(b, size);
|
||||
return 0;
|
||||
}
|
||||
size_t Zip::Write(Handle *h, const void *b, size_t size)
|
||||
{ return 0; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Zip::Zip(const char *uri, const char *password)
|
||||
{
|
||||
zfile = NULL;
|
||||
memfs = new Memory;
|
||||
SetArchive(uri, password);
|
||||
}
|
||||
Zip::~Zip()
|
||||
{ SetArchive(NULL, NULL); }
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user