1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zcodec.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
33 #include <tools/stream.hxx>
38 #include "zlib/zlib.h"
41 #include <tools/zcodec.hxx>
43 #include <osl/endian.h>
49 #define PZSTREAM ((z_stream*) mpsC_Stream)
52 #define GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
53 #define GZ_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
54 #define GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
55 #define GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */
56 #define GZ_COMMENT 0x10 /* bit 4 set: file comment present */
57 #define GZ_RESERVED 0xE0 /* bits 5..7: reserved */
59 static int gz_magic
[2] = { 0x1f, 0x8b }; /* gzip magic header */
66 ZCodec::ZCodec( ULONG nInBufSize
, ULONG nOutBufSize
, ULONG nMemUsage
)
69 mnMemUsage
= nMemUsage
;
70 mnInBufSize
= nInBufSize
;
71 mnOutBufSize
= nOutBufSize
;
72 mpsC_Stream
= new z_stream
;
75 ZCodec::ZCodec( void )
78 mnMemUsage
= MAX_MEM_USAGE
;
79 mnInBufSize
= DEFAULT_IN_BUFSIZE
;
80 mnOutBufSize
= DEFAULT_OUT_BUFSIZE
;
81 mpsC_Stream
= new z_stream
;
84 // ------------------------------------------------------------------------
88 delete (z_stream
*) mpsC_Stream
;
91 // ------------------------------------------------------------------------
93 void ZCodec::BeginCompression( ULONG nCompressMethod
)
98 mpIStm
= mpOStm
= NULL
;
99 mnInToRead
= 0xffffffff;
100 mpInBuf
= mpOutBuf
= NULL
;
101 PZSTREAM
->total_out
= PZSTREAM
->total_in
= 0;
102 mnCompressMethod
= nCompressMethod
;
103 PZSTREAM
->zalloc
= ( alloc_func
)0;
104 PZSTREAM
->zfree
= ( free_func
)0;
105 PZSTREAM
->opaque
= ( voidpf
)0;
106 PZSTREAM
->avail_out
= PZSTREAM
->avail_in
= 0;
109 // ------------------------------------------------------------------------
111 long ZCodec::EndCompression()
117 if ( mbInit
& 2 ) // 1->decompress, 3->compress
123 while ( deflate( PZSTREAM
, Z_FINISH
) != Z_STREAM_END
);
127 retvalue
= PZSTREAM
->total_in
;
128 deflateEnd( PZSTREAM
);
132 retvalue
= PZSTREAM
->total_out
;
133 inflateEnd( PZSTREAM
);
138 return ( mbStatus
) ? retvalue
: -1;
142 // ------------------------------------------------------------------------
144 long ZCodec::Compress( SvStream
& rIStm
, SvStream
& rOStm
)
146 long nOldTotal_In
= PZSTREAM
->total_in
;
152 ImplInitBuf( FALSE
);
153 mpInBuf
= new BYTE
[ mnInBufSize
];
155 while (( PZSTREAM
->avail_in
= mpIStm
->Read( PZSTREAM
->next_in
= mpInBuf
, mnInBufSize
)) != 0 )
157 if ( PZSTREAM
->avail_out
== 0 )
159 if ( deflate( PZSTREAM
, Z_NO_FLUSH
) < 0 )
165 return ( mbStatus
) ? (long)(PZSTREAM
->total_in
- nOldTotal_In
) : -1;
168 // ------------------------------------------------------------------------
170 long ZCodec::Decompress( SvStream
& rIStm
, SvStream
& rOStm
)
174 long nOldTotal_Out
= PZSTREAM
->total_out
;
177 return PZSTREAM
->total_out
- nOldTotal_Out
;
184 PZSTREAM
->next_out
= mpOutBuf
= new BYTE
[ PZSTREAM
->avail_out
= mnOutBufSize
];
188 if ( PZSTREAM
->avail_out
== 0 ) ImplWriteBack();
189 if ( PZSTREAM
->avail_in
== 0 && mnInToRead
)
191 nInToRead
= ( mnInBufSize
> mnInToRead
) ? mnInToRead
: mnInBufSize
;
192 PZSTREAM
->avail_in
= mpIStm
->Read( PZSTREAM
->next_in
= mpInBuf
, nInToRead
);
193 mnInToRead
-= nInToRead
;
195 if ( mnCompressMethod
& ZCODEC_UPDATE_CRC
)
196 mnCRC
= UpdateCRC( mnCRC
, mpInBuf
, nInToRead
);
199 err
= inflate( PZSTREAM
, Z_NO_FLUSH
);
207 while ( ( err
!= Z_STREAM_END
) && ( PZSTREAM
->avail_in
|| mnInToRead
) );
210 if ( err
== Z_STREAM_END
)
212 return ( mbStatus
) ? (long)(PZSTREAM
->total_out
- nOldTotal_Out
) : -1;
215 // ------------------------------------------------------------------------
217 long ZCodec::Write( SvStream
& rOStm
, const BYTE
* pData
, ULONG nSize
)
222 ImplInitBuf( FALSE
);
225 PZSTREAM
->avail_in
= nSize
;
226 PZSTREAM
->next_in
= (unsigned char*)pData
;
228 while ( PZSTREAM
->avail_in
|| ( PZSTREAM
->avail_out
== 0 ) )
230 if ( PZSTREAM
->avail_out
== 0 )
233 if ( deflate( PZSTREAM
, Z_NO_FLUSH
) < 0 )
239 return ( mbStatus
) ? (long)nSize
: -1;
242 // ------------------------------------------------------------------------
244 long ZCodec::Read( SvStream
& rIStm
, BYTE
* pData
, ULONG nSize
)
250 return 0; // PZSTREAM->total_out;
257 PZSTREAM
->avail_out
= nSize
;
258 PZSTREAM
->next_out
= pData
;
261 if ( PZSTREAM
->avail_in
== 0 && mnInToRead
)
263 nInToRead
= (mnInBufSize
> mnInToRead
) ? mnInToRead
: mnInBufSize
;
264 PZSTREAM
->avail_in
= mpIStm
->Read (
265 PZSTREAM
->next_in
= mpInBuf
, nInToRead
);
266 mnInToRead
-= nInToRead
;
268 if ( mnCompressMethod
& ZCODEC_UPDATE_CRC
)
269 mnCRC
= UpdateCRC( mnCRC
, mpInBuf
, nInToRead
);
272 err
= inflate( PZSTREAM
, Z_NO_FLUSH
);
275 // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
276 mbStatus
= (err
== Z_BUF_ERROR
);
280 while ( (err
!= Z_STREAM_END
) &&
281 (PZSTREAM
->avail_out
!= 0) &&
282 (PZSTREAM
->avail_in
|| mnInToRead
) );
283 if ( err
== Z_STREAM_END
)
286 return (mbStatus
? (long)(nSize
- PZSTREAM
->avail_out
) : -1);
289 // ------------------------------------------------------------------------
291 long ZCodec::ReadAsynchron( SvStream
& rIStm
, BYTE
* pData
, ULONG nSize
)
297 return 0; // PZSTREAM->total_out;
304 PZSTREAM
->avail_out
= nSize
;
305 PZSTREAM
->next_out
= pData
;
308 if ( PZSTREAM
->avail_in
== 0 && mnInToRead
)
310 nInToRead
= (mnInBufSize
> mnInToRead
) ? mnInToRead
: mnInBufSize
;
312 ULONG nStreamPos
= rIStm
.Tell();
313 rIStm
.Seek( STREAM_SEEK_TO_END
);
314 ULONG nMaxPos
= rIStm
.Tell();
315 rIStm
.Seek( nStreamPos
);
316 if ( ( nMaxPos
- nStreamPos
) < nInToRead
)
318 rIStm
.SetError( ERRCODE_IO_PENDING
);
319 err
= ! Z_STREAM_END
; // TODO What is appropriate code for this?
323 PZSTREAM
->avail_in
= mpIStm
->Read (
324 PZSTREAM
->next_in
= mpInBuf
, nInToRead
);
325 mnInToRead
-= nInToRead
;
327 if ( mnCompressMethod
& ZCODEC_UPDATE_CRC
)
328 mnCRC
= UpdateCRC( mnCRC
, mpInBuf
, nInToRead
);
331 err
= inflate( PZSTREAM
, Z_NO_FLUSH
);
334 // Accept Z_BUF_ERROR as EAGAIN or EWOULDBLOCK.
335 mbStatus
= (err
== Z_BUF_ERROR
);
339 while ( (err
!= Z_STREAM_END
) &&
340 (PZSTREAM
->avail_out
!= 0) &&
341 (PZSTREAM
->avail_in
|| mnInToRead
) );
342 if ( err
== Z_STREAM_END
)
345 return (mbStatus
? (long)(nSize
- PZSTREAM
->avail_out
) : -1);
348 // ------------------------------------------------------------------------
350 void ZCodec::ImplWriteBack()
352 ULONG nAvail
= mnOutBufSize
- PZSTREAM
->avail_out
;
356 if ( mbInit
& 2 && ( mnCompressMethod
& ZCODEC_UPDATE_CRC
) )
357 mnCRC
= UpdateCRC( mnCRC
, mpOutBuf
, nAvail
);
358 mpOStm
->Write( PZSTREAM
->next_out
= mpOutBuf
, nAvail
);
359 PZSTREAM
->avail_out
= mnOutBufSize
;
363 // ------------------------------------------------------------------------
365 void ZCodec::SetBreak( ULONG nInToRead
)
367 mnInToRead
= nInToRead
;
370 // ------------------------------------------------------------------------
372 ULONG
ZCodec::GetBreak( void )
374 return ( mnInToRead
+ PZSTREAM
->avail_in
);
377 // ------------------------------------------------------------------------
379 void ZCodec::SetCRC( ULONG nCRC
)
384 // ------------------------------------------------------------------------
386 ULONG
ZCodec::GetCRC()
391 // ------------------------------------------------------------------------
393 void ZCodec::ImplInitBuf ( BOOL nIOFlag
)
400 if ( mbStatus
&& ( mnCompressMethod
& ZCODEC_GZ_LIB
) )
402 BYTE n1
, n2
, j
, nMethod
, nFlags
;
403 for ( int i
= 0; i
< 2; i
++ ) // gz - magic number
406 if ( j
!= gz_magic
[ i
] )
411 if ( nMethod
!= Z_DEFLATED
)
413 if ( ( nFlags
& GZ_RESERVED
) != 0 )
415 /* Discard time, xflags and OS code: */
416 mpIStm
->SeekRel( 6 );
417 /* skip the extra field */
418 if ( nFlags
& GZ_EXTRA_FIELD
)
421 mpIStm
->SeekRel( n1
+ ( n2
<< 8 ) );
423 /* skip the original file name */
424 if ( nFlags
& GZ_ORIG_NAME
)
430 while ( j
&& !mpIStm
->IsEof() );
432 /* skip the .gz file comment */
433 if ( nFlags
& GZ_COMMENT
)
439 while ( j
&& !mpIStm
->IsEof() );
441 /* skip the header crc */
442 if ( nFlags
& GZ_HEAD_CRC
)
443 mpIStm
->SeekRel( 2 );
445 mbStatus
= ( inflateInit2( PZSTREAM
, -MAX_WBITS
) != Z_OK
) ? FALSE
: TRUE
;
449 mbStatus
= ( inflateInit( PZSTREAM
) >= 0 );
451 mpInBuf
= new BYTE
[ mnInBufSize
];
457 mbStatus
= ( deflateInit2_( PZSTREAM
, mnCompressMethod
& 0xff, Z_DEFLATED
,
458 MAX_WBITS
, mnMemUsage
, ( mnCompressMethod
>> 8 ) & 0xff,
459 ZLIB_VERSION
, sizeof( z_stream
) ) >= 0 );
461 PZSTREAM
->next_out
= mpOutBuf
= new BYTE
[ PZSTREAM
->avail_out
= mnOutBufSize
];
466 // ------------------------------------------------------------------------
468 ULONG
ZCodec::UpdateCRC ( ULONG nLatestCRC
, ULONG nNumber
)
472 nNumber
= SWAPLONG( nNumber
);
474 return rtl_crc32( nLatestCRC
, &nNumber
, 4 );
477 // ------------------------------------------------------------------------
479 ULONG
ZCodec::UpdateCRC ( ULONG nLatestCRC
, BYTE
* pSource
, long nDatSize
)
481 return rtl_crc32( nLatestCRC
, pSource
, nDatSize
);
484 // ------------------------------------------------------------------------
486 void GZCodec::BeginCompression( ULONG nCompressMethod
)
488 ZCodec::BeginCompression( nCompressMethod
| ZCODEC_GZ_LIB
);