Bump for 3.6-28
[LibreOffice.git] / hwpfilter / source / hgzip.cxx
blob13811d2069a8e46fba54d57ec2576e5ed3b3dbd8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "precompile.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include "hgzip.h"
36 #include "hstream.h"
38 #ifndef local
39 # define local static
40 #endif
42 #define Z_BUFSIZE (1024 * 4)
44 #define ALLOC(size) malloc(size)
45 #define TRYFREE(p) {if (p) free(p);}
47 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
48 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
49 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
50 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
51 #define COMMENT 0x10 /* bit 4 set: file comment present */
52 #define RESERVED 0xE0 /* bits 5..7: reserved */
54 local int get_byte(gz_stream * s);
55 local int destroy(gz_stream * s);
56 local uLong getLong(gz_stream * s);
58 /* ===========================================================================
59 Opens a gzip (.gz) file for reading or writing. The mode parameter
60 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
61 or path name (if fd == -1).
62 gz_open return NULL if the file could not be opened or if there was
63 insufficient memory to allocate the (de)compression state; errno
64 can be checked to distinguish the two cases (if errno is zero, the
65 zlib error is Z_MEM_ERROR).
67 gz_stream *gz_open(HStream & _stream)
69 int err;
70 //int level = Z_DEFAULT_COMPRESSION; /* compression level */
72 // char *p = (char*)mode;
73 //char fmode[80]; /* copy of mode, without the compression level */
74 //char *m = fmode;
75 gz_stream *s;
77 s = (gz_stream *) ALLOC(sizeof(gz_stream));
78 if (!s)
79 return Z_NULL;
80 s->stream.zalloc = (alloc_func) 0;
81 s->stream.zfree = (free_func) 0;
82 s->stream.opaque = (voidpf) 0;
83 s->stream.next_in = s->inbuf = Z_NULL;
84 s->stream.next_out = s->outbuf = Z_NULL;
85 s->stream.avail_in = s->stream.avail_out = 0;
86 //s->_inputstream = NULL;
87 s->z_err = Z_OK;
88 s->z_eof = 0;
89 s->crc = crc32(0L, Z_NULL, 0);
90 s->msg = NULL;
91 s->transparent = 0;
93 s->mode = 'r';
95 //realking
96 err = inflateInit2(&(s->stream), -MAX_WBITS);
97 s->stream.next_in = s->inbuf = (Byte *) ALLOC(Z_BUFSIZE);
99 if (err != Z_OK || s->inbuf == Z_NULL)
101 return destroy(s), (gz_stream *) Z_NULL;
104 s->stream.avail_out = Z_BUFSIZE;
106 errno = 0;
107 s->_inputstream = &_stream;
109 return (gz_stream *) s;
113 /* ===========================================================================
114 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
115 for end of file.
116 IN assertion: the stream s has been sucessfully opened for reading.
118 local int get_byte(gz_stream * s)
120 if (s->z_eof)
121 return EOF;
122 if (s->stream.avail_in == 0)
124 errno = 0;
126 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
127 if (s->stream.avail_in == 0)
129 s->z_eof = 1;
130 return EOF;
132 s->stream.next_in = s->inbuf;
134 s->stream.avail_in--;
135 return *(s->stream.next_in)++;
139 /* ===========================================================================
140 * Cleanup then free the given gz_stream. Return a zlib error code.
141 * Try freeing in the reverse order of allocations.
143 local int destroy(gz_stream * s)
145 int err = Z_OK;
147 if (!s)
148 return Z_STREAM_ERROR;
150 TRYFREE(s->msg);
152 if (s->stream.state != NULL)
154 err = inflateEnd(&(s->stream));
156 if (s->z_err < 0)
157 err = s->z_err;
159 TRYFREE(s->inbuf);
160 TRYFREE(s->outbuf);
161 TRYFREE(s);
162 return err;
166 // typedef unsigned char Byte
167 // typedef Byte FAR Bytef;
168 /* ===========================================================================
169 Reads the given number of uncompressed bytes from the compressed file.
170 gz_read returns the number of bytes actually read (0 for end of file).
172 int gz_read(gz_stream * file, voidp buf, unsigned len)
174 //printf("@@ gz_read : len : %d\t",len);
175 gz_stream *s = (gz_stream *) file;
176 Bytef *start = (Bytef *) buf; /* starting point for crc computation */
177 Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
178 if (s == NULL)
179 return Z_STREAM_ERROR;
181 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
182 return -1;
183 if (s->z_err == Z_STREAM_END)
184 return 0; /* EOF */
186 s->stream.next_out = next_out = (Bytef *) buf;
187 s->stream.avail_out = len;
189 while (s->stream.avail_out != 0)
191 if (s->transparent)
193 /* Copy first the lookahead bytes: */
194 uInt n = s->stream.avail_in;
196 if (n > s->stream.avail_out)
197 n = s->stream.avail_out;
198 if (n > 0)
200 memcpy(s->stream.next_out, s->stream.next_in, n);
201 next_out += n;
202 s->stream.next_out = next_out;
203 s->stream.next_in += n;
204 s->stream.avail_out -= n;
205 s->stream.avail_in -= n;
207 if (s->stream.avail_out > 0)
209 s->stream.avail_out -=
210 s->_inputstream->readBytes(next_out, s->stream.avail_out);
212 return (int) (len - s->stream.avail_out);
214 if (s->stream.avail_in == 0 && !s->z_eof)
217 errno = 0;
218 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
219 if (s->stream.avail_in == 0)
221 s->z_eof = 1;
222 break;
224 s->stream.next_in = s->inbuf;
226 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
228 if (s->z_err == Z_STREAM_END)
230 /* Check CRC and original size */
231 s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
232 start = s->stream.next_out;
234 if (getLong(s) != s->crc || getLong(s) != s->stream.total_out)
236 s->z_err = Z_DATA_ERROR;
238 else if (s->z_err == Z_OK)
240 inflateReset(&(s->stream));
241 s->crc = crc32(0L, Z_NULL, 0);
244 if (s->z_err != Z_OK || s->z_eof)
245 break;
247 s->crc = crc32(s->crc, start, (uInt) (s->stream.next_out - start));
248 return (int) (len - s->stream.avail_out);
251 /* ===========================================================================
252 Flushes all pending output into the compressed file. The parameter
253 flush is as in the deflate() function.
254 gz_flush should be called only when strictly necessary because it can
255 degrade compression.
257 int gz_flush(gz_stream * file, int flush)
259 uInt len;
260 int done = 0;
261 gz_stream *s = (gz_stream *) file;
263 if (s == NULL || s->mode != 'w')
264 return Z_STREAM_ERROR;
266 s->stream.avail_in = 0; /* should be zero already anyway */
268 for (;;)
270 len = Z_BUFSIZE - s->stream.avail_out;
271 if (len != 0)
274 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
275 s->z_err = Z_ERRNO;
276 return Z_ERRNO;
279 s->stream.next_out = s->outbuf;
280 s->stream.avail_out = Z_BUFSIZE;
282 if (done)
283 break;
284 s->z_err = deflate(&(s->stream), flush);
286 /* deflate has finished flushing only when it hasn't used up
287 * all the available space in the output buffer:
289 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
291 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END)
292 break;
294 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
298 /* ===========================================================================
299 Reads a long in LSB order from the given gz_stream. Sets
301 local uLong getLong(gz_stream * s)
303 uLong x = (uLong) get_byte(s);
304 int c;
306 x += ((uLong) get_byte(s)) << 8;
307 x += ((uLong) get_byte(s)) << 16;
308 c = get_byte(s);
309 if (c == EOF)
310 s->z_err = Z_DATA_ERROR;
311 x += ((uLong) c) << 24;
312 return x;
316 /* ===========================================================================
317 Flushes all pending output if necessary, closes the compressed file
318 and deallocates all the (de)compression state.
320 int gz_close(gz_stream * file)
322 // int err;
323 gz_stream *s = (gz_stream *) file;
325 if (s == NULL)
326 return Z_STREAM_ERROR;
327 #if 0
328 if (s->mode == 'w')
330 err = gz_flush(file, Z_FINISH);
331 if (err != Z_OK)
332 return destroy(s);
333 putLong(s->file, s->crc);
334 putLong(s->file, s->stream.total_in);
336 #endif
337 return destroy(s);
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */