- 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:
427
JGE/src/zipFS/zstream.cpp
Normal file
427
JGE/src/zipFS/zstream.cpp
Normal 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
|
||||
Reference in New Issue
Block a user