Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGZStream.inl

Go to the documentation of this file.
00001 //*****************************************************************************
00002 //  template class basic_zip_streambuf
00003 //*****************************************************************************
00004 
00005 //-----------------------------------------------------------------------------
00006 // PUBLIC
00007 //-----------------------------------------------------------------------------
00008 
00013 template <class charT, class traits>
00014 basic_zip_streambuf<charT, traits>::basic_zip_streambuf(ostream_reference ostream,
00015                                                         int level,
00016                                                         EStrategy strategy,
00017                                                         int window_size,
00018                                                         int memory_level,
00019                                                         size_t buffer_size)
00020     : _ostream(ostream),
00021       _output_buffer(buffer_size, 0),
00022       _buffer(buffer_size, 0),
00023       _crc(0)
00024 {
00025     _zip_stream.zalloc = (alloc_func) 0;
00026     _zip_stream.zfree = (free_func) 0;
00027 
00028     _zip_stream.next_in = NULL;
00029     _zip_stream.avail_in = 0;
00030     _zip_stream.avail_out = 0;
00031     _zip_stream.next_out = NULL;
00032 
00033     if(level > 9)
00034         level = 9;
00035         
00036     if(memory_level > 9)
00037         memory_level = 9;
00038         
00039     _err=deflateInit2(&_zip_stream, level, Z_DEFLATED,
00040                       window_size, memory_level,
00041                       static_cast<int>(strategy));
00042 
00043     setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]));
00044 }
00045 
00048 template <class charT, class traits>
00049 basic_zip_streambuf<charT, traits>::~basic_zip_streambuf(void)
00050 {
00051     flush();
00052     _ostream.flush();
00053     _err=deflateEnd(&_zip_stream);
00054 }
00055 
00060 template <class charT, class traits>
00061 int basic_zip_streambuf<charT, traits>::sync(void)
00062 { 
00063     if(this->pptr() && this->pptr() > this->pbase()) 
00064     {
00065         /*int c =*/ overflow(EOF);
00066 
00067         // ACHTUNG wenn das drin ist hoert er nach dem ersten endl auf!
00068         /*
00069           if ( c == EOF)
00070           return -1;
00071         */
00072     }
00073 
00074     return 0;
00075 }
00076 
00081 template <class charT, class traits>
00082 typename basic_zip_streambuf<charT, traits>::int_type
00083 basic_zip_streambuf<charT, traits>::overflow(int_type c)
00084 { 
00085     int w = static_cast<int>(this->pptr() - this->pbase());
00086     if (c != EOF)
00087     {
00088         *this->pptr() = c;
00089         ++w;
00090     }
00091     if (zip_to_stream(this->pbase(), w))
00092     {
00093         setp(this->pbase(), this->epptr() - 1);
00094         return c;
00095     }
00096     else
00097     {
00098         return EOF;
00099     }
00100 }
00101 
00107 template <class charT, class traits>
00108 std::streamsize basic_zip_streambuf<charT, traits>::flush(void)
00109 {
00110     std::streamsize written_byte_size = 0, total_written_byte_size = 0;
00111 
00112     size_t remainder = 0;
00113 
00114     // updating crc
00115     _crc = crc32(_crc,  _zip_stream.next_in,
00116                  _zip_stream.avail_in);        
00117 
00118     do
00119     {
00120         _err = deflate(&_zip_stream, Z_FINISH);
00121         if(_err == Z_OK || _err == Z_STREAM_END)
00122         {
00123             written_byte_size = static_cast<std::streamsize>(_output_buffer.size()) - _zip_stream.avail_out;
00124             total_written_byte_size += written_byte_size;
00125             // ouput buffer is full, dumping to ostream
00126             _ostream.write( (const char_type*) &(_output_buffer[0]), 
00127                             static_cast<std::streamsize>(written_byte_size/sizeof(char_type)*sizeof(char)));
00128             
00129             // checking if some bytes were not written.
00130             if((remainder = written_byte_size%sizeof(char_type)) != 0)
00131             {
00132                 // copy to the beginning of the stream
00133                 memcpy(&(_output_buffer[0]), 
00134                        &(_output_buffer[written_byte_size-remainder]), remainder);
00135                     
00136             }
00137                 
00138             _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size() - remainder);
00139             _zip_stream.next_out = &_output_buffer[remainder];
00140         }
00141     }
00142     while(_err == Z_OK);
00143 
00144     _ostream.flush();
00145 
00146     return total_written_byte_size;
00147 }
00148 
00151 template <class charT, class traits> inline 
00152 typename basic_zip_streambuf<charT, traits>::ostream_reference
00153 basic_zip_streambuf<charT, traits>::get_ostream(void) const
00154 {
00155     return _ostream;
00156 }
00157 
00160 template <class charT, class traits> inline
00161 int basic_zip_streambuf<charT, traits>::get_zerr(void) const
00162 {
00163     return _err;
00164 }
00165 
00168 template <class charT, class traits> inline
00169 unsigned long
00170 basic_zip_streambuf<charT, traits>:: get_crc(void) const
00171 {
00172     return _crc;
00173 }
00174 
00177 template <class charT, class traits> inline
00178 unsigned long
00179 basic_zip_streambuf<charT, traits>::get_in_size(void) const
00180 {
00181     return _zip_stream.total_in;
00182 }
00183 
00186 template <class charT, class traits> inline
00187 long 
00188 basic_zip_streambuf<charT, traits>::get_out_size(void) const
00189 {
00190     return _zip_stream.total_out;
00191 }
00192 
00193 //-----------------------------------------------------------------------------
00194 // PRIVATE
00195 //-----------------------------------------------------------------------------
00196 
00201 template <class charT, class traits>
00202 bool basic_zip_streambuf<charT, traits>::zip_to_stream(
00203     char_type *buffer,
00204     std::streamsize buffer_size)
00205 {    
00206     std::streamsize written_byte_size = 0, total_written_byte_size = 0;
00207 
00208     _zip_stream.next_in = (byte_buffer_type) buffer;
00209     _zip_stream.avail_in = static_cast<uInt>(buffer_size * sizeof(char_type));
00210     _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size());
00211     _zip_stream.next_out = &_output_buffer[0];
00212     size_t remainder = 0;
00213 
00214     // updating crc
00215     _crc = crc32(_crc, _zip_stream.next_in,
00216                  _zip_stream.avail_in);        
00217 
00218     do
00219     {
00220         _err = deflate(&_zip_stream, 0);
00221     
00222         if (_err == Z_OK  || _err == Z_STREAM_END)
00223         {
00224             written_byte_size= static_cast<std::streamsize>(_output_buffer.size()) -
00225                 _zip_stream.avail_out;
00226             total_written_byte_size += written_byte_size;
00227             // ouput buffer is full, dumping to ostream
00228 
00229             _ostream.write((const char_type*) &_output_buffer[0], 
00230                            static_cast<std::streamsize>(written_byte_size / sizeof(char_type)));
00231                                                 
00232             // checking if some bytes were not written.
00233             if((remainder = written_byte_size % sizeof(char_type)) != 0)
00234             {
00235                 // copy to the beginning of the stream
00236                 memcpy(&_output_buffer[0], 
00237                        &_output_buffer[written_byte_size-remainder],
00238                        remainder);
00239             }
00240                 
00241             _zip_stream.avail_out = static_cast<uInt>(_output_buffer.size()-remainder);
00242             _zip_stream.next_out = &_output_buffer[remainder];
00243         }
00244     } 
00245     while(_zip_stream.avail_in != 0 && _err == Z_OK);
00246     
00247     return _err == Z_OK;
00248 }
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 //*****************************************************************************
00257 //  template class basic_unzip_streambuf
00258 //*****************************************************************************
00259 
00260 //-----------------------------------------------------------------------------
00261 // PUBLIC
00262 //-----------------------------------------------------------------------------
00263 
00266 template <class charT, class traits>
00267 basic_unzip_streambuf<charT, traits>::basic_unzip_streambuf(istream_reference istream,
00268                                                             int window_size,
00269                                                             size_t read_buffer_size,
00270                                                             size_t input_buffer_size)
00271     : _istream(istream),
00272       _input_buffer(input_buffer_size),
00273       _buffer(read_buffer_size),
00274       _crc(0)
00275 {
00276     // setting zalloc, zfree and opaque
00277     _zip_stream.zalloc = (alloc_func) 0;
00278     _zip_stream.zfree = (free_func) 0;
00279 
00280     _zip_stream.next_in = NULL;
00281     _zip_stream.avail_in = 0;
00282     _zip_stream.avail_out = 0;
00283     _zip_stream.next_out = NULL;
00284 
00285     _err = inflateInit2(&_zip_stream, window_size);
00286         
00287     this->setg(&_buffer[0] + 4,     // beginning of putback area
00288                &_buffer[0] + 4,     // read position
00289                &_buffer[0] + 4);    // end position    
00290 }
00291 
00295 template <class charT, class traits>
00296 basic_unzip_streambuf<charT, traits>::~basic_unzip_streambuf(void)
00297 {
00298     inflateEnd(&_zip_stream);
00299 }
00300 
00301 
00305 template <class charT, class traits>
00306 typename basic_unzip_streambuf<charT, traits>::int_type
00307 basic_unzip_streambuf<charT, traits>::underflow(void)
00308 { 
00309     if(this->gptr() && ( this->gptr() < this->egptr()))
00310         return * reinterpret_cast<unsigned char *>(this->gptr());
00311      
00312     int n_putback = static_cast<int>(this->gptr() - this->eback());
00313     if(n_putback > 4)
00314         n_putback = 4;
00315        
00316     memcpy(&_buffer[0] + (4 - n_putback),
00317            this->gptr() - n_putback,
00318            n_putback * sizeof(char_type));
00319   
00320     int num = 
00321         unzip_from_stream(&_buffer[0] + 4, 
00322                           static_cast<std::streamsize>((_buffer.size() - 4) *
00323                                                        sizeof(char_type)));
00324         
00325     if(num <= 0) // ERROR or EOF
00326         return EOF;
00327     
00328     // reset buffer pointers
00329     this->setg(&_buffer[0] + (4 - n_putback),   // beginning of putback area
00330                &_buffer[0] + 4,                 // read position
00331                &_buffer[0] + 4 + num);          // end of buffer
00332     
00333     // return next character
00334     return * reinterpret_cast<unsigned char *>(this->gptr());    
00335 }
00336 
00339 template <class charT, class traits> inline
00340 typename basic_unzip_streambuf<charT, traits>::istream_reference
00341 basic_unzip_streambuf<charT, traits>::get_istream(void)
00342 {
00343     return _istream;
00344 }
00345 
00348 template <class charT, class traits> inline
00349 z_stream &
00350 basic_unzip_streambuf<charT, traits>::get_zip_stream(void)
00351 {
00352     return _zip_stream;
00353 }
00354 
00357 template <class charT, class traits> inline
00358 int
00359 basic_unzip_streambuf<charT, traits>::get_zerr(void) const
00360 {
00361     return _err;
00362 }
00363 
00366 template <class charT, class traits> inline
00367 unsigned long
00368 basic_unzip_streambuf<charT, traits>::get_crc(void) const
00369 {
00370     return _crc;
00371 }
00372 
00375 template <class charT, class traits> inline
00376 long
00377 basic_unzip_streambuf<charT, traits>::get_out_size(void) const
00378 {
00379     return _zip_stream.total_out;
00380 }
00381 
00384 template <class charT, class traits> inline
00385 long
00386 basic_unzip_streambuf<charT, traits>::get_in_size(void) const
00387 {
00388     return _zip_stream.total_in;
00389 }
00390 
00391 
00392 //-----------------------------------------------------------------------------
00393 // PRIVATE
00394 //-----------------------------------------------------------------------------
00395 
00398 template <class charT, class traits> inline
00399 void
00400 basic_unzip_streambuf<charT, traits>::put_back_from_zip_stream(void)
00401 {
00402     if(_zip_stream.avail_in == 0)
00403         return;
00404 
00405     _istream.clear(std::ios::goodbit);
00406     _istream.seekg(-intf(_zip_stream.avail_in),
00407                    std::ios_base::cur);
00408 
00409     _zip_stream.avail_in = 0;
00410 }
00411 
00414 template <class charT, class traits> inline
00415 std::streamsize
00416 basic_unzip_streambuf<charT, traits>::unzip_from_stream(char_type* buffer,
00417                                                         std::streamsize buffer_size)
00418 {
00419     _zip_stream.next_out  = 
00420         (byte_buffer_type) buffer;
00421     _zip_stream.avail_out = 
00422         static_cast<uInt>(buffer_size * sizeof(char_type));
00423     size_t count = _zip_stream.avail_in;
00424 
00425     do
00426     {
00427         if(_zip_stream.avail_in == 0)
00428             count=fill_input_buffer();
00429 
00430         if(_zip_stream.avail_in)
00431         {
00432             _err = inflate(&_zip_stream,  Z_SYNC_FLUSH);
00433         }
00434     }
00435     while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0);
00436 
00437     // updating crc
00438     _crc = crc32(_crc, (byte_buffer_type) buffer,
00439                  buffer_size - _zip_stream.avail_out / sizeof(char_type));
00440         
00441     std::streamsize n_read = 
00442         buffer_size - _zip_stream.avail_out / sizeof(char_type);
00443         
00444     // check if it is the end
00445     if (_err == Z_STREAM_END)
00446         put_back_from_zip_stream();                
00447         
00448     return n_read;
00449 }
00450 
00451 
00454 template <class charT, class traits> inline
00455 size_t
00456 basic_unzip_streambuf<charT, traits>::fill_input_buffer(void)
00457 {
00458     _zip_stream.next_in = &_input_buffer[0];
00459     _istream.read((char_type*) &_input_buffer[0], 
00460                   static_cast<std::streamsize>(_input_buffer.size() /
00461                                                sizeof(char_type)));
00462         
00463     return _zip_stream.avail_in = _istream.gcount()*sizeof(char_type);
00464 }
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 //*****************************************************************************
00473 //  template class basic_zip_ostream
00474 //*****************************************************************************
00475 
00476 //-----------------------------------------------------------------------------
00477 // PUBLIC
00478 //-----------------------------------------------------------------------------
00479 
00482 template <class charT, class traits> inline
00483 basic_zip_ostream<charT, traits>::basic_zip_ostream(ostream_reference ostream,
00484                                                     bool is_gzip,
00485                                                     int level,
00486                                                     EStrategy strategy,
00487                                                     int window_size,
00488                                                     int memory_level,
00489                                                     size_t buffer_size) :
00490     basic_zip_streambuf<charT, traits>(ostream, level, strategy, window_size,
00491                                        memory_level, buffer_size),
00492     std::basic_ostream<charT, traits>(this),
00493     _is_gzip(is_gzip),
00494     _added_footer(false)
00495 {
00496     if(_is_gzip)
00497         add_header();
00498 }
00499 
00502 template <class charT, class traits>
00503 basic_zip_ostream<charT, traits>::~basic_zip_ostream(void)
00504 {
00505     if(_is_gzip)
00506         add_footer();
00507 }
00508 
00511 template <class charT, class traits> inline
00512 bool basic_zip_ostream<charT, traits>::is_gzip(void) const
00513 {
00514     return _is_gzip;
00515 }
00516 
00520 template <class charT, class traits> inline
00521 basic_zip_ostream<charT, traits>& basic_zip_ostream<charT, traits>::zflush(void)
00522 {
00523     std::basic_ostream<charT, traits>::flush();
00524     basic_zip_streambuf<charT, traits>::flush();
00525     return *this;
00526 }
00527 
00528 template <class charT, class traits> inline
00529 void basic_zip_ostream<charT, traits>::finished(void)
00530 {
00531     if(_is_gzip)
00532         add_footer();
00533     else
00534         zflush();
00535 }
00536 
00537 
00538 //-----------------------------------------------------------------------------
00539 // PRIVATE
00540 //-----------------------------------------------------------------------------
00541 
00545 template <class charT, class traits>
00546 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_header(void)
00547 {
00548     char_type zero = 0;
00549         
00550     this->get_ostream() << static_cast<char_type>(detail::gz_magic[0])
00551                         << static_cast<char_type>(detail::gz_magic[1])
00552                         << static_cast<char_type>(Z_DEFLATED)
00553                         << zero //flags
00554                         << zero<<zero<<zero<<zero // time
00555                         << zero //xflags
00556                         << static_cast<char_type>(OS_CODE);
00557         
00558     return *this;
00559 }
00560 
00564 template <class charT, class traits>
00565 basic_zip_ostream<charT,traits>& basic_zip_ostream<charT, traits>::add_footer(void)
00566 {
00567     if(_added_footer)
00568         return *this;
00569 
00570     zflush();
00571 
00572     _added_footer = true;
00573 
00574     // Writes crc and length in LSB order to the stream.
00575     unsigned long crc = this->get_crc();
00576     for(int n=0;n<4;++n)
00577     {
00578         this->get_ostream().put((int)(crc & 0xff));
00579         crc >>= 8;
00580     }
00581 
00582     unsigned long length = this->get_in_size();
00583     for(int n=0;n<4;++n)
00584     {
00585         this->get_ostream().put((int)(length & 0xff));
00586         length >>= 8;
00587     }
00588 
00589     return *this;
00590 }
00591 
00592 
00593 
00594 
00595 
00596 
00597 //*****************************************************************************
00598 //  template class basic_zip_istream
00599 //*****************************************************************************
00600 
00601 //-----------------------------------------------------------------------------
00602 // PUBLIC
00603 //-----------------------------------------------------------------------------
00604 
00607 template <class charT, class traits>
00608 basic_zip_istream<charT, traits>::basic_zip_istream(istream_reference istream,
00609                                                     int window_size,
00610                                                     size_t read_buffer_size,
00611                                                     size_t input_buffer_size)
00612     : basic_unzip_streambuf<charT, traits>(istream, window_size,
00613                                            read_buffer_size, input_buffer_size),
00614       std::basic_istream<charT, traits>(this),
00615       _is_gzip(false),
00616       _gzip_crc(0),
00617       _gzip_data_size(0)
00618 {
00619     if(this->get_zerr() == Z_OK)
00620         check_header();
00621 }
00622 
00625 template <class charT, class traits> inline
00626 bool
00627 basic_zip_istream<charT, traits>::is_gzip(void) const
00628 {
00629     return _is_gzip;
00630 }
00631 
00639 template <class charT, class traits> inline
00640 bool
00641 basic_zip_istream<charT, traits>::check_crc(void)
00642 {
00643     read_footer();
00644     return this->get_crc() == _gzip_crc;
00645 }
00646 
00649 template <class charT, class traits> inline
00650 bool
00651 basic_zip_istream<charT, traits>::check_data_size(void) const
00652 {
00653     return this->get_out_size() == _gzip_data_size;
00654 }
00655 
00658 template <class charT, class traits> inline
00659 long
00660 basic_zip_istream<charT, traits>::get_gzip_crc(void) const
00661 {
00662     return _gzip_crc;
00663 }
00664 
00667 template <class charT, class traits> inline
00668 long
00669 basic_zip_istream<charT, traits>::get_gzip_data_size(void) const
00670 {
00671     return _gzip_data_size;
00672 }
00673 
00674 //-----------------------------------------------------------------------------
00675 // PROTECTED
00676 //-----------------------------------------------------------------------------
00677 
00681 template <class charT, class traits>
00682 int
00683 basic_zip_istream<charT, traits>::check_header(void)
00684 {
00685     int method; /* method byte */
00686     int flags;  /* flags byte */
00687     uInt len;
00688     int c;
00689     int err=0;
00690     z_stream &zip_stream = this->get_zip_stream();
00691 
00692     /* Check the gzip magic header */
00693     for(len = 0; len < 2; len++) 
00694     {
00695         c = (int)this->get_istream().get();
00696         if (c != detail::gz_magic[len]) 
00697         {
00698             if (len != 0) 
00699                 this->get_istream().unget();
00700             if (c!= EOF) 
00701             {
00702                 this->get_istream().unget();
00703             }
00704             
00705             err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
00706             _is_gzip = false;
00707             return err;
00708         }
00709     }
00710     
00711     _is_gzip = true;
00712     method = (int)this->get_istream().get();
00713     flags = (int)this->get_istream().get();
00714     if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0) 
00715     {
00716         err = Z_DATA_ERROR;
00717         return err;
00718     }
00719 
00720     /* Discard time, xflags and OS code: */
00721     for (len = 0; len < 6; len++) 
00722         this->get_istream().get();
00723     
00724     if ((flags & detail::gz_extra_field) != 0) 
00725     { 
00726         /* skip the extra field */
00727         len  =  (uInt)this->get_istream().get();
00728         len += ((uInt)this->get_istream().get())<<8;
00729         /* len is garbage if EOF but the loop below will quit anyway */
00730         while (len-- != 0 && this->get_istream().get() != EOF) ;
00731     }
00732     if ((flags & detail::gz_orig_name) != 0) 
00733     { 
00734         /* skip the original file name */
00735         while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00736     }
00737     if ((flags & detail::gz_comment) != 0) 
00738     {   
00739         /* skip the .gz file comment */
00740         while ((c = this->get_istream().get()) != 0 && c != EOF) ;
00741     }
00742     if ((flags & detail::gz_head_crc) != 0) 
00743     {  /* skip the header crc */
00744         for (len = 0; len < 2; len++) 
00745             this->get_istream().get();
00746     }
00747     err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK;
00748 
00749     return err;
00750 }
00751 
00755 template <class charT, class traits>
00756 void
00757 basic_zip_istream<charT, traits>::read_footer(void)
00758 {        
00759     if(_is_gzip)
00760     {
00761         _gzip_crc = 0;
00762         for(int n=0;n<4;++n)
00763             _gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n));
00764 
00765         _gzip_data_size = 0;
00766         for(int n=0;n<4;++n)
00767             _gzip_data_size += 
00768                 ((((int) this->get_istream().get()) & 0xff) << (8*n));
00769     }
00770 }

Generated on Thu Aug 25 04:12:20 2005 for OpenSG by  doxygen 1.4.3