LibreOffice Module hwpfilter (master) 1
hgzip.cxx
Go to the documentation of this file.
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 "precompile.h"
21
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include <errno.h>
26#include "hgzip.h"
27#include "hstream.hxx"
28
29#define Z_BUFSIZE (1024 * 4)
30
31#define ALLOC(size) malloc(size)
32#define TRYFREE(p) {if (p) free(p);}
33
34static int get_byte(gz_stream * s);
35static int destroy(gz_stream * s);
36static uLong getLong(gz_stream * s);
37
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).
46*/
48{
49 int err;
50 //int level = Z_DEFAULT_COMPRESSION; /* compression level */
51
52// char *p = (char*)mode;
53 //char fmode[80]; /* copy of mode, without the compression level */
54 //char *m = fmode;
55 gz_stream *s;
56
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(0, Z_NULL, 0);
70 s->msg = nullptr;
71
72 s->mode = 'r';
73
74//realking
75 err = inflateInit2(&(s->stream), -MAX_WBITS);
76 s->stream.next_in = s->inbuf = static_cast<Byte *>(ALLOC(Z_BUFSIZE));
77
78 if (err != Z_OK || s->inbuf == Z_NULL)
79 {
80 destroy(s);
81 return Z_NULL;
82 }
83
84 s->stream.avail_out = Z_BUFSIZE;
85
86 errno = 0;
87 s->_inputstream = &_stream;
88
89 return s;
90}
91
92
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.
97*/
98static int get_byte(gz_stream * s)
99{
100 if (s->z_eof)
101 return EOF;
102 if (s->stream.avail_in == 0)
103 {
104 errno = 0;
105
106 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
107 if (s->stream.avail_in == 0)
108 {
109 s->z_eof = 1;
110 return EOF;
111 }
112 s->stream.next_in = s->inbuf;
113 }
114 s->stream.avail_in--;
115 return *(s->stream.next_in)++;
116}
117
118
119/* ===========================================================================
120 * Cleanup then free the given gz_stream. Return a zlib error code.
121 * Try freeing in the reverse order of allocations.
122 */
123static int destroy(gz_stream * s)
124{
125 int err = Z_OK;
126
127 if (!s)
128 return Z_STREAM_ERROR;
129
130 TRYFREE(s->msg);
131
132 if (s->stream.state != nullptr)
133 {
134 err = inflateEnd(&(s->stream));
135 }
136 if (s->z_err < 0)
137 err = s->z_err;
138
139 TRYFREE(s->inbuf);
140 TRYFREE(s);
141 return err;
142}
143
144
145// typedef unsigned char Byte
146// typedef Byte 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).
150*/
151size_t gz_read(gz_stream * file, voidp buf, unsigned len)
152{
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 if (s == nullptr)
157 return 0;
158
159 if (s->z_eof)
160 return 0;
161
162 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
163 return 0;
164 if (s->z_err == Z_STREAM_END)
165 return 0; /* EOF */
166
167 s->stream.next_out = static_cast<Bytef *>(buf);
168 s->stream.avail_out = len;
169
170 while (s->stream.avail_out != 0)
171 {
172 if (s->stream.avail_in == 0 && !s->z_eof)
173 {
174
175 errno = 0;
176 s->stream.avail_in = s->_inputstream->readBytes(s->inbuf, Z_BUFSIZE);
177 if (s->stream.avail_in == 0)
178 {
179 s->z_eof = 1;
180 break;
181 }
182 s->stream.next_in = s->inbuf;
183 }
184 s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
185
186 if (s->z_err == Z_STREAM_END)
187 {
188/* Check CRC and original size */
189 s->crc = crc32(s->crc, start, static_cast<uInt>(s->stream.next_out - start));
190 start = s->stream.next_out;
191
192 if (getLong(s) != s->crc || getLong(s) != s->stream.total_out)
193 {
194 s->z_err = Z_DATA_ERROR;
195 }
196 else if (s->z_err == Z_OK)
197 {
198 inflateReset(&(s->stream));
199 s->crc = crc32(0, Z_NULL, 0);
200 }
201 }
202 if (s->z_err != Z_OK || s->z_eof)
203 break;
204 }
205 s->crc = crc32(s->crc, start, static_cast<uInt>(s->stream.next_out - start));
206 return len - s->stream.avail_out;
207}
208
209/* ===========================================================================
210 Flushes all pending output into the compressed file. The parameter
211 flush is as in the deflate() function.
212 gz_flush should be called only when strictly necessary because it can
213 degrade compression.
214*/
215int gz_flush(gz_stream * file, int flush)
216{
217 uInt len;
218 bool done = false;
219 gz_stream *s = file;
220
221 if (s == nullptr || s->mode != 'w')
222 return Z_STREAM_ERROR;
223
224 s->stream.avail_in = 0; /* should be zero already anyway */
225
226 for (;;)
227 {
228 len = Z_BUFSIZE - s->stream.avail_out;
229 if (len != 0)
230 {
231/*
232 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
233 s->z_err = Z_ERRNO;
234 return Z_ERRNO;
235 }
236 */
237 s->stream.next_out = nullptr;
238 s->stream.avail_out = Z_BUFSIZE;
239 }
240 if (done)
241 break;
242 s->z_err = deflate(&(s->stream), flush);
243
244/* deflate has finished flushing only when it hasn't used up
245 * all the available space in the output buffer:
246 */
247 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
248
249 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END)
250 break;
251 }
252 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
253}
254
255
256/* ===========================================================================
257 Reads a long in LSB order from the given gz_stream. Sets
258*/
259static uLong getLong(gz_stream * s)
260{
261 uLong x = static_cast<unsigned char>(get_byte(s));
262
263 x += static_cast<unsigned char>(get_byte(s)) << 8;
264 x += static_cast<unsigned char>(get_byte(s)) << 16;
265 x += static_cast<unsigned char>(get_byte(s)) << 24;
266 if (s->z_eof)
267 {
268 s->z_err = Z_DATA_ERROR;
269 }
270 return x;
271}
272
273
274/* ===========================================================================
275 Flushes all pending output if necessary, closes the compressed file
276 and deallocates all the (de)compression state.
277*/
279{
280// int err;
281 gz_stream *s = file;
282
283 if (s == nullptr)
284 return Z_STREAM_ERROR;
285#if 0
286 if (s->mode == 'w')
287 {
288 err = gz_flush(file, Z_FINISH);
289 if (err != Z_OK)
290 return destroy(s);
291 putLong(s->file, s->crc);
292 putLong(s->file, s->stream.total_in);
293 }
294#endif
295 return destroy(s);
296}
297
298/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
size_t readBytes(byte *buf, size_t aToRead)
Read some byte to buf as given size.
Definition: hstream.cxx:31
float x
#define Z_BUFSIZE
Definition: hgzip.cxx:29
gz_stream * gz_open(HStream &_stream)
Opens a gzipped stream for reading.
Definition: hgzip.cxx:47
int gz_close(gz_stream *file)
Flushes all pending output if necessary, closes the compressed stream and deallocates all the (de)com...
Definition: hgzip.cxx:278
#define TRYFREE(p)
Definition: hgzip.cxx:32
int gz_flush(gz_stream *file, int flush)
Flushes all pending output into the compressed file gz_flush should be called only when strictly nece...
Definition: hgzip.cxx:215
static int get_byte(gz_stream *s)
Definition: hgzip.cxx:98
#define ALLOC(size)
Definition: hgzip.cxx:31
static int destroy(gz_stream *s)
Definition: hgzip.cxx:123
static uLong getLong(gz_stream *s)
Definition: hgzip.cxx:259
size_t gz_read(gz_stream *file, voidp buf, unsigned len)
Reads the given number of uncompressed bytes from the compressed stream.
Definition: hgzip.cxx:151
err
Structure for using z_stream.
Definition: hgzip.h:30
z_stream stream
Definition: hgzip.h:31
char mode
'w' or 'r'
Definition: hgzip.h:59
int z_eof
EOF of the input file.
Definition: hgzip.h:39
Byte * inbuf
Input buffer.
Definition: hgzip.h:47
uLong crc
Crc32 of uncompressed data.
Definition: hgzip.h:51
HStream * _inputstream
Stream.
Definition: hgzip.h:43
int z_err
The error code of z_stream operation.
Definition: hgzip.h:35
char * msg
Stream.
Definition: hgzip.h:55