Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

gzip.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: gzip.c,v 1.23 2006/01/09 12:38:38 tat Exp $
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;              /* parent structure block           */
00027     int action;                 /* GZIP_COMPRESS or GZIP_UNCOMPRESS */
00028     int err;                    /* last error code                  */
00029     z_stream zstr;              /* zlib internal structure          */
00030     int (*op)(z_streamp, int);  /* inflate or deflate               */
00031     int (*opEnd)(z_streamp);    /* inflateEnd or deflateEnd         */
00032     char dummy;                 /* ZLIB < 1.2 workaround dummy byte */
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     /* can't set it to NULL even if zlib must not use it (avail_in == 0) */
00048     iz->zstr.next_in = (char*)0xDEADBEEF;
00049     iz->zstr.avail_in = 0;
00050 
00051 #if !defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200
00052     /* zlib < 1.2.0 workaround: push a dummy byte at the end of the 
00053        stream when inflating (see zlib ChangeLog) */
00054     if(iz->action == GZIP_UNCOMPRESS && iz->dummy == 0)
00055     { 
00056         iz->zstr.next_in = &iz->dummy; /* dummy byte */
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     /* should be Z_STREAM_END while uncompressing */
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;   /* written */
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;  /* consumed */
00106     *dcount = *dcount - iz->zstr.avail_out; /* written */
00107 
00108     return consumed; /* # of consumed input bytes */
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 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved