1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "precompile.h"
33 #define Z_BUFSIZE (1024 * 4)
35 #define ALLOC(size) malloc(size)
36 #define TRYFREE(p) {if (p) free(p);}
38 local
int get_byte(gz_stream
* s
);
39 local
int destroy(gz_stream
* s
);
40 local uLong
getLong(gz_stream
* s
);
42 /* ===========================================================================
43 Opens a gzip (.gz) file for reading or writing. The mode parameter
44 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
45 or path name (if fd == -1).
46 gz_open return NULL if the file could not be opened or if there was
47 insufficient memory to allocate the (de)compression state; errno
48 can be checked to distinguish the two cases (if errno is zero, the
49 zlib error is Z_MEM_ERROR).
51 gz_stream
*gz_open(HStream
& _stream
)
54 //int level = Z_DEFAULT_COMPRESSION; /* compression level */
56 // char *p = (char*)mode;
57 //char fmode[80]; /* copy of mode, without the compression level */
61 s
= (gz_stream
*) ALLOC(sizeof(gz_stream
));
64 s
->stream
.zalloc
= (alloc_func
) 0;
65 s
->stream
.zfree
= (free_func
) 0;
66 s
->stream
.opaque
= (voidpf
) 0;
67 s
->stream
.next_in
= s
->inbuf
= Z_NULL
;
68 s
->stream
.next_out
= s
->outbuf
= Z_NULL
;
69 s
->stream
.avail_in
= s
->stream
.avail_out
= 0;
70 //s->_inputstream = NULL;
73 s
->crc
= crc32(0L, Z_NULL
, 0);
80 err
= inflateInit2(&(s
->stream
), -MAX_WBITS
);
81 s
->stream
.next_in
= s
->inbuf
= (Byte
*) ALLOC(Z_BUFSIZE
);
83 if (err
!= Z_OK
|| s
->inbuf
== Z_NULL
)
85 return destroy(s
), (gz_stream
*) Z_NULL
;
88 s
->stream
.avail_out
= Z_BUFSIZE
;
91 s
->_inputstream
= &_stream
;
93 return (gz_stream
*) s
;
97 /* ===========================================================================
98 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
100 IN assertion: the stream s has been successfully opened for reading.
102 local
int get_byte(gz_stream
* s
)
106 if (s
->stream
.avail_in
== 0)
110 s
->stream
.avail_in
= s
->_inputstream
->readBytes(s
->inbuf
, Z_BUFSIZE
);
111 if (s
->stream
.avail_in
== 0)
116 s
->stream
.next_in
= s
->inbuf
;
118 s
->stream
.avail_in
--;
119 return *(s
->stream
.next_in
)++;
123 /* ===========================================================================
124 * Cleanup then free the given gz_stream. Return a zlib error code.
125 * Try freeing in the reverse order of allocations.
127 local
int destroy(gz_stream
* s
)
132 return Z_STREAM_ERROR
;
136 if (s
->stream
.state
!= NULL
)
138 err
= inflateEnd(&(s
->stream
));
150 // typedef unsigned char Byte
151 // typedef Byte FAR Bytef;
152 /* ===========================================================================
153 Reads the given number of uncompressed bytes from the compressed file.
154 gz_read returns the number of bytes actually read (0 for end of file).
156 int gz_read(gz_stream
* file
, voidp buf
, unsigned len
)
158 //printf("@@ gz_read : len : %d\t",len);
159 gz_stream
*s
= (gz_stream
*) file
;
160 Bytef
*start
= (Bytef
*) buf
; /* starting point for crc computation */
161 Byte
*next_out
; /* == stream.next_out but not forced far (for MSDOS) */
163 return Z_STREAM_ERROR
;
165 if (s
->z_err
== Z_DATA_ERROR
|| s
->z_err
== Z_ERRNO
)
167 if (s
->z_err
== Z_STREAM_END
)
170 s
->stream
.next_out
= next_out
= (Bytef
*) buf
;
171 s
->stream
.avail_out
= len
;
173 while (s
->stream
.avail_out
!= 0)
177 /* Copy first the lookahead bytes: */
178 uInt n
= s
->stream
.avail_in
;
180 if (n
> s
->stream
.avail_out
)
181 n
= s
->stream
.avail_out
;
184 memcpy(s
->stream
.next_out
, s
->stream
.next_in
, n
);
186 s
->stream
.next_out
= next_out
;
187 s
->stream
.next_in
+= n
;
188 s
->stream
.avail_out
-= n
;
189 s
->stream
.avail_in
-= n
;
191 if (s
->stream
.avail_out
> 0)
193 s
->stream
.avail_out
-=
194 s
->_inputstream
->readBytes(next_out
, s
->stream
.avail_out
);
196 return (int) (len
- s
->stream
.avail_out
);
198 if (s
->stream
.avail_in
== 0 && !s
->z_eof
)
202 s
->stream
.avail_in
= s
->_inputstream
->readBytes(s
->inbuf
, Z_BUFSIZE
);
203 if (s
->stream
.avail_in
== 0)
208 s
->stream
.next_in
= s
->inbuf
;
210 s
->z_err
= inflate(&(s
->stream
), Z_NO_FLUSH
);
212 if (s
->z_err
== Z_STREAM_END
)
214 /* Check CRC and original size */
215 s
->crc
= crc32(s
->crc
, start
, (uInt
) (s
->stream
.next_out
- start
));
216 start
= s
->stream
.next_out
;
218 if (getLong(s
) != s
->crc
|| getLong(s
) != s
->stream
.total_out
)
220 s
->z_err
= Z_DATA_ERROR
;
222 else if (s
->z_err
== Z_OK
)
224 inflateReset(&(s
->stream
));
225 s
->crc
= crc32(0L, Z_NULL
, 0);
228 if (s
->z_err
!= Z_OK
|| s
->z_eof
)
231 s
->crc
= crc32(s
->crc
, start
, (uInt
) (s
->stream
.next_out
- start
));
232 return (int) (len
- s
->stream
.avail_out
);
235 /* ===========================================================================
236 Flushes all pending output into the compressed file. The parameter
237 flush is as in the deflate() function.
238 gz_flush should be called only when strictly necessary because it can
241 int gz_flush(gz_stream
* file
, int flush
)
245 gz_stream
*s
= (gz_stream
*) file
;
247 if (s
== NULL
|| s
->mode
!= 'w')
248 return Z_STREAM_ERROR
;
250 s
->stream
.avail_in
= 0; /* should be zero already anyway */
254 len
= Z_BUFSIZE
- s
->stream
.avail_out
;
258 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
263 s
->stream
.next_out
= s
->outbuf
;
264 s
->stream
.avail_out
= Z_BUFSIZE
;
268 s
->z_err
= deflate(&(s
->stream
), flush
);
270 /* deflate has finished flushing only when it hasn't used up
271 * all the available space in the output buffer:
273 done
= (s
->stream
.avail_out
!= 0 || s
->z_err
== Z_STREAM_END
);
275 if (s
->z_err
!= Z_OK
&& s
->z_err
!= Z_STREAM_END
)
278 return s
->z_err
== Z_STREAM_END
? Z_OK
: s
->z_err
;
282 /* ===========================================================================
283 Reads a long in LSB order from the given gz_stream. Sets
285 local uLong
getLong(gz_stream
* s
)
287 uLong x
= (uLong
) get_byte(s
);
290 x
+= ((uLong
) get_byte(s
)) << 8;
291 x
+= ((uLong
) get_byte(s
)) << 16;
294 s
->z_err
= Z_DATA_ERROR
;
295 x
+= ((uLong
) c
) << 24;
300 /* ===========================================================================
301 Flushes all pending output if necessary, closes the compressed file
302 and deallocates all the (de)compression state.
304 int gz_close(gz_stream
* file
)
307 gz_stream
*s
= (gz_stream
*) file
;
310 return Z_STREAM_ERROR
;
314 err
= gz_flush(file
, Z_FINISH
);
317 putLong(s
->file
, s
->crc
);
318 putLong(s
->file
, s
->stream
.total_in
);
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */