Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / hwpfilter / source / hgzip.cxx
blobe813cd01b98e441360fe6728bec7b858b5e32a74
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include "hgzip.h"
27 #include "hstream.hxx"
29 #define Z_BUFSIZE (1024 * 4)
31 #define ALLOC(size) malloc(size)
32 #define TRYFREE(p) {if (p) free(p);}
34 static int get_byte(gz_stream * s);
35 static int destroy(gz_stream * s);
36 static uLong getLong(gz_stream * s);
38 /* ===========================================================================
39 Opens a gzip (.gz) file for reading or writing. The mode parameter
40 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
41 or path name (if fd == -1).
42 gz_open return NULL if the file could not be opened or if there was
43 insufficient memory to allocate the (de)compression state; errno
44 can be checked to distinguish the two cases (if errno is zero, the
45 zlib error is Z_MEM_ERROR).
47 gz_stream *gz_open(HStream & _stream)
49 int err;
50 //int level = Z_DEFAULT_COMPRESSION; /* compression level */
52 // char *p = (char*)mode;
53 //char fmode[80]; /* copy of mode, without the compression level */
54 //char *m = fmode;
55 gz_stream *s;
57 s = static_cast<gz_stream *>(ALLOC(sizeof(gz_stream)));
58 if (!s)
59 return Z_NULL;
60 s->stream.zalloc = nullptr;
61 s->stream.zfree = nullptr;
62 s->stream.opaque = nullptr;
63 s->stream.next_in = s->inbuf = Z_NULL;
64 s->stream.next_out = Z_NULL;
65 s->stream.avail_in = s->stream.avail_out = 0;
66 //s->_inputstream = NULL;
67 s->z_err = Z_OK;
68 s->z_eof = 0;
69 s->crc = crc32(0L, Z_NULL, 0);
70 s->msg = nullptr;
72 s->mode = 'r';
74 //realking
75 err = inflateInit2(&(s->stream), -MAX_WBITS);
76 s->stream.next_in = s->inbuf = static_cast<Byte *>(ALLOC(Z_BUFSIZE));
78 if (err != Z_OK || s->inbuf == Z_NULL)
80 destroy(s);
81 return Z_NULL;
84 s->stream.avail_out = Z_BUFSIZE;
86 errno = 0;
87 s->_inputstream = &_stream;
89 return s;
93 /* ===========================================================================
94 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
95 for end of file.
96 IN assertion: the stream s has been successfully opened for reading.
98 static int get_byte(gz_stream * s)
100 if (s->z_eof)
101 return EOF;
102 if (s->stream.avail_in == 0)
104 errno = 0;
106 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
107 if (s->stream.avail_in == 0)
109 s->z_eof = 1;
110 return EOF;
112 s->stream.next_in = s->inbuf;
114 s->stream.avail_in--;
115 return *(s->stream.next_in)++;
119 /* ===========================================================================
120 * Cleanup then free the given gz_stream. Return a zlib error code.
121 * Try freeing in the reverse order of allocations.
123 static int destroy(gz_stream * s)
125 int err = Z_OK;
127 if (!s)
128 return Z_STREAM_ERROR;
130 TRYFREE(s->msg);
132 if (s->stream.state != nullptr)
134 err = inflateEnd(&(s->stream));
136 if (s->z_err < 0)
137 err = s->z_err;
139 TRYFREE(s->inbuf);
140 TRYFREE(s);
141 return err;
145 // typedef unsigned char Byte
146 // typedef Byte FAR Bytef;
147 /* ===========================================================================
148 Reads the given number of uncompressed bytes from the compressed file.
149 gz_read returns the number of bytes actually read (0 for end of file).
151 size_t gz_read(gz_stream * file, voidp buf, unsigned len)
153 //printf("@@ gz_read : len : %d\t",len);
154 gz_stream *s = file;
155 Bytef *start = static_cast<Bytef *>(buf); /* starting point for crc computation */
156 Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
157 if (s == nullptr)
158 return 0;
160 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
161 return 0;
162 if (s->z_err == Z_STREAM_END)
163 return 0; /* EOF */
165 s->stream.next_out = next_out = static_cast<Bytef *>(buf);
166 s->stream.avail_out = len;
168 while (s->stream.avail_out != 0)
170 if (s->stream.avail_in == 0 && !s->z_eof)
173 errno = 0;
174 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
175 if (s->stream.avail_in == 0)
177 s->z_eof = 1;
178 break;
180 s->stream.next_in = s->inbuf;
182 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
184 if (s->z_err == Z_STREAM_END)
186 /* Check CRC and original size */
187 s->crc = crc32(s->crc, start, static_cast<uInt>(s->stream.next_out - start));
188 start = s->stream.next_out;
190 if (getLong(s) != s->crc || getLong(s) != s->stream.total_out)
192 s->z_err = Z_DATA_ERROR;
194 else if (s->z_err == Z_OK)
196 inflateReset(&(s->stream));
197 s->crc = crc32(0L, Z_NULL, 0);
200 if (s->z_err != Z_OK || s->z_eof)
201 break;
203 s->crc = crc32(s->crc, start, static_cast<uInt>(s->stream.next_out - start));
204 return len - s->stream.avail_out;
207 /* ===========================================================================
208 Flushes all pending output into the compressed file. The parameter
209 flush is as in the deflate() function.
210 gz_flush should be called only when strictly necessary because it can
211 degrade compression.
213 int gz_flush(gz_stream * file, int flush)
215 uInt len;
216 bool done = false;
217 gz_stream *s = file;
219 if (s == nullptr || s->mode != 'w')
220 return Z_STREAM_ERROR;
222 s->stream.avail_in = 0; /* should be zero already anyway */
224 for (;;)
226 len = Z_BUFSIZE - s->stream.avail_out;
227 if (len != 0)
230 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
231 s->z_err = Z_ERRNO;
232 return Z_ERRNO;
235 s->stream.next_out = nullptr;
236 s->stream.avail_out = Z_BUFSIZE;
238 if (done)
239 break;
240 s->z_err = deflate(&(s->stream), flush);
242 /* deflate has finished flushing only when it hasn't used up
243 * all the available space in the output buffer:
245 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
247 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END)
248 break;
250 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
254 /* ===========================================================================
255 Reads a long in LSB order from the given gz_stream. Sets
257 static uLong getLong(gz_stream * s)
259 uLong x = static_cast<unsigned char>(get_byte(s));
261 x += static_cast<unsigned char>(get_byte(s)) << 8;
262 x += static_cast<unsigned char>(get_byte(s)) << 16;
263 x += static_cast<unsigned char>(get_byte(s)) << 24;
264 if (s->z_eof)
266 s->z_err = Z_DATA_ERROR;
268 return x;
272 /* ===========================================================================
273 Flushes all pending output if necessary, closes the compressed file
274 and deallocates all the (de)compression state.
276 int gz_close(gz_stream * file)
278 // int err;
279 gz_stream *s = file;
281 if (s == nullptr)
282 return Z_STREAM_ERROR;
283 #if 0
284 if (s->mode == 'w')
286 err = gz_flush(file, Z_FINISH);
287 if (err != Z_OK)
288 return destroy(s);
289 putLong(s->file, s->crc);
290 putLong(s->file, s->stream.total_in);
292 #endif
293 return destroy(s);
296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */