/* xpkGZIP.c -- using zlib by Jean-loup Gailly and Mark Adler * Copyright (C) 1996-2000 authors * This file is part of the xpk package. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ /* Written by Gunther Nikl * UNIX version by Vesa Halttunen */ #include #include #include #include /* common constants from zutil.h */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ /* * a shortcut */ typedef struct XpkSubParams XPAR; /* * required information structures */ #define GZIPMODE(x) (struct XpkMode *)(GZIPModes+x) static const struct XpkMode GZIPModes[] = { { GZIPMODE(1), 9, 0, 0, 0, 1607, 4575, 0, 0, "store" }, { GZIPMODE(2), 19, 0, 0, 0, 269, 1451, 468, 0, "laziest" }, { GZIPMODE(3), 29, 0, 0, 0, 245, 1451, 473, 0, "lazier" }, { GZIPMODE(4), 39, 0, 0, 0, 198, 1451, 474, 0, "lazy" }, { GZIPMODE(5), 49, 0, 0, 0, 175, 1487, 486, 0, "calm" }, { GZIPMODE(6), 59, 0, 0, 0, 137, 1525, 493, 0, "average" }, { GZIPMODE(7), 69, 0, 0, 0, 98, 1525, 496, 0, "willing" }, { GZIPMODE(8), 79, 0, 0, 0, 86, 1525, 497, 0, "greedy" }, { GZIPMODE(9), 89, 0, 0, 0, 62, 1525, 497, 0, "greedier" }, { NULL, 100, 0, 0, 0, 52, 1525, 497, 0, "greediest" } }; static const struct XpkInfo GZIPInfo = { 1, /* info version */ 1, /* lib version */ 0, /* master vers */ // 2, /* master vers */ 0, /* pad */ "GZIP", /* short name */ "GZIP Version 1.1", /* long name */ "LZ77 class packer with hashing and dynamic Huffman coding", /* description */ 0x475A4950, /* 4 letter ID */ XPKIF_PK_CHUNK | /* flags */ XPKIF_UP_CHUNK | XPKIF_MODES, 16*1024*1024, /* max in chunk */ 0, /* min in chunk */ 256*1024, /* def in chunk */ "deflating", /* pk message */ "inflating", /* up message */ "deflated", /* pk past msg */ "inflated", /* up past msg */ 65, /* def mode */ 0, /* pad */ GZIPMODE(0), /* modes */ {0,} /* reserved */ }; z_streamp ZStream; /* * return an info structure about our packer */ const struct XpkInfo *LIBXpksPackerInfo(void) { return &GZIPInfo; } /* * utility functions for ZLIB */ static void zcFree(voidpf opaque, voidpf ptr) { /* struct XpkSubParams *xpar = (struct XpkSubParams *)opaque; */ if (ptr) free(ptr-sizeof(unsigned int)); } static voidpf zcAlloc(voidpf opaque,unsigned items,unsigned itemsize) { /* struct XpkSubParams *xpar = (struct XpkSubParams *)opaque; */ unsigned int size, *mem; if ((mem=(unsigned int *)calloc(size=sizeof(*mem)+items*itemsize, 1))) *mem++ = size; return mem; } /* * initialize a z_stream (either for compression or decompression) */ static z_streamp init_stream(struct XpkSubParams *xpar) { z_streamp stream = ZStream; for(;;) { if (!stream) { if ((ZStream=stream=zcAlloc(xpar,1,sizeof(*stream))) == NULL) break; stream->zalloc = zcAlloc; stream->zfree = zcFree; stream->opaque = xpar; } stream->next_in = (Bytef *)xpar->xsp_InBuf; stream->avail_in = (uInt )xpar->xsp_InLen; stream->next_out = (Bytef *)xpar->xsp_OutBuf; stream->avail_out = (uInt )xpar->xsp_OutBufLen; break; } return stream; } /* * kill a z_stream */ static void free_stream(struct XpkSubParams *xpar, z_streamp stream) { zcFree(xpar, stream); } /* * compress a chunk of memory */ int LIBXpksPackChunk(struct XpkSubParams *xpar) { int level, err = XPKERR_NOMEM; z_streamp stream; if ((stream=init_stream(xpar))) { if ((level=xpar->xsp_Mode/10) != 10) { if (level < Z_NO_COMPRESSION || level > Z_BEST_COMPRESSION) level = Z_DEFAULT_COMPRESSION; } else level = Z_BEST_COMPRESSION; if (deflateInit2(stream,level,Z_DEFLATED,DEF_WBITS,DEF_MEM_LEVEL,Z_DEFAULT_STRATEGY) == Z_OK) { if (deflate(stream,Z_FINISH) == Z_STREAM_END) { xpar->xsp_OutLen = stream->total_out; err = XPKERR_OK; } else err = XPKERR_UNKNOWN; deflateEnd(stream); } free_stream(xpar, stream); } return err; } /* * restore state information after a XPKERR_EXPANSION */ int LIBXpksPackReset(struct XpkSubParams *xpar) { int err; if (!ZStream || (err=deflateReset(ZStream))!=Z_OK) err = XPKERR_UNKNOWN; else err = XPKERR_OK; return err; } /* * uncompress a chunk of memory */ int LIBXpksUnpackChunk(struct XpkSubParams *xpar) { int err = XPKERR_NOMEM; z_streamp stream; if ((stream=init_stream(xpar))) { if (inflateInit2(stream,DEF_WBITS) == Z_OK) { if (inflate(stream,Z_FINISH) == Z_STREAM_END) { xpar->xsp_OutLen = stream->total_out; err = XPKERR_OK; } else err = XPKERR_UNKNOWN; inflateEnd(stream); } } return err; }