/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Christoph Renner co-programmer: ... */ #include "zip.h" #include "loading/new_resource_manager.h" #include "debug.h" /** * the singleton reference to this class */ Zip* Zip::singletonRef = NULL; /** * standard constructor */ Zip::Zip() { } /** * @brief standard deconstructor */ Zip::~Zip() { Zip::singletonRef = NULL; } /** * load a dictionary to unzip. you can load more than one dictionary * if you call unzip with data from zip without loading the same dictionary * used with zip unzip will fail * @param name name of dictionary * @return true on success */ int Zip::loadDictionary( std::string name ) { std::string fileName = Resources::NewResourceManager::getInstance()->mainGlobalPath().name(); //PRINTF(0)("datadir: %s\n", fileName.c_str()); fileName = fileName + "/dicts/" + name; //PRINTF(0)("filename: %s\n", fileName.c_str()); FILE * f = fopen( fileName.c_str(), "r" ); if ( !f ) { PRINTF(1)("Could not open %d\n", fileName.c_str()); return -1; } byte buf[1024]; int nBytesRead = 0; while ( !feof( f ) ) { nBytesRead += fread( buf, 1, sizeof(buf), f ); } DictionaryEntry entry; entry.dictLen = nBytesRead; entry.dict = new Byte[nBytesRead]; fseek( f, 0, SEEK_SET ); assert( fread( entry.dict, 1, nBytesRead, f ) == nBytesRead ); entry.adler = adler32( adler32( 0L, Z_NULL, 0 ), entry.dict, nBytesRead ); dicts.push_back( entry ); PRINTF(3)("Loaded dictionary '%s' with adler = %d\n", name.c_str(), entry.adler ); return dicts.size()-1; } /** * zip data. you must call loadDictionary before * @param from data to compress * @param fromLength length of data to compress * @param to pointer to compressed data * @param maxLength max bytes to compress * @param dict dictionary to use. default is 0 * @return num bytes writen to to */ int Zip::zip( byte * from, int fromLength, byte * to, int maxLength, int dict ) { if ( dicts.size() < dict+1 ) { PRINTF(1)("you cannot use dict nr %d. num dicts: %d\n", dict, dicts.size() ); return -1; } int res; z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; res = deflateInit( &strm, 9 ); if ( res != Z_OK ) { PRINTF(1)("deflateInit error: %s\n", strm.msg); return -1; } res = deflateSetDictionary( &strm, (Bytef*)(dicts[dict].dict), dicts[dict].dictLen ); if ( res != Z_OK ) { PRINTF(1)("deflateSetDictionary error: %s\n", strm.msg); return -1; } strm.next_out = (Bytef*)to; strm.avail_out = maxLength; assert( strm.total_out == 0 ); strm.next_in = (Bytef*)from; strm.avail_in = fromLength; assert( strm.total_in == 0 ); res = deflate( &strm, Z_FINISH ); if ( res != Z_STREAM_END ) { PRINTF(1)("buffer to small or deflate error: %s\n", strm.msg); return -1; } assert( strm.avail_out != 0 ); assert( strm.avail_in == 0 ); int zippedlen = strm.total_out; res = deflateEnd( &strm ); if ( res != Z_OK ) { if ( res == Z_STREAM_ERROR ) PRINTF(1)("deflateEnd error: Z_STREAM_ERROR\n"); else if ( res == Z_DATA_ERROR ) PRINTF(1)("deflateEnd error: Z_DATA_ERROR %s\n", strm.msg); else PRINTF(1)("deflateEnd error: dont know\n"); return -1; } return zippedlen; } /** * uncompress data. same dict as used in zip must be loaded * @param from compressed data * @param fromLength length of compressed data * @param to buffer to copy uncompressed data to * @param maxLength max bytes to copy to to * @return num bytes writen to to */ int Zip::unZip( byte * from, int fromLength, byte * to, int maxLength ) { z_stream strm; int res = 0; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; res = inflateInit( &strm ); if ( res != Z_OK ) { PRINTF(1)("inflateInit error: %s\n", strm.msg); return -1; } strm.next_out = (Bytef*)to; strm.avail_out = maxLength; assert( strm.total_out == 0 ); strm.next_in = (Bytef*)from; strm.avail_in = fromLength; assert( strm.total_in == 0 ); assert( inflate( &strm, Z_NO_FLUSH ) == Z_NEED_DICT ); int dictId = -1; for ( int i = 0; i < dicts.size(); i++ ) { if ( dicts[i].adler == strm.adler ) { dictId = i; break; } } if ( dictId == -1 ) { PRINTF(1)("Could not find dict used to compress this packet! ( adler = %d )\n", strm.adler); return -1; } res = inflateSetDictionary( &strm, (Bytef*)dicts[dictId].dict, dicts[dictId].dictLen ); if ( res != Z_OK ) { PRINTF(1)("inflateSetDictionary error: %s\n", strm.msg); return -1; } res = inflate( &strm, Z_FINISH ); if ( res != Z_STREAM_END ) { PRINTF(1)("inflate error: %s\n", strm.msg); return -1; } assert( strm.avail_out != 0 ); assert( strm.avail_in == 0 ); int unzippedlen = strm.total_out; res = inflateEnd( &strm ); if ( res != Z_OK ) { PRINTF(1)("inflateEnd error: %s\n", strm.msg); return -1; } return unzippedlen; }