diff --git a/stepmania/src/Makefile.am b/stepmania/src/Makefile.am index e9ae8c81dc..01d51d16f7 100644 --- a/stepmania/src/Makefile.am +++ b/stepmania/src/Makefile.am @@ -228,6 +228,7 @@ RageFileBasic.cpp RageFileBasic.h \ RageFile.cpp RageFile.h RageFileDriver.cpp RageFileDriver.h RageFileManager.cpp RageFileManager.h \ RageFileDriverDirect.cpp RageFileDriverDirect.h RageFileDriverDirectHelpers.cpp RageFileDriverDirectHelpers.h \ RageFileDriverMemory.cpp RageFileDriverMemory.h RageFileDriverZip.cpp RageFileDriverZip.h \ +RageFileDriverDeflate.cpp RageFileDriverDeflate.h \ RageFileDriverSlice.cpp RageFileDriverSlice.h Rage = $(Helpers) $(PCRE) $(RageFile) $(RageSoundFileReaders) \ diff --git a/stepmania/src/RageFileDriverDeflate.cpp b/stepmania/src/RageFileDriverDeflate.cpp new file mode 100644 index 0000000000..a89795642a --- /dev/null +++ b/stepmania/src/RageFileDriverDeflate.cpp @@ -0,0 +1,206 @@ +#include "global.h" +#include "RageFileDriverDeflate.h" +#include "RageLog.h" + +#if defined(_WINDOWS) || defined(_XBOX) + #include "zlib/zlib.h" + #pragma comment(lib, "zlib/zdll.lib") +#elif defined(DARWIN) + /* Since crypto++ was added to the repository, includes the zlib.h + * in there rather than the correct system one. I don't know why it would do + * this since crypto51 is not being listed as one of the include directories. + * I've never run into this problem before and looking at the command line + * used to compile RageFileDriverZip.o, I have no idea how it's happening. + * --Steve + */ + #include "/usr/include/zlib.h" +#else + #include +#endif + +RageFileObjInflate::RageFileObjInflate( RageFileBasic *pFile, int iUncompressedSize ) +{ + m_pFile = pFile; + decomp_buf_avail = 0; + m_pInflate = new z_stream; + + m_iUncompressedSize = iUncompressedSize; + + m_pInflate->zalloc = Z_NULL; + m_pInflate->zfree = Z_NULL; + + int err = inflateInit2( m_pInflate, -MAX_WBITS ); + if( err == Z_MEM_ERROR ) + RageException::Throw( "inflateInit2( %i ): out of memory", -MAX_WBITS ); + if( err != Z_OK ) + LOG->Trace( "Huh? inflateInit2() err = %i", err ); + + decomp_buf_ptr = decomp_buf; + m_iFilePos = 0; +} + +RageFileObjInflate::RageFileObjInflate( const RageFileObjInflate &cpy ): + RageFileObj( cpy ) +{ + /* XXX completely untested */ + /* Copy the entire decode state. */ + /* inflateInit2 isn't widespread yet */ + ASSERT( 0 ); +/* + m_pFile = cpy.m_pFile->Copy(); + m_pInflate = new z_stream; + inflateCopy( m_pInflate, const_cast(cpy.m_pInflate) ); + + // memcpy decomp_buf? + decomp_buf_ptr = decomp_buf + (cpy.decomp_buf_ptr - cpy.decomp_buf); + decomp_buf_avail = cpy.decomp_buf_avail; + m_iFilePos = cpy.m_iFilePos; + */ +} + +RageFileBasic *RageFileObjInflate::Copy() const +{ + RageException::Throw( "Loading ZIPs from deflated ZIPs is currently disabled; see RageFileObjInflate" ); + + // return new RageFileObjInflate( *this, p ); +} + + +RageFileObjInflate::~RageFileObjInflate() +{ + delete m_pFile; + + int err = inflateEnd( m_pInflate ); + if( err != Z_OK ) + LOG->Trace( "Huh? inflateEnd() err = %i", err ); + + delete m_pInflate; +} + +int RageFileObjInflate::ReadInternal( void *buf, size_t bytes ) +{ + bool done=false; + int ret = 0; + while( bytes && !done ) + { + if ( !decomp_buf_avail ) + { + decomp_buf_ptr = decomp_buf; + decomp_buf_avail = 0; + int got = m_pFile->Read( decomp_buf, sizeof(decomp_buf) ); + if( got == -1 ) + { + SetError( m_pFile->GetError() ); + return -1; + } + if( got == 0 ) + break; + + decomp_buf_avail = got; + } + + m_pInflate->next_in = (Bytef *) decomp_buf_ptr; + m_pInflate->avail_in = decomp_buf_avail; + m_pInflate->next_out = (Bytef *) buf; + m_pInflate->avail_out = bytes; + + + int err = inflate( m_pInflate, Z_PARTIAL_FLUSH ); + switch( err ) + { + case Z_DATA_ERROR: + SetError( "Data error" ); + return -1; + case Z_MEM_ERROR: + SetError( "out of memory" ); + return -1; + case Z_STREAM_END: + done = true; + break; + case Z_OK: + break; + default: + LOG->Trace( "Huh? inflate err %i", err ); + } + + const int used = (char *)m_pInflate->next_in - decomp_buf_ptr; + decomp_buf_ptr += used; + decomp_buf_avail -= used; + + const int got = (char *)m_pInflate->next_out - (char *)buf; + m_iFilePos += got; + ret += got; + buf = (char *)buf + got; + bytes -= got; + } + + return ret; +} + +int RageFileObjInflate::SeekInternal( int iPos ) +{ + /* Optimization: if offset is the end of the file, it's a lseek(0,SEEK_END). Don't + * decode anything. */ + if( iPos >= m_iUncompressedSize ) + { + m_iFilePos = m_iUncompressedSize; + m_pFile->Seek( m_pFile->GetFileSize() ); + decomp_buf_ptr = decomp_buf; + decomp_buf_avail = 0; + inflateReset( m_pInflate ); + return m_iUncompressedSize; + } + + if( iPos < m_iFilePos ) + { + inflateReset( m_pInflate ); + decomp_buf_ptr = decomp_buf; + decomp_buf_avail = 0; + + m_pFile->Seek( 0 ); + m_iFilePos = 0; + } + + int iOffset = iPos - m_iFilePos; + + /* Can this be optimized? */ + char buf[1024*4]; + while( iOffset ) + { + int got = ReadInternal( buf, min( (int) sizeof(buf), iOffset ) ); + if( got == -1 ) + return -1; + + if( got == 0 ) + break; + iOffset -= got; + } + + return m_iFilePos; +} + +/* + * Copyright (c) 2003-2004 Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + diff --git a/stepmania/src/RageFileDriverDeflate.h b/stepmania/src/RageFileDriverDeflate.h new file mode 100644 index 0000000000..abac388b86 --- /dev/null +++ b/stepmania/src/RageFileDriverDeflate.h @@ -0,0 +1,60 @@ +/* RageFileObjInflate - decompress streams compressed with "deflate" compression. */ + +#ifndef RAGE_FILE_DRIVER_DEFLATE_H +#define RAGE_FILE_DRIVER_DEFLATE_H + +#include "RageFileBasic.h" + +typedef struct z_stream_s z_stream; + +class RageFileObjInflate: public RageFileObj +{ +public: + /* pFile will be freed. */ + RageFileObjInflate( RageFileBasic *pFile, int iUncompressedSize ); + RageFileObjInflate( const RageFileObjInflate &cpy ); + ~RageFileObjInflate(); + int ReadInternal( void *pBuffer, size_t iBytes ); + int WriteInternal( const void *pBuffer, size_t iBytes ) { SetError( "Not implemented" ); return -1; } + int SeekInternal( int iOffset ); + int GetFileSize() const { return m_iUncompressedSize; } + RageFileBasic *Copy() const; + +private: + int m_iUncompressedSize; + RageFileBasic *m_pFile; + int m_iFilePos; + + z_stream *m_pInflate; + enum { INBUFSIZE = 1024*4 }; + char decomp_buf[INBUFSIZE], *decomp_buf_ptr; + int decomp_buf_avail; +}; + +#endif + +/* + * Copyright (c) 2003-2004 Glenn Maynard + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + diff --git a/stepmania/src/RageFileDriverZip.cpp b/stepmania/src/RageFileDriverZip.cpp index 98fa08a919..ed9201a0cd 100644 --- a/stepmania/src/RageFileDriverZip.cpp +++ b/stepmania/src/RageFileDriverZip.cpp @@ -8,28 +8,12 @@ #include "global.h" #include "RageFileDriverZip.h" #include "RageFileDriverSlice.h" +#include "RageFileDriverDeflate.h" #include "RageLog.h" #include "RageUtil.h" #include "RageUtil_FileDB.h" - #include -#if defined(_WINDOWS) || defined(_XBOX) - #include "zlib/zlib.h" - #pragma comment(lib, "zlib/zdll.lib") -#elif defined(DARWIN) - /* Since crypto++ was added to the repository, includes the zlib.h - * in there rather than the correct system one. I don't know why it would do - * this since crypto51 is not being listed as one of the include directories. - * I've never run into this problem before and looking at the command line - * used to compile RageFileDriverZip.o, I have no idea how it's happening. - * --Steve - */ - #include "/usr/include/zlib.h" -#else - #include -#endif - #define INBUFSIZE 1024*4 static struct FileDriverEntry_ZIP: public FileDriverEntry @@ -67,34 +51,6 @@ struct end_central_dir_record #define STORED 0 #define DEFLATED 8 -class RageFileObjZipDeflated: public RageFileObj -{ -private: - int m_iUncompressedSize; - RageFileBasic *m_pFile; - int m_iFilePos; - - z_stream dstrm; - char decomp_buf[INBUFSIZE], *decomp_buf_ptr; - int decomp_buf_avail; - -public: - /* pFile will be freed. */ - RageFileObjZipDeflated( RageFileBasic *pFile, int iUncompressedSize ); - RageFileObjZipDeflated( const RageFileObjZipDeflated &cpy ); - ~RageFileObjZipDeflated(); - int ReadInternal( void *pBuffer, size_t iBytes ); - int WriteInternal( const void *pBuffer, size_t iBytes ) { SetError( "Not implemented" ); return -1; } - int SeekInternal( int iOffset ); - int GetFileSize() const { return m_iUncompressedSize; } - RageFileBasic *Copy() const - { - RageException::Throw( "Loading ZIPs from deflated ZIPs is currently disabled; see RageFileObjZipDeflated" ); - - // return new RageFileObjZipDeflated( *this, p ); - } -}; - RageFileDriverZip::RageFileDriverZip( CString path ): RageFileDriver( new NullFilenameDB ) { @@ -416,7 +372,7 @@ RageFileBasic *RageFileDriverZip::Open( const CString &path, int mode, int &err case STORED: return pFile; case DEFLATED: - return new RageFileObjZipDeflated( pFile, info->uncompr_size ); + return new RageFileObjInflate( pFile, info->uncompr_size ); default: /* unknown compression method */ ASSERT( 0 ); @@ -431,155 +387,6 @@ void RageFileDriverZip::FlushDirCache( const CString &sPath ) } -RageFileObjZipDeflated::RageFileObjZipDeflated( RageFileBasic *pFile, int iUncompressedSize ) -{ - m_pFile = pFile; - decomp_buf_avail = 0; - m_iUncompressedSize = iUncompressedSize; - - dstrm.zalloc = Z_NULL; - dstrm.zfree = Z_NULL; - - int err = inflateInit2( &dstrm, -MAX_WBITS ); - if( err == Z_MEM_ERROR ) - RageException::Throw( "inflateInit2( %i ): out of memory", -MAX_WBITS ); - if( err != Z_OK ) - LOG->Trace( "Huh? inflateInit2() err = %i", err ); - - decomp_buf_ptr = decomp_buf; - m_iFilePos = 0; -} - -RageFileObjZipDeflated::RageFileObjZipDeflated( const RageFileObjZipDeflated &cpy ): - RageFileObj( cpy ) -{ - /* XXX completely untested */ - /* Copy the entire decode state. */ - /* inflateInit2 isn't widespread yet */ - ASSERT( 0 ); -/* - m_pFile = cpy.m_pFile->Copy(); - inflateCopy( &dstrm, const_cast(&cpy.dstrm) ); - - // memcpy decomp_buf? - decomp_buf_ptr = decomp_buf + (cpy.decomp_buf_ptr - cpy.decomp_buf); - decomp_buf_avail = cpy.decomp_buf_avail; - m_iFilePos = cpy.m_iFilePos; - */ -} - - -RageFileObjZipDeflated::~RageFileObjZipDeflated() -{ - delete m_pFile; - - int err = inflateEnd( &dstrm ); - if( err != Z_OK ) - LOG->Trace( "Huh? inflateEnd() err = %i", err ); -} - -int RageFileObjZipDeflated::ReadInternal( void *buf, size_t bytes ) -{ - bool done=false; - int ret = 0; - while( bytes && !done ) - { - if ( !decomp_buf_avail ) - { - decomp_buf_ptr = decomp_buf; - decomp_buf_avail = 0; - int got = m_pFile->Read( decomp_buf, sizeof(decomp_buf) ); - if( got == -1 ) - { - SetError( m_pFile->GetError() ); - return -1; - } - if( got == 0 ) - break; - - decomp_buf_avail = got; - } - - dstrm.next_in = (Bytef *) decomp_buf_ptr; - dstrm.avail_in = decomp_buf_avail; - dstrm.next_out = (Bytef *) buf; - dstrm.avail_out = bytes; - - - int err = inflate(&dstrm, Z_PARTIAL_FLUSH); - switch( err ) - { - case Z_DATA_ERROR: - SetError( "Data error" ); - return -1; - case Z_MEM_ERROR: - SetError( "out of memory" ); - return -1; - case Z_STREAM_END: - done = true; - break; - case Z_OK: - break; - default: - LOG->Trace( "Huh? inflate err %i", err ); - } - - const int used = (char *)dstrm.next_in - decomp_buf_ptr; - decomp_buf_ptr += used; - decomp_buf_avail -= used; - - const int got = (char *)dstrm.next_out - (char *)buf; - m_iFilePos += got; - ret += got; - buf = (char *)buf + got; - bytes -= got; - } - - return ret; -} - -int RageFileObjZipDeflated::SeekInternal( int iPos ) -{ - /* Optimization: if offset is the end of the file, it's a lseek(0,SEEK_END). Don't - * decode anything. */ - if( iPos >= m_iUncompressedSize ) - { - m_iFilePos = m_iUncompressedSize; - m_pFile->Seek( m_pFile->GetFileSize() ); - decomp_buf_ptr = decomp_buf; - decomp_buf_avail = 0; - inflateReset( &dstrm ); - return m_iUncompressedSize; - } - - if( iPos < m_iFilePos ) - { - inflateReset( &dstrm ); - decomp_buf_ptr = decomp_buf; - decomp_buf_avail = 0; - - m_pFile->Seek( 0 ); - m_iFilePos = 0; - } - - int iOffset = iPos - m_iFilePos; - - /* Can this be optimized? */ - char buf[1024*4]; - while( iOffset ) - { - int got = ReadInternal( buf, min( (int) sizeof(buf), iOffset ) ); - if( got == -1 ) - return -1; - - if( got == 0 ) - break; - iOffset -= got; - } - - return m_iFilePos; -} - /* * Copyright (c) 1990-2002 Info-ZIP. All rights reserved. * Copyright (c) 2003-2004 Glenn Maynard. All rights reserved.