# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlCore/GZipCodec.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlCore/VisualizationLibrary.hpp>
    00033 #include <vlCore/GZipCodec.hpp>
    00034 #include <vlCore/Log.hpp>
    00035 #include <vlCore/Say.hpp>
    00036 #include <zlib.h>
    00037
    00038 using namespace vl;
    00039
    00040 //-----------------------------------------------------------------------------
    00041 // GZipCodec
    00042 //-----------------------------------------------------------------------------
    00043 GZipCodec::GZipCodec(VirtualFile* stream): mStream(stream)
    00044 {
    00045   mCompressionLevel = 6;
    00046   mReadBytes = -1;
    00047   mWrittenBytes = -1;
    00048   mZStream = new z_stream_s;
    00049   memset(mZStream, 0, sizeof(z_stream_s));
    00050   mUncompressedSize = -1;
    00051   mWarnOnSeek = true;
    00052 }
    00053 //-----------------------------------------------------------------------------
    00054 GZipCodec::GZipCodec(const String& gz_path): mStream(NULL)
    00055 {
    00056   mCompressionLevel = 6;
    00057   mReadBytes = -1;
    00058   mWrittenBytes = -1;
    00059   mZStream = new z_stream_s;
    00060   memset(mZStream, 0, sizeof(z_stream_s));
    00061   mUncompressedSize = -1;
    00062   setPath(gz_path);
    00063   mWarnOnSeek = true;
    00064 }
    00065 //-----------------------------------------------------------------------------
    00066 GZipCodec::~GZipCodec()
    00067 {
    00068   close();
    00069   delete mZStream; mZStream = NULL;
    00070   mUncompressedSize = -1;
    00071   mWrittenBytes = -1;
    00072 }
    00073 //-----------------------------------------------------------------------------
    00074 bool GZipCodec::open(EOpenMode mode)
    00075 {
    00076   if (isOpen())
    00077   {
    00078     Log::error("GZipCodec::open(): file already open.\n");
    00079     return false;
    00080   }
    00081   switch(mode)
    00082   {
    00083     case OM_ReadOnly:  mMode = ZDecompress; break;
    00084     case OM_WriteOnly: mMode = ZCompress;   break;
    00085     default: mMode = ZNone;
    00086   }
    00087   mReadBytes = 0;
    00088   mWrittenBytes = 0;
    00089   mUncompressedBufferPtr = 0;
    00090   mUncompressedBuffer.clear();
    00091   /* z_stream_s */
    00092   memset(mZStream, 0, sizeof(z_stream_s));
    00093   mZStream->zalloc   = Z_NULL;
    00094   mZStream->zfree    = Z_NULL;
    00095   mZStream->opaque   = Z_NULL;
    00096   mZStream->avail_in = 0;
    00097   mZStream->next_in  = Z_NULL;
    00098   if (mMode == ZDecompress)
    00099   {
    00100     if ( inflateInit2(mZStream, 15+32/*autodected gzip header*/) != Z_OK )
    00101     {
    00102       Log::error("GZipCodec::open(): inflateInit2 failed.\n");
    00103       return false;
    00104     }
    00105   }
    00106   else
    00107   if (mMode == ZCompress)
    00108   {
    00109     if (deflateInit2(mZStream, compressionLevel(), Z_DEFLATED, 15+16/*gz compression*/, 8/*mem level*/, Z_DEFAULT_STRATEGY) != Z_OK)
    00110     {
    00111       Log::error("GZipCodec::open(): deflateInit2 failed.\n");
    00112       return false;
    00113     }
    00114   }
    00115   if (!stream() && !path().empty())
    00116   {
    00117     ref<VirtualFile> file = vl::locateFile(path());
    00118     setStream(file.get());
    00119   }
    00120   if (!stream())
    00121   {
    00122     Log::error("GZipCodec::open(): no input or output stream defined. See the setStream() method documentation.\n");
    00123     return false;
    00124   }
    00125   if (!stream()->open(mode))
    00126   {
    00127     Log::error("GZipCodec::open(): input or output stream open failed.\n");
    00128     return false;
    00129   }
    00130   mStreamSize = stream()->size();
    00131   return true;
    00132 }
    00133 //-----------------------------------------------------------------------------
    00134 void GZipCodec::close()
    00135 {
    00136   if ( mMode == ZDecompress )
    00137     inflateEnd(mZStream);
    00138   else
    00139   if ( mMode == ZCompress )
    00140   {
    00141     // flush data
    00142     unsigned char next_out[CHUNK_SIZE];
    00143     unsigned char dummy_buffer=0;
    00144     mZStream->avail_in = 0;
    00145     mZStream->next_in  = (Bytef*)&dummy_buffer;
    00146     do
    00147     {
    00148       mZStream->avail_out = CHUNK_SIZE;
    00149       mZStream->next_out  = next_out;
    00150       int ret = deflate(mZStream, Z_FINISH);
    00151       if (ret == Z_STREAM_ERROR)
    00152       {
    00153         Log::error("GZStream::write(): Z_STREAM_ERROR.\n");
    00154         deflateEnd(mZStream);
    00155         memset(mZStream, 0, sizeof(z_stream_s));
    00156         break;
    00157       }
    00158       unsigned have = CHUNK_SIZE - mZStream->avail_out;
    00159       if (have>0)
    00160       {
    00161         long long written = stream()->write(next_out, have);
    00162         if (written < have)
    00163           Log::error("GZStream: write failed.\n");
    00164       }
    00165     } while (mZStream->avail_out == 0);
    00166     deflateEnd(mZStream);
    00167   }
    00168   if (stream())
    00169     stream()->close();
    00170   memset(mZStream, 0, sizeof(z_stream_s));
    00171   mMode = ZNone;
    00172   mReadBytes = -1;
    00173   mWrittenBytes = -1;
    00174   mUncompressedBufferPtr = 0;
    00175   mUncompressedBuffer.clear();
    00176 }
    00177 //-----------------------------------------------------------------------------
    00178 ref<VirtualFile> GZipCodec::clone() const
    00179 {
    00180   ref<GZipCodec> file = new GZipCodec;
    00181   file->operator=(*this);
    00182   return file;
    00183 }
    00184 //-----------------------------------------------------------------------------
    00185 GZipCodec& GZipCodec::operator=(const GZipCodec& other)
    00186 {
    00187   close();
    00188   VirtualFile::operator=(other);
    00189   mCompressionLevel = other.mCompressionLevel;
    00190   if (other.mStream)
    00191     mStream = other.mStream->clone();
    00192   return *this;
    00193 }
    00194 //-----------------------------------------------------------------------------
    00195 long long GZipCodec::read_Implementation(void* buffer, long long bytes_to_read)
    00196 {
    00197   if ( bytes_to_read < 1 )
    00198     return 0;
    00199   if (!isOpen())
    00200   {
    00201     Log::error("GZStream::read(): read requested on closed stream.\n");
    00202     return 0;
    00203   }
    00204   /*if ( mReadBytes >= ??? )
    00205     return 0;*/
    00206   long long read_bytes = 0;
    00207   if ( mUncompressedBuffer.empty() )
    00208     fillUncompressedBuffer();
    00209   if ( mUncompressedBuffer.empty() )
    00210     return 0;
    00211   do
    00212   {
    00213     long long bytes = bytes_to_read < (int)mUncompressedBuffer.size()-mUncompressedBufferPtr ? bytes_to_read : (int)mUncompressedBuffer.size()-mUncompressedBufferPtr;
    00214     // copy uncompressed data
    00215     VL_CHECK( mUncompressedBufferPtr < (int)mUncompressedBuffer.size() )
    00216     if (bytes)
    00217       memcpy((char*)buffer+read_bytes, &mUncompressedBuffer[0]+mUncompressedBufferPtr, (size_t)bytes);
    00218     mReadBytes += bytes;
    00219     read_bytes += bytes;
    00220     mUncompressedBufferPtr += (int)bytes;
    00221     bytes_to_read -= bytes;
    00222     // remove read data from the buffer
    00223     // mUncompressedBuffer.erase( mUncompressedBuffer.begin(), mUncompressedBuffer.begin() + (size_t)bytes );
    00224     if(mUncompressedBufferPtr == (int)mUncompressedBuffer.size())
    00225     {
    00226       mUncompressedBuffer.clear();
    00227       mUncompressedBufferPtr = 0;
    00228     }
    00229   } while( bytes_to_read && fillUncompressedBuffer() && !mUncompressedBuffer.empty() );
    00230   return read_bytes;
    00231 }
    00232 //-----------------------------------------------------------------------------
    00233 long long GZipCodec::write_Implementation(const void* buffer, long long byte_count)
    00234 {
    00235   unsigned char next_out[CHUNK_SIZE];
    00236   mZStream->avail_in = (uInt)byte_count;
    00237   mZStream->next_in  = (Bytef*)buffer;
    00238   do
    00239   {
    00240     mZStream->avail_out = CHUNK_SIZE;
    00241     mZStream->next_out  = next_out;
    00242     int ret = deflate(mZStream, Z_NO_FLUSH);
    00243     if (ret == Z_STREAM_ERROR)
    00244     {
    00245       Log::error("GZStream::write(): Z_STREAM_ERROR.\n");
    00246       return 0;
    00247     }
    00248     unsigned have = CHUNK_SIZE - mZStream->avail_out;
    00249     if (have>0)
    00250     {
    00251       long long written = stream()->write(next_out, have);
    00252       if (written < have)
    00253         Log::error("GZStream: write failed.\n");
    00254     }
    00255   } while (mZStream->avail_out == 0);
    00256   mWrittenBytes += byte_count;
    00257   return byte_count;
    00258 }
    00259 //-----------------------------------------------------------------------------
    00260 long long GZipCodec::position_Implementation() const
    00261 {
    00262   return mReadBytes;
    00263 }
    00264 //-----------------------------------------------------------------------------
    00265 void GZipCodec::resetStream()
    00266 {
    00267   close();
    00268   open(OM_ReadOnly);
    00269 }
    00270 //-----------------------------------------------------------------------------
    00271 bool GZipCodec::seekSet_Implementation(long long pos)
    00272 {
    00273   if (mMode == ZDecompress)
    00274   {
    00275     if (warnOnSeek())
    00276       Log::print( Say("Performance warning: GZipCodec::seek() requested for file %s. For maximum performances avoid seeking a GZipCodec, especially avoid seeking backwards.\n") << path() );
    00277
    00278     if (pos<position())
    00279       resetStream();
    00280
    00281     unsigned char buffer[CHUNK_SIZE];
    00282     long long remained = pos - position();
    00283     long long eat_bytes = remained < CHUNK_SIZE ? remained : CHUNK_SIZE;
    00284     while ( (remained -= read(buffer, eat_bytes)) )
    00285       eat_bytes = remained < CHUNK_SIZE ? remained : CHUNK_SIZE;
    00286     return position() == pos;
    00287   }
    00288   else
    00289   {
    00290     Log::error("GZStream: seek supported only by OM_ReadOnly open mode.\n");
    00291     return false;
    00292   }
    00293 }
    00294 //-----------------------------------------------------------------------------
    00295 bool GZipCodec::fillUncompressedBuffer()
    00296 {
    00297   VL_CHECK(mUncompressedBufferPtr == (int)mUncompressedBuffer.size())
    00298   VL_CHECK( mUncompressedBuffer.empty() )
    00299   mUncompressedBufferPtr = 0;
    00300   VL_CHECK(isOpen())
    00301   /*if (!isOpen())
    00302     return false;*/
    00303   /*if ( mReadBytes >= ??? )
    00304     return false;*/
    00305   int have = 0;
    00306   int ret  = 0;
    00307   /*long long compressed_read_bytes = stream()->position();*/
    00308   long long bytes_to_read = CHUNK_SIZE < (mStreamSize - stream()->position())?
    00309                             CHUNK_SIZE : (mStreamSize - stream()->position());
    00310   mZStream->avail_in = (uInt)stream()->read(mZipBufferIn, bytes_to_read);
    00311   if (mZStream->avail_in == 0)
    00312     return true;
    00313   mZStream->next_in = mZipBufferIn;
    00314   do
    00315   {
    00316     mZStream->avail_out = CHUNK_SIZE;
    00317     mZStream->next_out  = mZipBufferOut;
    00318     ret = inflate(mZStream, Z_NO_FLUSH);
    00319     switch (ret)
    00320     {
    00321     case Z_STREAM_ERROR:
    00322     case Z_NEED_DICT:
    00323     case Z_DATA_ERROR:
    00324     case Z_MEM_ERROR:
    00325         close();
    00326         Log::error("GZStream: error reading gzip stream.\n");
    00327         return false;
    00328     }
    00329     have = CHUNK_SIZE - mZStream->avail_out;
    00330     if (!have)
    00331       break;
    00332     int start = (int)mUncompressedBuffer.size();
    00333     mUncompressedBuffer.resize(start + have);
    00334     memcpy(&mUncompressedBuffer[0] + start, mZipBufferOut, have);
    00335   }
    00336   while ( mZStream->avail_out == 0 );
    00337   return true;
    00338 }
    00339 //-----------------------------------------------------------------------------
    00340 long long GZipCodec::uncompressedSize()
    00341 {
    00342   if (mMode == ZDecompress || mMode == ZNone)
    00343   {
    00344     if (stream() && mUncompressedSize == -1)
    00345     {
    00346       if (stream()->isOpen())
    00347       {
    00348         long long pos = stream()->position();
    00349         stream()->seekEnd(-4);
    00350         mUncompressedSize = stream()->readUInt32();
    00351         stream()->seekSet(pos);
    00352       }
    00353       else
    00354       {
    00355         stream()->open(OM_ReadOnly);
    00356         stream()->seekEnd(-4);
    00357         mUncompressedSize = stream()->readUInt32();
    00358         stream()->close();
    00359       }
    00360     }
    00361     return mUncompressedSize;
    00362   }
    00363   else
    00364     return -1;
    00365 }
    00366 //-----------------------------------------------------------------------------
    00367 long long GZipCodec::size() const
    00368 {
    00369   if (mMode == ZCompress)
    00370     return mWrittenBytes;
    00371   else
    00372     return const_cast<GZipCodec*>(this)->uncompressedSize();
    00373 }
    00374 //-----------------------------------------------------------------------------
    00375 void GZipCodec::setStream(VirtualFile* str)
    00376 {
    00377   if (stream() && stream()->isOpen())
    00378     stream()->close();
    00379   mStream = str;
    00380   mUncompressedSize = -1;
    00381   mWrittenBytes = -1;
    00382   setPath( str ? str->path() : String() );
    00383 }
    00384 //-----------------------------------------------------------------------------
    00385 float GZipCodec::compressionRatio() const
    00386 {
    00387   double comp = (double)compressedSize();
    00388   double unco = (double)size();
    00389   return float(comp/unco);
    00390 }
    00391 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:20.
Permission is granted to use this page to write and publish articles regarding Visualization Library.