Started to merge @ZobyTwo cmake branch
This commit is contained in:
453
thirdparty/zipFS/zstream.cpp
vendored
Normal file
453
thirdparty/zipFS/zstream.cpp
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
// zstream.cpp: implementation of the zstream class.
|
||||
//
|
||||
// Copyright (C) 2002 Tanguy Fautre
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
bool zbuffer::use(std::streamoff Offset, std::streamoff Size)
|
||||
{
|
||||
if (! m_ZipFile)
|
||||
return false;
|
||||
|
||||
//Don't use a buffer already used;
|
||||
if (m_Used)
|
||||
return false;
|
||||
|
||||
// adjust file position
|
||||
if (! m_ZipFile.seekg(Offset, ios::beg))
|
||||
return false;
|
||||
|
||||
setg( m_Buffer, // beginning of putback area
|
||||
m_Buffer, // read position
|
||||
m_Buffer); // end of buffer
|
||||
|
||||
m_Buffer[0] = 0;
|
||||
|
||||
m_Pos = -1;
|
||||
m_Size = Size;
|
||||
m_Used = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// 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 (! use(Offset, Size))
|
||||
return NULL;
|
||||
|
||||
m_Opened = true;
|
||||
m_Filename = Filename;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
zbuffer_stored * zbuffer_stored::close()
|
||||
{
|
||||
if (! m_Opened)
|
||||
return NULL;
|
||||
else {
|
||||
m_Opened = false;
|
||||
m_Used = false;
|
||||
m_ZipFile.close();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int zbuffer_stored::overflow(int)
|
||||
{
|
||||
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.
|
||||
// Set the real position of the beginning of the buffer.
|
||||
if (m_Pos == streamoff(-1))
|
||||
m_Pos = 0;
|
||||
|
||||
streamoff ToRead = ((m_Size - m_Pos) < BUFFERSIZE) ? (m_Size - m_Pos) : BUFFERSIZE;
|
||||
if ((ToRead == 0) || (! m_ZipFile.read(m_Buffer, ToRead)))
|
||||
return EOF;
|
||||
|
||||
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, ToRead))
|
||||
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 *, int)
|
||||
{
|
||||
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 (! use(Offset, Size))
|
||||
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_Filename = Filename;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
zbuffer_deflated * zbuffer_deflated::close()
|
||||
{
|
||||
if (! m_Opened)
|
||||
return NULL;
|
||||
else {
|
||||
m_Opened = false;
|
||||
m_Used = false;
|
||||
m_ZipFile.close();
|
||||
|
||||
// z_stream unitialization.
|
||||
if (inflateEnd(&m_ZStream) != Z_OK)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int zbuffer_deflated::overflow(int)
|
||||
{
|
||||
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 *, int)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace zip_file_system
|
||||
Reference in New Issue
Block a user