00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <u/libu.h>
00013 #include <klone/codec.h>
00014 #include <klone/cgzip.h>
00015 #include <klone/utils.h>
00016
00022 #include <zlib.h>
00023
00024 struct codec_gzip_s
00025 {
00026 codec_t codec;
00027 int action;
00028 int err;
00029 z_stream zstr;
00030 int (*op)(z_streamp, int);
00031 int (*opEnd)(z_streamp);
00032 char dummy;
00033 };
00034
00035 typedef struct codec_gzip_s codec_gzip_t;
00036
00037 static ssize_t gzip_flush(codec_t *codec, char *dst, size_t *dcount)
00038 {
00039 codec_gzip_t *iz;
00040
00041 dbg_return_if (codec == NULL, -1);
00042 dbg_return_if (dst == NULL, -1);
00043 dbg_return_if (dcount == NULL, -1);
00044
00045 iz = (codec_gzip_t*)codec;
00046
00047
00048 iz->zstr.next_in = (char*)0xDEADBEEF;
00049 iz->zstr.avail_in = 0;
00050
00051 #if !defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200
00052
00053
00054 if(iz->action == GZIP_UNCOMPRESS && iz->dummy == 0)
00055 {
00056 iz->zstr.next_in = &iz->dummy;
00057 iz->zstr.avail_in = 1;
00058 iz->dummy++;
00059 }
00060 #endif
00061
00062 iz->zstr.next_out = dst;
00063 iz->zstr.avail_out = *dcount;
00064
00065
00066 if(iz->err != Z_STREAM_END)
00067 {
00068 iz->err = iz->op(&iz->zstr,
00069 iz->action == GZIP_COMPRESS ? Z_FINISH : Z_NO_FLUSH);
00070 dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);
00071 }
00072
00073 *dcount = *dcount - iz->zstr.avail_out;
00074
00075 return iz->err == Z_STREAM_END && *dcount == 0 ?
00076 CODEC_FLUSH_COMPLETE : CODEC_FLUSH_CHUNK;
00077 err:
00078 dbg("%s", zError(iz->err));
00079 return -1;
00080 }
00081
00082 static ssize_t gzip_transform(codec_t *codec, char *dst, size_t *dcount,
00083 const char *src, size_t src_sz)
00084 {
00085 codec_gzip_t *iz;
00086 size_t consumed;
00087
00088 dbg_return_if (codec == NULL, -1);
00089 dbg_return_if (src == NULL, -1);
00090 dbg_return_if (dst == NULL, -1);
00091 dbg_return_if (dcount == NULL || *dcount == 0, -1);
00092 dbg_return_if (src_sz == 0, -1);
00093
00094 iz = (codec_gzip_t*)codec;
00095
00096 iz->zstr.next_out = dst;
00097 iz->zstr.avail_out = *dcount;
00098
00099 iz->zstr.next_in = src;
00100 iz->zstr.avail_in = src_sz;
00101
00102 iz->err = iz->op(&iz->zstr, Z_NO_FLUSH);
00103 dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);
00104
00105 consumed = src_sz - iz->zstr.avail_in;
00106 *dcount = *dcount - iz->zstr.avail_out;
00107
00108 return consumed;
00109 err:
00110 dbg("%s", zError(iz->err));
00111 return -1;
00112 }
00113
00114 static int gzip_free(codec_t *codec)
00115 {
00116 codec_gzip_t *iz;
00117 int err;
00118
00119 nop_return_if (codec == NULL, 0);
00120
00121 iz = (codec_gzip_t*)codec;
00122 dbg_err_if((err = iz->opEnd(&iz->zstr)) != Z_OK);
00123 U_FREE(iz);
00124
00125 return 0;
00126 err:
00127 dbg("%s", zError(err));
00128 return ~0;
00129 }
00130
00142 int codec_gzip_create(int op, codec_t **piz)
00143 {
00144 codec_gzip_t *iz = NULL;
00145
00146 dbg_return_if (piz == NULL, ~0);
00147
00148 iz = u_zalloc(sizeof(codec_gzip_t));
00149 dbg_err_if(iz == NULL);
00150
00151 iz->codec.transform = gzip_transform;
00152 iz->codec.flush = gzip_flush;
00153 iz->codec.free = gzip_free;
00154 iz->action = op;
00155
00156 switch(op)
00157 {
00158 case GZIP_COMPRESS:
00159 iz->op = deflate;
00160 iz->opEnd = deflateEnd;
00161 dbg_err_if(deflateInit2(&iz->zstr, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
00162 -MAX_WBITS, 8, Z_DEFAULT_STRATEGY));
00163 break;
00164 case GZIP_UNCOMPRESS:
00165 iz->op = inflate;
00166 iz->opEnd = inflateEnd;
00167 dbg_err_if(inflateInit2(&iz->zstr, -MAX_WBITS) != Z_OK);
00168 break;
00169 default:
00170 dbg_err_if("bad gzip op");
00171 }
00172
00173 *piz = (codec_t*)iz;
00174
00175 return 0;
00176 err:
00177 U_FREE(iz);
00178 return ~0;
00179 }
00180