2
* Zlib-enabled input and output streams
4
* This is a thin wrapper of libz calls, in order
5
* to provide a simple interface to our developers
6
* for gzip input and output.
9
* Bob Jamison <rjamison@titan.com>
11
* Copyright (C) 2004 Inkscape.org
13
* Released under GNU GPL, read the file 'COPYING' for more information
16
#include "gzipstream.h"
26
//#########################################################################
27
//# G Z I P I N P U T S T R E A M
28
//#########################################################################
35
GzipInputStream::GzipInputStream(InputStream &sourceStream)
36
: BasicInputStream(sourceStream),
49
memset( &d_stream, 0, sizeof(d_stream) );
55
GzipInputStream::~GzipInputStream()
69
* Returns the number of bytes that can be read (or skipped over) from
70
* this input stream without blocking by the next caller of a method for
73
int GzipInputStream::available()
75
if (closed || !outputBuf)
77
return outputBufLen - outputBufPos;
82
* Closes this input stream and releases any system resources
83
* associated with the stream.
85
void GzipInputStream::close()
90
int zerr = inflateEnd(&d_stream);
92
printf("inflateEnd: Some kind of problem: %d\n", zerr);
107
* Reads the next byte of data from the input stream. -1 if EOF
109
int GzipInputStream::get()
113
// leave return value -1
115
else if (!loaded && !load()) {
121
if ( outputBufPos >= outputBufLen ) {
122
// time to read more, if we can
126
if ( outputBufPos < outputBufLen ) {
127
ch = (int)outputBuf[outputBufPos++];
138
#define FCOMMENT 0x10
140
bool GzipInputStream::load()
142
crc = crc32(0L, Z_NULL, 0);
144
std::vector<Byte> inputBuf;
147
int ch = source.get();
150
inputBuf.push_back((Byte)(ch & 0xff));
152
long inputBufLen = inputBuf.size();
154
if (inputBufLen < 19) //header + tail + 1
159
srcLen = inputBuf.size();
160
srcBuf = (Bytef *)malloc(srcLen * sizeof(Byte));
165
outputBuf = (unsigned char *)malloc(OUT_SIZE);
171
outputBufLen = 0; // Not filled in yet
173
std::vector<unsigned char>::iterator iter;
175
for (iter=inputBuf.begin() ; iter != inputBuf.end() ; iter++)
181
int val = (int)srcBuf[0];
182
//printf("val:%x\n", val);
183
val = (int)srcBuf[1];
184
//printf("val:%x\n", val);
187
val = (int)srcBuf[2];
188
//printf("val:%x\n", val);
191
int flags = (int)srcBuf[3];
194
val = (int)srcBuf[4];
195
val = (int)srcBuf[5];
196
val = (int)srcBuf[6];
197
val = (int)srcBuf[7];
200
val = (int)srcBuf[8];
202
val = (int)srcBuf[9];
205
// if ( flags & FEXTRA ) {
208
// TODO deal with optional header parts
210
if ( flags & FNAME ) {
211
while ( srcBuf[cur] )
220
srcCrc = ((0x0ff & srcBuf[srcLen - 5]) << 24)
221
| ((0x0ff & srcBuf[srcLen - 6]) << 16)
222
| ((0x0ff & srcBuf[srcLen - 7]) << 8)
223
| ((0x0ff & srcBuf[srcLen - 8]) << 0);
224
//printf("srcCrc:%lx\n", srcCrc);
226
srcSiz = ((0x0ff & srcBuf[srcLen - 1]) << 24)
227
| ((0x0ff & srcBuf[srcLen - 2]) << 16)
228
| ((0x0ff & srcBuf[srcLen - 3]) << 8)
229
| ((0x0ff & srcBuf[srcLen - 4]) << 0);
230
//printf("srcSiz:%lx/%ld\n", srcSiz, srcSiz);
236
//outputBufLen = srcSiz + srcSiz/100 + 14;
238
unsigned char *data = srcBuf + headerLen;
239
unsigned long dataLen = srcLen - (headerLen + 8);
240
//printf("%x %x\n", data[0], data[dataLen-1]);
242
d_stream.zalloc = (alloc_func)0;
243
d_stream.zfree = (free_func)0;
244
d_stream.opaque = (voidpf)0;
245
d_stream.next_in = data;
246
d_stream.avail_in = dataLen;
247
d_stream.next_out = outputBuf;
248
d_stream.avail_out = OUT_SIZE;
250
int zerr = inflateInit2(&d_stream, -MAX_WBITS);
255
printf("inflateInit2: Some kind of problem: %d\n", zerr);
259
return (zerr == Z_OK) || (zerr == Z_STREAM_END);
263
int GzipInputStream::fetchMore()
267
// TODO assumes we aren't called till the buffer is empty
268
d_stream.next_out = outputBuf;
269
d_stream.avail_out = OUT_SIZE;
273
zerr = inflate( &d_stream, Z_SYNC_FLUSH );
274
if ( zerr == Z_OK || zerr == Z_STREAM_END ) {
275
outputBufLen = OUT_SIZE - d_stream.avail_out;
276
if ( outputBufLen ) {
277
crc = crc32(crc, (const Bytef *)outputBuf, outputBufLen);
279
//printf("crc:%lx\n", crc);
280
// } else if ( zerr != Z_STREAM_END ) {
281
// // TODO check to be sure this won't happen for partial end reads
282
// printf("inflate: Some kind of problem: %d\n", zerr);
288
//#########################################################################
289
//# G Z I P O U T P U T S T R E A M
290
//#########################################################################
295
GzipOutputStream::GzipOutputStream(OutputStream &destinationStream)
296
: BasicOutputStream(destinationStream)
301
crc = crc32(0L, Z_NULL, 0);
304
destination.put(0x1f);
305
destination.put(0x8b);
307
//Say it is compressed
308
destination.put(Z_DEFLATED);
322
//OS code - from zutil.h
323
//destination.put(OS_CODE);
324
//apparently, we should not explicitly include zutil.h
332
GzipOutputStream::~GzipOutputStream()
338
* Closes this output stream and releases any system resources
339
* associated with this stream.
341
void GzipOutputStream::close()
350
for (int n = 0; n < 4; n++)
352
destination.put((int)(outlong & 0xff));
355
//# send the file length
356
outlong = totalIn & 0xffffffffL;
357
for (int n = 0; n < 4; n++)
359
destination.put((int)(outlong & 0xff));
368
* Flushes this output stream and forces any buffered output
369
* bytes to be written out.
371
void GzipOutputStream::flush()
373
if (closed || inputBuf.size()<1)
376
uLong srclen = inputBuf.size();
377
Bytef *srcbuf = (Bytef *)malloc(srclen * sizeof(Byte));
383
uLong destlen = srclen;
384
Bytef *destbuf = (Bytef *)malloc((destlen + (srclen/100) + 13) * sizeof(Byte));
391
std::vector<unsigned char>::iterator iter;
393
for (iter=inputBuf.begin() ; iter != inputBuf.end() ; iter++)
396
crc = crc32(crc, (const Bytef *)srcbuf, srclen);
398
int zerr = compress(destbuf, (uLongf *)&destlen, srcbuf, srclen);
401
printf("Some kind of problem\n");
405
//skip the redundant zlib header and checksum
406
for (uLong i=2; i<destlen-4 ; i++)
408
destination.put((int)destbuf[i]);
424
* Writes the specified byte to this output stream.
426
void GzipOutputStream::put(int ch)
430
//probably throw an exception here
436
inputBuf.push_back(ch);
444
} // namespace Inkscape
447
//#########################################################################
448
//# E N D O F F I L E
449
//#########################################################################
454
c-file-style:"stroustrup"
455
c-file-offsets:((innamespace . 0)(inline-open . 0))
460
// vim: expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :