LCOV - code coverage report
Current view: top level - tools/source/zcodec - zcodec.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 142 195 72.8 %
Date: 2014-11-03 Functions: 15 16 93.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/stream.hxx>
      21             : 
      22             : #include <zlib.h>
      23             : 
      24             : #include <tools/zcodec.hxx>
      25             : #include <rtl/crc.h>
      26             : #include <osl/endian.h>
      27             : 
      28             : #define PZSTREAM ((z_stream*) mpsC_Stream)
      29             : 
      30             : /* gzip flag byte */
      31             : //      GZ_ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
      32             : #define GZ_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
      33             : #define GZ_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
      34             : #define GZ_ORIG_NAME    0x08 /* bit 3 set: original file name present */
      35             : #define GZ_COMMENT      0x10 /* bit 4 set: file comment present */
      36             : #define GZ_RESERVED     0xE0 /* bits 5..7: reserved */
      37             : 
      38             : static const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
      39             : 
      40       26779 : ZCodec::ZCodec( sal_uIntPtr nInBufSize, sal_uIntPtr nOutBufSize )
      41             :     : meState(STATE_INIT)
      42             :     , mbStatus(false)
      43             :     , mbFinish(false)
      44             :     , mpInBuf(NULL)
      45             :     , mnInBufSize(nInBufSize)
      46             :     , mnInToRead(0)
      47             :     , mpOStm(NULL)
      48             :     , mpOutBuf(NULL)
      49             :     , mnOutBufSize(nOutBufSize)
      50             :     , mnCRC(0)
      51             :     , mnCompressLevel(0)
      52             :     , mbUpdateCrc(false)
      53       26779 :     , mbGzLib(false)
      54             : {
      55       26779 :     mpsC_Stream = new z_stream;
      56       26779 : }
      57             : 
      58       26779 : ZCodec::~ZCodec()
      59             : {
      60       26779 :     delete (z_stream*) mpsC_Stream;
      61       26779 : }
      62             : 
      63       26769 : void ZCodec::BeginCompression( int nCompressLevel, bool updateCrc, bool gzLib )
      64             : {
      65             :     assert(meState == STATE_INIT);
      66       26769 :     mbStatus = true;
      67       26769 :     mbFinish = false;
      68       26769 :     mpOStm = NULL;
      69       26769 :     mnInToRead = 0xffffffff;
      70       26769 :     mpInBuf = mpOutBuf = NULL;
      71       26769 :     PZSTREAM->total_out = PZSTREAM->total_in = 0;
      72       26769 :     mnCompressLevel = nCompressLevel;
      73       26769 :     mbUpdateCrc = updateCrc;
      74       26769 :     mbGzLib = gzLib;
      75       26769 :     PZSTREAM->zalloc = ( alloc_func )0;
      76       26769 :     PZSTREAM->zfree = ( free_func )0;
      77       26769 :     PZSTREAM->opaque = ( voidpf )0;
      78       26769 :     PZSTREAM->avail_out = PZSTREAM->avail_in = 0;
      79       26769 : }
      80             : 
      81       26769 : long ZCodec::EndCompression()
      82             : {
      83       26769 :     long retvalue = 0;
      84             : 
      85       26769 :     if (meState != STATE_INIT)
      86             :     {
      87       26769 :         if (meState == STATE_COMPRESS)
      88             :         {
      89        1199 :             do
      90             :             {
      91        1199 :                 ImplWriteBack();
      92             :             }
      93        1199 :             while ( deflate( PZSTREAM, Z_FINISH ) != Z_STREAM_END );
      94             : 
      95        1199 :             ImplWriteBack();
      96             : 
      97        1199 :             retvalue = PZSTREAM->total_in;
      98        1199 :             deflateEnd( PZSTREAM );
      99             :         }
     100             :         else
     101             :         {
     102       25570 :             retvalue = PZSTREAM->total_out;
     103       25570 :             inflateEnd( PZSTREAM );
     104             :         }
     105       26769 :         delete[] mpOutBuf;
     106       26769 :         delete[] mpInBuf;
     107       26769 :         meState = STATE_INIT;
     108             :     }
     109       26769 :     return ( mbStatus ) ? retvalue : -1;
     110             : }
     111             : 
     112           0 : long ZCodec::Compress( SvStream& rIStm, SvStream& rOStm )
     113             : {
     114           0 :     long nOldTotal_In = PZSTREAM->total_in;
     115             : 
     116             :     assert(meState == STATE_INIT);
     117           0 :     mpOStm = &rOStm;
     118           0 :     InitCompress();
     119           0 :     mpInBuf = new sal_uInt8[ mnInBufSize ];
     120           0 :     while (( PZSTREAM->avail_in = rIStm.Read( PZSTREAM->next_in = mpInBuf, mnInBufSize )) != 0 )
     121             :     {
     122           0 :         if ( PZSTREAM->avail_out == 0 )
     123           0 :             ImplWriteBack();
     124           0 :         if ( deflate( PZSTREAM, Z_NO_FLUSH ) < 0 )
     125             :         {
     126           0 :             mbStatus = false;
     127           0 :             break;
     128             :         }
     129             :     };
     130           0 :     return ( mbStatus ) ? (long)(PZSTREAM->total_in - nOldTotal_In) : -1;
     131             : }
     132             : 
     133         124 : long ZCodec::Decompress( SvStream& rIStm, SvStream& rOStm )
     134             : {
     135             :     int err;
     136             :     sal_uIntPtr nInToRead;
     137         124 :     long    nOldTotal_Out = PZSTREAM->total_out;
     138             : 
     139             :     assert(meState == STATE_INIT);
     140         124 :     mpOStm = &rOStm;
     141         124 :     InitDecompress(rIStm);
     142         124 :     PZSTREAM->next_out = mpOutBuf = new sal_uInt8[ PZSTREAM->avail_out = mnOutBufSize ];
     143         130 :     do
     144             :     {
     145         138 :         if ( PZSTREAM->avail_out == 0 ) ImplWriteBack();
     146         138 :         if ( PZSTREAM->avail_in == 0 && mnInToRead )
     147             :         {
     148         124 :             nInToRead = ( mnInBufSize > mnInToRead ) ? mnInToRead : mnInBufSize;
     149         124 :             PZSTREAM->avail_in = rIStm.Read( PZSTREAM->next_in = mpInBuf, nInToRead );
     150         124 :             mnInToRead -= nInToRead;
     151             : 
     152         124 :             if ( mbUpdateCrc )
     153           0 :                 UpdateCRC( mpInBuf, nInToRead );
     154             : 
     155             :         }
     156         138 :         err = inflate( PZSTREAM, Z_NO_FLUSH );
     157         138 :         if ( err < 0 )
     158             :         {
     159           8 :             mbStatus = false;
     160           8 :             break;
     161             :         }
     162             : 
     163             :     }
     164          14 :     while ( ( err != Z_STREAM_END)  && ( PZSTREAM->avail_in || mnInToRead ) );
     165         124 :     ImplWriteBack();
     166             : 
     167         124 :     return ( mbStatus ) ? (long)(PZSTREAM->total_out - nOldTotal_Out) : -1;
     168             : }
     169             : 
     170       23711 : long ZCodec::Write( SvStream& rOStm, const sal_uInt8* pData, sal_uIntPtr nSize )
     171             : {
     172       23711 :     if (meState == STATE_INIT)
     173             :     {
     174        1199 :         mpOStm = &rOStm;
     175        1199 :         InitCompress();
     176             :     }
     177             :     assert(&rOStm == mpOStm);
     178             : 
     179       23711 :     PZSTREAM->avail_in = nSize;
     180       23711 :     PZSTREAM->next_in = (unsigned char*)pData;
     181             : 
     182       71133 :     while ( PZSTREAM->avail_in || ( PZSTREAM->avail_out == 0 ) )
     183             :     {
     184       23711 :         if ( PZSTREAM->avail_out == 0 )
     185           0 :             ImplWriteBack();
     186             : 
     187       23711 :         if ( deflate( PZSTREAM, Z_NO_FLUSH ) < 0 )
     188             :         {
     189           0 :             mbStatus = false;
     190           0 :             break;
     191             :         }
     192             :     }
     193       23711 :     return ( mbStatus ) ? (long)nSize : -1;
     194             : }
     195             : 
     196           2 : long ZCodec::Read( SvStream& rIStm, sal_uInt8* pData, sal_uIntPtr nSize )
     197             : {
     198             :     int err;
     199             :     sal_uIntPtr nInToRead;
     200             : 
     201           2 :     if ( mbFinish )
     202           0 :         return 0;           // PZSTREAM->total_out;
     203             : 
     204           2 :     if (meState == STATE_INIT)
     205             :     {
     206           2 :         InitDecompress(rIStm);
     207             :     }
     208           2 :     PZSTREAM->avail_out = nSize;
     209           2 :     PZSTREAM->next_out = pData;
     210           2 :     do
     211             :     {
     212           2 :         if ( PZSTREAM->avail_in == 0 && mnInToRead )
     213             :         {
     214           2 :             nInToRead = (mnInBufSize > mnInToRead) ? mnInToRead : mnInBufSize;
     215             :             PZSTREAM->avail_in = rIStm.Read (
     216           2 :                 PZSTREAM->next_in = mpInBuf, nInToRead);
     217           2 :             mnInToRead -= nInToRead;
     218             : 
     219           2 :             if ( mbUpdateCrc )
     220           0 :                 UpdateCRC( mpInBuf, nInToRead );
     221             : 
     222             :         }
     223           2 :         err = inflate( PZSTREAM, Z_NO_FLUSH );
     224           2 :         if ( err < 0 )
     225             :         {
     226             :             // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
     227           0 :             mbStatus = (err == Z_BUF_ERROR);
     228           0 :             break;
     229             :         }
     230             :     }
     231           0 :     while ( (err != Z_STREAM_END) &&
     232           0 :             (PZSTREAM->avail_out != 0) &&
     233           0 :             (PZSTREAM->avail_in || mnInToRead) );
     234           2 :     if ( err == Z_STREAM_END )
     235           2 :         mbFinish = true;
     236             : 
     237           2 :     return (mbStatus ? (long)(nSize - PZSTREAM->avail_out) : -1);
     238             : }
     239             : 
     240      552919 : long ZCodec::ReadAsynchron( SvStream& rIStm, sal_uInt8* pData, sal_uIntPtr nSize )
     241             : {
     242      552919 :     int err = 0;
     243             :     sal_uIntPtr nInToRead;
     244             : 
     245      552919 :     if ( mbFinish )
     246           0 :         return 0;           // PZSTREAM->total_out;
     247             : 
     248      552919 :     if (meState == STATE_INIT)
     249             :     {
     250       25444 :         InitDecompress(rIStm);
     251             :     }
     252      552919 :     PZSTREAM->avail_out = nSize;
     253      552919 :     PZSTREAM->next_out = pData;
     254      553071 :     do
     255             :     {
     256      553073 :         if ( PZSTREAM->avail_in == 0 && mnInToRead )
     257             :         {
     258       25943 :             nInToRead = (mnInBufSize > mnInToRead) ? mnInToRead : mnInBufSize;
     259             : 
     260       25943 :             sal_uInt64 const nRemaining = rIStm.remainingSize();
     261       25943 :             if (nRemaining < nInToRead)
     262             :             {
     263           0 :                 rIStm.SetError( ERRCODE_IO_PENDING );
     264           0 :                 err= int(!Z_STREAM_END); // TODO What is appropriate code for this?
     265           0 :                 break;
     266             :             }
     267             : 
     268             :             PZSTREAM->avail_in = rIStm.Read (
     269       25943 :                 PZSTREAM->next_in = mpInBuf, nInToRead);
     270       25943 :             mnInToRead -= nInToRead;
     271             : 
     272       25943 :             if ( mbUpdateCrc )
     273       25943 :                 UpdateCRC( mpInBuf, nInToRead );
     274             : 
     275             :         }
     276      553073 :         err = inflate( PZSTREAM, Z_NO_FLUSH );
     277      553073 :         if ( err < 0 )
     278             :         {
     279             :             // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
     280           2 :             mbStatus = (err == Z_BUF_ERROR);
     281           2 :             break;
     282             :         }
     283             :     }
     284      527629 :     while ( (err != Z_STREAM_END) &&
     285      528127 :             (PZSTREAM->avail_out != 0) &&
     286         498 :             (PZSTREAM->avail_in || mnInToRead) );
     287      552919 :     if ( err == Z_STREAM_END )
     288       25442 :         mbFinish = true;
     289             : 
     290      552919 :     return (mbStatus ? (long)(nSize - PZSTREAM->avail_out) : -1);
     291             : }
     292             : 
     293        2536 : void ZCodec::ImplWriteBack()
     294             : {
     295        2536 :     sal_uIntPtr nAvail = mnOutBufSize - PZSTREAM->avail_out;
     296             : 
     297        2536 :     if ( nAvail )
     298             :     {
     299        2536 :         if (meState == STATE_COMPRESS && mbUpdateCrc)
     300         396 :             UpdateCRC( mpOutBuf, nAvail );
     301        2536 :         mpOStm->Write( PZSTREAM->next_out = mpOutBuf, nAvail );
     302        2536 :         PZSTREAM->avail_out = mnOutBufSize;
     303             :     }
     304        2536 : }
     305             : 
     306       25788 : void ZCodec::SetBreak( sal_uIntPtr nInToRead )
     307             : {
     308       25788 :     mnInToRead = nInToRead;
     309       25788 : }
     310             : 
     311      552919 : sal_uIntPtr ZCodec::GetBreak()
     312             : {
     313      552919 :     return ( mnInToRead + PZSTREAM->avail_in );
     314             : }
     315             : 
     316         198 : void ZCodec::SetCRC( sal_uIntPtr nCRC )
     317             : {
     318         198 :     mnCRC = nCRC;
     319         198 : }
     320             : 
     321             : 
     322        1199 : void ZCodec::InitCompress()
     323             : {
     324             :     assert(meState == STATE_INIT);
     325        1199 :     meState = STATE_COMPRESS;
     326             :     mbStatus = deflateInit2_(
     327             :         PZSTREAM, mnCompressLevel, Z_DEFLATED, MAX_WBITS, MAX_MEM_LEVEL,
     328        1199 :         Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof (z_stream)) >= 0;
     329        1199 :     mpOutBuf = new sal_uInt8[mnOutBufSize];
     330        1199 :     PZSTREAM->next_out = mpOutBuf;
     331        1199 :     PZSTREAM->avail_out = mnOutBufSize;
     332        1199 : }
     333             : 
     334       25570 : void ZCodec::InitDecompress(SvStream & inStream)
     335             : {
     336             :     assert(meState == STATE_INIT);
     337       25570 :     meState = STATE_DECOMPRESS;
     338       25570 :     if ( mbStatus &&  mbGzLib )
     339             :     {
     340             :         sal_uInt8 n1, n2, j, nMethod, nFlags;
     341           0 :         for ( int i = 0; i < 2; i++ )   // gz - magic number
     342             :         {
     343           0 :             inStream.ReadUChar( j );
     344           0 :             if ( j != gz_magic[ i ] )
     345           0 :                 mbStatus = false;
     346             :         }
     347           0 :         inStream.ReadUChar( nMethod );
     348           0 :         inStream.ReadUChar( nFlags );
     349           0 :         if ( nMethod != Z_DEFLATED )
     350           0 :             mbStatus = false;
     351           0 :         if ( ( nFlags & GZ_RESERVED ) != 0 )
     352           0 :             mbStatus = false;
     353             :         /* Discard time, xflags and OS code: */
     354           0 :         inStream.SeekRel( 6 );
     355             :         /* skip the extra field */
     356           0 :         if ( nFlags & GZ_EXTRA_FIELD )
     357             :         {
     358           0 :             inStream.ReadUChar( n1 ).ReadUChar( n2 );
     359           0 :             inStream.SeekRel( n1 + ( n2 << 8 ) );
     360             :         }
     361             :         /* skip the original file name */
     362           0 :         if ( nFlags & GZ_ORIG_NAME)
     363             :         {
     364           0 :             do
     365             :             {
     366           0 :                 inStream.ReadUChar( j );
     367             :             }
     368           0 :             while ( j && !inStream.IsEof() );
     369             :         }
     370             :         /* skip the .gz file comment */
     371           0 :         if ( nFlags & GZ_COMMENT )
     372             :         {
     373           0 :             do
     374             :             {
     375           0 :                 inStream.ReadUChar( j );
     376             :             }
     377           0 :             while ( j && !inStream.IsEof() );
     378             :         }
     379             :         /* skip the header crc */
     380           0 :         if ( nFlags & GZ_HEAD_CRC )
     381           0 :             inStream.SeekRel( 2 );
     382           0 :         if ( mbStatus )
     383           0 :             mbStatus = ( inflateInit2( PZSTREAM, -MAX_WBITS) != Z_OK ) ? false : true;
     384             :     }
     385             :     else
     386             :     {
     387       25570 :         mbStatus = ( inflateInit( PZSTREAM ) >= 0 );
     388             :     }
     389       25570 :     mpInBuf = new sal_uInt8[ mnInBufSize ];
     390       25570 : }
     391             : 
     392       26339 : void ZCodec::UpdateCRC ( sal_uInt8* pSource, long nDatSize)
     393             : {
     394       26339 :     mnCRC = rtl_crc32( mnCRC, pSource, nDatSize );
     395       26339 : }
     396             : 
     397             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10