- Support for Zip Filesystem. It is now possible to zip the entire Res folder ("store" method preferred, zip so that the root of the zip has ai, player, etc...) in one single file for read only. Write access is done in another folder (hardcoded to be User/ for now, can be updated depending on platforms, etc...

-- zipFS has several limitations...
--- in a general way, seekg doesn't work... so getting a file's size needs to be done through JFileSystem.
--- getLine on files open with zipFS doesn't work so great. Not sure if it is a normal issue because files are open in binary or not... JFileSystem therefore offers a "readIntoString" function that needs to be used instead of the usual "getline" technique. However getLine can then be used on a stream connected to the string.

-- tested on Windows and PSP, I also made sure android still works, but haven't tested zip support on Android.
-- I tried to maintain backwards compatibility, but this might break on some platforms, if I broke some platforms and you can't find a way to fix them, please contact me and we'll figure something out
-- This removes wagic::ifstream. I didn't reimplement the securities that were involved in this, apologies for that. Might be useful to reimplement such securities in JFileSystem
-- I haven't tested options/profiles in a deep way, it is possible I broke that.
This commit is contained in:
wagic.the.homebrew
2011-08-21 09:04:59 +00:00
parent 14bd7b7a24
commit e27cf56fa2
73 changed files with 3539 additions and 936 deletions

427
JGE/src/zipFS/zstream.cpp Normal file
View File

@@ -0,0 +1,427 @@
// zstream.cpp: implementation of the zstream class.
//
// Copyright (C) 2002 Tanguy Fautré.
// For conditions of distribution and use,
// see copyright notice in zfsystem.h
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "zstream.h"
namespace zip_file_system {
using namespace std;
//////////////////////////////////////////////////////////////////////
// zstream Member Functions
//////////////////////////////////////////////////////////////////////
void izstream::open(const char * Filename, streamoff Offset, streamoff Size, int CompMethod)
{
// Change the buffer if need
if (m_CompMethod == CompMethod) {
if (rdbuf() != NULL)
static_cast<zbuffer *>(rdbuf())->close();
} else
SetCompMethod(CompMethod);
// clear up the file status
clear(ios::goodbit);
// open the buffer
switch (m_CompMethod) {
case STORED:
case DEFLATED:
if (! (static_cast<zbuffer *>(rdbuf())->open(Filename, Offset, Size))) {
setstate(ios::badbit);
SetCompMethod(-1);
}
break;
default:
setstate(ios::badbit);
}
}
zbuffer * izstream::GetRightBuffer(int CompMethod) const
{
switch (CompMethod) {
// stored
case STORED:
return new zbuffer_stored;
// deflated
case DEFLATED:
return new zbuffer_deflated;
// else not supported
default:
return NULL;
}
}
//////////////////////////////////////////////////////////////////////
// zbuffer_stored Member Functions
//////////////////////////////////////////////////////////////////////
zbuffer_stored * zbuffer_stored::open(const char * Filename, streamoff Offset, streamoff Size)
{
// open main compressed file
m_ZipFile.open(Filename, ios::binary);
if (! m_ZipFile)
return NULL;
// adjust file position
if (! m_ZipFile.seekg(Offset, ios::beg))
return NULL;
m_Opened = true;
m_Pos = -1;
m_Size = Size;
return this;
}
zbuffer_stored * zbuffer_stored::close()
{
if (! m_Opened)
return NULL;
else {
m_Opened = false;
m_ZipFile.close();
}
return this;
}
int zbuffer_stored::overflow(int c)
{
return EOF;
}
int zbuffer_stored::underflow()
{
// Buffer Valid?
if (! m_Opened)
return EOF;
// Do we really need to refill it?
if (gptr() < egptr())
return static_cast<unsigned char>(* gptr());
// Refill de buffer.
streamoff ToRead = ((m_Size - m_Pos) < BUFFERSIZE) ? (m_Size - m_Pos) : BUFFERSIZE;
if ((ToRead == 0) || (! m_ZipFile.read(m_Buffer, BUFFERSIZE)))
return EOF;
// Set the real position of the beginning of the buffer.
if (m_Pos == streamoff(-1))
m_Pos = 0;
else
m_Pos += ToRead;
// Reset buffer pointers.
setg( m_Buffer, // beginning of putback area
m_Buffer, // read position
m_Buffer + ToRead); // end of buffer
return static_cast<unsigned char>(m_Buffer[0]);
}
streampos zbuffer_stored::seekoff(streamoff off, ios::seekdir dir, ios::openmode nMode)
{
streamoff WantedPos = 0;
// Find out the wanted position.
switch (dir) {
case ios_base::cur:
WantedPos = m_Pos + streamoff(gptr() - eback()) + off;
break;
case ios_base::beg:
WantedPos = off;
break;
case ios_base::end:
WantedPos = m_Size + off;
break;
default:
assert(false);
}
// Is the position valid?
if ((WantedPos < 0) || (WantedPos > m_Size))
return streambuf::seekoff(off, dir, nMode); // return invalid streamoff
// Is the position already within the buffer?
if ((WantedPos >= m_Pos) && (WantedPos - m_Pos < egptr() - eback())) {
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
// Fill up the buffer at the right position.
if (! m_ZipFile.seekg(WantedPos, ios::beg))
return streambuf::seekoff(off, dir, nMode);
m_Pos = WantedPos;
streamoff ToRead = ((m_Size - m_Pos) < BUFFERSIZE) ? (m_Size - m_Pos) : BUFFERSIZE;
if (ToRead == 0)
return WantedPos;
if (! m_ZipFile.read(m_Buffer, BUFFERSIZE))
return streambuf::seekoff(off, dir, nMode);
// Set the buffer at the right position
setg(m_Buffer, m_Buffer, m_Buffer + ToRead);
return WantedPos;
}
int zbuffer_stored::sync()
{
return 0;
}
streambuf * zbuffer_stored::setbuf(char * pr, int nLength)
{
return NULL;
}
//////////////////////////////////////////////////////////////////////
// zbuffer_deflated Member Functions
//////////////////////////////////////////////////////////////////////
zbuffer_deflated * zbuffer_deflated::open(const char * Filename, streamoff Offset, streamoff Size)
{
// open main compressed file
m_ZipFile.open(Filename, ios::binary);
if (! m_ZipFile)
return NULL;
// adjust file position
if (! m_ZipFile.seekg(Offset, ios::beg))
return NULL;
// z_stream (NULL) Initialization
m_ZStream.next_in = Z_NULL;
m_ZStream.avail_in = 0;
m_ZStream.total_in = 0;
m_ZStream.next_out = Z_NULL;
m_ZStream.avail_out = 0;
m_ZStream.total_out = 0;
m_ZStream.zalloc = Z_NULL;
m_ZStream.zfree = Z_NULL;
m_ZStream.opaque = Z_NULL;
// inflate routine Initialization: Window Size = -MAX_WBITS tells there are no header
if (inflateInit2(&m_ZStream, -MAX_WBITS) != Z_OK)
return NULL;
m_Opened = true;
m_StreamEnd = false;
m_Pos = 0;
m_CompPos = 0;
m_Size = Size;
return this;
}
zbuffer_deflated * zbuffer_deflated::close()
{
if (! m_Opened)
return NULL;
else {
m_Opened = false;
m_ZipFile.close();
// z_stream unitialization.
if (inflateEnd(&m_ZStream) != Z_OK)
return NULL;
}
return this;
}
int zbuffer_deflated::overflow(int c)
{
return EOF;
}
int zbuffer_deflated::underflow()
{
// Buffer Valid?
if (! m_Opened)
return EOF;
// Do we really need to refill it?
if (gptr() < egptr())
return static_cast<unsigned char>(* gptr());
// Can we refill?
if (m_StreamEnd)
return EOF;
streamoff ToRead;
streamoff OldPos;
bool BufferRefill = false;
// Check input (compressed) buffer status
if ((m_ZStream.avail_in == 0) && (m_CompPos < m_Size )) {
ToRead = ((m_Size - m_CompPos) > BUFFERSIZE) ? BUFFERSIZE : (m_Size - m_CompPos);
m_CompPos += ToRead;
if (! m_ZipFile.read(m_CompBuffer, ToRead))
return EOF;
m_ZStream.next_in = reinterpret_cast<unsigned char *>(m_CompBuffer);
m_ZStream.avail_in = ToRead;
}
// Ajust start read position in output buffer at the "old" end of buffer
ToRead = m_ZStream.total_out % BUFFERSIZE;
OldPos = m_ZStream.total_out;
// Check output (decompressed) buffer status
if (m_ZStream.avail_out == 0) {
BufferRefill = true;
m_ZStream.next_out = reinterpret_cast<unsigned char *>(m_Buffer);
m_ZStream.avail_out = BUFFERSIZE;
}
// Decompress (Inflate)
int Result = inflate(&m_ZStream, Z_SYNC_FLUSH);
// Check decompression result
if (Result == Z_STREAM_END)
m_StreamEnd = true;
else if (Result != Z_OK)
return EOF;
// Set the real position of the beginning of the buffer.
if (m_Pos == streamoff(-1))
m_Pos = 0;
else
if (BufferRefill)
m_Pos += m_ZStream.total_out - OldPos;
// Reset buffer pointers.
setg( m_Buffer, // beginning of putback area
m_Buffer + ToRead, // read position
m_Buffer + ((m_ZStream.total_out - 1) % (BUFFERSIZE)) + 1); // end of buffer
return static_cast<unsigned char>(m_Buffer[ToRead]);
}
streampos zbuffer_deflated::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode nMode)
{
streamoff WantedPos = 0;
// Find out the wanted position.
switch (dir) {
case ios_base::cur:
WantedPos = m_Pos + streamoff(gptr() - eback()) + off;
break;
case ios_base::beg:
WantedPos = off;
break;
case ios_base::end:
WantedPos = m_Size + off;
break;
default:
assert(false);
}
// Is the position valid?
if ((WantedPos < 0) || (WantedPos > m_Size))
return streambuf::seekoff(off, dir, nMode); // return invalid streamoff
// Is the position already within the buffer?
if ((WantedPos >= m_Pos) && (WantedPos - m_Pos < egptr() - eback())) {
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
// Found out whether we have to decompress further or if we have to reset the decompression.
if (WantedPos < m_Pos) {
// Reset the decompression.
if (inflateReset(&m_ZStream) != Z_OK)
return streambuf::seekoff(off, dir, nMode);
// z_stream Reset
m_ZStream.next_in = Z_NULL;
m_ZStream.avail_in = 0;
m_ZStream.total_in = 0;
m_ZStream.next_out = Z_NULL;
m_ZStream.avail_out = 0;
m_ZStream.total_out = 0;
}
// call underflow() untill the right position is within the buffer.
while (WantedPos - m_Pos >= egptr() - eback()) {
setg(eback(), egptr(), egptr());
if (underflow() == EOF)
return streambuf::seekoff(off, dir, nMode);
}
// now the position is within the buffer.
setg(eback(), eback() + (WantedPos - m_Pos), egptr());
return WantedPos;
}
int zbuffer_deflated::sync()
{
return 0;
}
streambuf * zbuffer_deflated::setbuf(char * pr, int nLength)
{
return NULL;
}
} // namespace zip_file_system