gzip.c
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
00017 #include <zlib.h>
00018
00019 struct codec_gzip_s
00020 {
00021 codec_t codec;
00022 int action;
00023 int err;
00024 z_stream zstr;
00025 int (*op)(z_streamp, int);
00026 int (*opEnd)(z_streamp);
00027 char dummy;
00028 };
00029
00030 typedef struct codec_gzip_s codec_gzip_t;
00031
00032 static ssize_t gzip_flush(codec_t *codec, char *dst, size_t *dcount)
00033 {
00034 codec_gzip_t *iz;
00035
00036 dbg_return_if (codec == NULL, -1);
00037 dbg_return_if (dst == NULL, -1);
00038 dbg_return_if (dcount == NULL, -1);
00039
00040 iz = (codec_gzip_t*)codec;
00041
00042
00043 iz->zstr.next_in = (char*)0xDEADBEEF;
00044 iz->zstr.avail_in = 0;
00045
00046 #if !defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200
00047
00048
00049 if(iz->action == GZIP_UNCOMPRESS && iz->dummy == 0)
00050 {
00051 iz->zstr.next_in = &iz->dummy;
00052 iz->zstr.avail_in = 1;
00053 iz->dummy++;
00054 }
00055 #endif
00056
00057 iz->zstr.next_out = dst;
00058 iz->zstr.avail_out = *dcount;
00059
00060
00061 if(iz->err != Z_STREAM_END)
00062 {
00063 iz->err = iz->op(&iz->zstr,
00064 iz->action == GZIP_COMPRESS ? Z_FINISH : Z_NO_FLUSH);
00065 dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);
00066 }
00067
00068 *dcount = *dcount - iz->zstr.avail_out;
00069
00070 return iz->err == Z_STREAM_END && *dcount == 0 ?
00071 CODEC_FLUSH_COMPLETE : CODEC_FLUSH_CHUNK;
00072 err:
00073 u_dbg("%s", zError(iz->err));
00074 return -1;
00075 }
00076
00077 static ssize_t gzip_transform(codec_t *codec, char *dst, size_t *dcount,
00078 const char *src, size_t src_sz)
00079 {
00080 codec_gzip_t *iz;
00081 size_t consumed;
00082
00083 dbg_return_if (codec == NULL, -1);
00084 dbg_return_if (src == NULL, -1);
00085 dbg_return_if (dst == NULL, -1);
00086 dbg_return_if (dcount == NULL || *dcount == 0, -1);
00087 dbg_return_if (src_sz == 0, -1);
00088
00089 iz = (codec_gzip_t*)codec;
00090
00091 iz->zstr.next_out = dst;
00092 iz->zstr.avail_out = *dcount;
00093
00094 iz->zstr.next_in = (char*)src;
00095 iz->zstr.avail_in = src_sz;
00096
00097 iz->err = iz->op(&iz->zstr, Z_NO_FLUSH);
00098 dbg_err_if(iz->err != Z_OK && iz->err != Z_STREAM_END);
00099
00100 consumed = src_sz - iz->zstr.avail_in;
00101 *dcount = *dcount - iz->zstr.avail_out;
00102
00103 return consumed;
00104 err:
00105 u_dbg("%s", zError(iz->err));
00106 return -1;
00107 }
00108
00109 static int gzip_free(codec_t *codec)
00110 {
00111 codec_gzip_t *iz;
00112 int err;
00113
00114 nop_return_if (codec == NULL, 0);
00115
00116 iz = (codec_gzip_t*)codec;
00117 dbg_err_if((err = iz->opEnd(&iz->zstr)) != Z_OK);
00118 U_FREE(iz);
00119
00120 return 0;
00121 err:
00122 u_dbg("%s", zError(err));
00123 return ~0;
00124 }
00125
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