Using the 'zlib' library to provide IO driver 'compress' functionality
|
|
Type: | Programming |
Rating: | 4 (medium-difficult) |
Description: | This example module uses the 'zlib' library (see: http://www.gzip.org) to provide the I/O driver 'compress' (e.g. "zlib.compress:model.bim") for stream compression and 'gzip' (e.g. "zlib.gzip:data.gz") for handling gzip files. Language extensions provided by this module:
|
File(s): | zlib.c |
|
zlib.c |
/****************************************** Mosel NI Examples ================= File zlib.c ``````````` Example module defining an IO driver for (un)compression using zlib library which can be found at http://www.zlib.org (c) 2008 Fair Isaac Corporation author: Y. Colombani, 2003 zlib: (c) 1995-2002 Jean-Loup Gailly and Mark Adler *******************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #define XPRM_NICOMPAT 3004002 /* Compatibility level: Mosel 3.4.2 */ #include "xprm_ni.h" #ifdef _WIN32 #define snprintf _snprintf #define _WINDOWS #define ZLIB_DLL /* for precompiled zlib 1.2.1 */ #define ZLIB_WINAPI #endif #include "zlib.h" #define BUFSIZE 1024 /* buffer size for data transfer */ /**************************************************/ /* gzip driver: to handle files using GZIP format */ /* Example: "zlib.gzip:mydata.gz" */ /**************************************************/ /* Functions of 'gzip' driver */ static void *gzip_open(XPRMcontext ctx,int *mode,const char *fname); static int gzip_close(XPRMcontext ctx,gzFile gzf,int mode); static long gzip_read(XPRMcontext ctx,gzFile gzf,void *buffer, unsigned long size); static long gzip_write(XPRMcontext ctx,gzFile gzf,void *buffer, unsigned long size); static void setgzerror(XPRMcontext ctx,gzFile gzf); static XPRMiofcttab iodrv_gzip[]= { {XPRM_IOCTRL_OPEN,gzip_open}, {XPRM_IOCTRL_CLOSE,gzip_close}, {XPRM_IOCTRL_READ,gzip_read}, {XPRM_IOCTRL_WRITE,gzip_write}, {XPRM_IOCTRL_INFO,"filename"}, {0,NULL} }; /*************************************************/ /* compress driver: to handle compressed streams */ /* As opposed to 'gzip' driver this driver does */ /* not require a physical file */ /* Note also that files produced by this driver */ /* are not compatible with gzip */ /* Example: "zlib.compress:mem:0x1234/256" */ /**************************************************/ /* Functions of 'compress' driver */ static void *comp_open(XPRMcontext ctx,int *mode,const char *fname); static int comp_close(XPRMcontext ctx,z_streamp zstr,int mode); static long comp_read(XPRMcontext ctx,z_streamp zstr,void *buffer, unsigned long size); static long comp_write(XPRMcontext ctx,z_streamp zstr,void *buffer, unsigned long size); static XPRMiofcttab iodrv_compress[]= { {XPRM_IOCTRL_OPEN,comp_open}, {XPRM_IOCTRL_CLOSE,comp_close}, {XPRM_IOCTRL_READ,comp_read}, {XPRM_IOCTRL_WRITE,comp_write}, {XPRM_IOCTRL_INFO,"extended_filename"}, {0,NULL} }; /* Drivers of zlib module: gzip,compress */ static XPRMiodrvtab iodrv_zlib[]= { {"gzip",iodrv_gzip}, {"compress",iodrv_compress}, {NULL,NULL} }; static int chkres(int); /* Table of services: only IO drivers */ static XPRMdsoserv tabserv[]= { {XPRM_SRV_IODRVS,iodrv_zlib}, {XPRM_SRV_CHKRES,(void*)chkres} }; /* DSO interface: only services */ static XPRMdsointer dsointer= { 0,NULL, 0,NULL, 0,NULL, sizeof(tabserv)/sizeof(mm_dsoserv),tabserv }; static XPRMnifct mm; /* For storing Mosel NI function table */ /************************************************/ /* Initialize the library just after loading it */ /************************************************/ DSO_INIT zlib_init(XPRMnifct nifct, int *interver,int *libver, XPRMdsointer **interf) { const char *zlv; mm=nifct; /* Save the table of Mosel NI functions */ *interver=XPRM_NIVERS; /* The interface version we are using */ /* We check ZLIB library version here */ zlv=zlibVersion(); if((zlv==NULL)||(zlv[0]!=ZLIB_VERSION[0])) { mm->dispmsg(NULL,"ZLIB: wrong version (expect %s got %s).\n",ZLIB_VERSION, (zlv!=NULL)?zlv:"0"); return 1; } else { *libver=XPRM_MKVER(0,0,2); /* The version of the module: 0.0.2 */ *interf=&dsointer; /* Our interface */ return 0; } } /****************************************************************/ /* Check restrictions (this module implements all restrictions) */ /****************************************************************/ static int chkres(int r) { return 0; } /****************************************/ /* Open a gzip-file for (de)compression */ /****************************************/ static void *gzip_open(XPRMcontext ctx,int *mode,const char *fname) { char cfname[MM_MAXPATHLEN]; char cmode[16]; int cml; void *gzf; if((fname==NULL)|| (mm->pathcheck(ctx,fname,cfname,MM_MAXPATHLEN, ((*mode)&MM_F_WRITE)?MM_RCHK_WRITE:MM_RCHK_READ)!=0)) { mm->setioerrmsg(ctx,strerror(EACCES),1); return NULL; } else { cml=2; cmode[0]=((*mode)&MM_F_WRITE)?'w':'r'; cmode[1]=((*mode)&MM_F_BINARY)?'b':'t'; if((*mode)&MM_F_APPEND) cmode[cml++]='a'; cmode[cml]='\0'; gzf=gzopen(cfname,cmode); if(gzf==NULL) mm->setioerrmsg(ctx,strerror(errno),2); return gzf; } } /***********************/ /* Close the gzip-file */ /***********************/ static int gzip_close(XPRMcontext ctx,gzFile gzf,int mode) { return gzclose(gzf); } /******************************/ /* Uncompress a block of data */ /******************************/ static long gzip_read(XPRMcontext ctx,gzFile gzf,void *buffer, unsigned long size) { long l; l=gzread(gzf,buffer,size); if(l<0) setgzerror(ctx,gzf); return l; } /****************************/ /* Compress a block of data */ /****************************/ static long gzip_write(XPRMcontext ctx,gzFile gzf,void *buffer, unsigned long size) { long l; l=gzwrite(gzf,buffer,size); if(l<=0) setgzerror(ctx,gzf); return l; } /*********************************/ /* Set message of the last error */ /*********************************/ static void setgzerror(XPRMcontext ctx,gzFile gzf) { int errnum; const char *emsg; if((((emsg=gzerror(gzf,&errnum))!=NULL)&&(errnum==Z_ERRNO))) { errnum=errno; emsg=strerror(errno); } if(errnum!=0) mm->setioerrmsg(ctx,emsg,errnum); } /*************************************/ /* Open a stream for (de)compression */ /*************************************/ static void *comp_open(XPRMcontext ctx,int *mode,const char *fname) { z_streamp zstr; int rts; /* 1st: open actual file */ if(mm->fopen(ctx,((*mode)&XPRM_F_WRITE)|XPRM_F_BINARY,fname)<0) { *mode|=XPRM_F_SILENT; /* Error message already displayed */ /* switch so silent mode */ return NULL; } else { /* If OK, prepare data structures for zlib */ /* Allocate memory for zstream and a buffer */ if((zstr=(z_streamp)malloc(sizeof(z_stream)+BUFSIZE))==NULL) { mm->fclose(ctx,(*mode)&(XPRM_F_READ|XPRM_F_WRITE)); mm->setioerrmsg(ctx,"Not enough memory",1); return NULL; } memset(zstr,0,sizeof(z_stream)); zstr->zalloc=Z_NULL; zstr->zfree=Z_NULL; if(((*mode)&(XPRM_F_READ|XPRM_F_WRITE))==XPRM_F_READ) { /* For reading: 'inflate' algorithm */ rts=inflateInit(zstr); zstr->next_in=(void *)(zstr+1); /* Buffer is after zstream */ } else { /* For writing: 'deflate' algorithm */ rts=deflateInit(zstr,Z_DEFAULT_COMPRESSION); zstr->next_out=(void *)(zstr+1); /* Buffer is after zstream */ zstr->avail_out=BUFSIZE; } if(rts!=Z_OK) { mm->setioerrmsg(ctx,zstr->msg,rts); free(zstr); mm->fclose(ctx,(*mode)&(XPRM_F_READ|XPRM_F_WRITE)); return NULL; } else return zstr; } } /********************/ /* Close the stream */ /********************/ static int comp_close(XPRMcontext ctx,z_stream *zstr,int mode) { int rts1,rts2; Bytef dummy; if((mode&(XPRM_F_READ|XPRM_F_WRITE))==XPRM_F_READ) { /* If reading: just release zstream */ rts1=inflateEnd(zstr); } else { /* If writing: buffers have to be flushed first */ zstr->next_in=&dummy; zstr->avail_in=0; if(zstr->avail_out==0) { mm->fwrite(ctx,zstr+1,BUFSIZE); zstr->next_out=(void *)(zstr+1); zstr->avail_out=BUFSIZE; } do { rts1=deflate(zstr,Z_FINISH); if(BUFSIZE-zstr->avail_out>0) mm->fwrite(ctx,zstr+1,BUFSIZE-zstr->avail_out); zstr->next_out=(void *)(zstr+1); zstr->avail_out=BUFSIZE; } while(rts1==Z_OK); rts1=deflateEnd(zstr); } /* Finally close actual file and release memory */ rts2=mm->fclose(ctx,mode); if(rts1!=Z_OK) mm->setioerrmsg(ctx,zstr->msg,rts1); free(zstr); return (rts1!=Z_OK)||(rts2!=0); } /******************************/ /* Uncompress a block of data */ /******************************/ static long comp_read(XPRMcontext ctx,z_stream *zstr,void *buffer, unsigned long size) { int rts,finish; zstr->next_out=buffer; zstr->avail_out=size; finish=0; do { if(zstr->avail_in==0) { zstr->avail_in=mm->fread(ctx,zstr+1,BUFSIZE); zstr->next_in=(void *)(zstr+1); finish=(zstr->avail_in==0); } rts=inflate(zstr,Z_NO_FLUSH); } while((rts==Z_OK)&&(zstr->avail_out>0) && !finish); if(finish && (zstr->avail_out>0)) rts=inflate(zstr,Z_SYNC_FLUSH); if((rts==Z_OK)||(rts==Z_STREAM_END)) return (long)(size-zstr->avail_out); else { mm->setioerrmsg(ctx,zstr->msg,rts); return -1; } } /****************************/ /* Compress a block of data */ /****************************/ static long comp_write(XPRMcontext ctx,z_stream *zstr,void *buffer, unsigned long size) { int rts; zstr->next_in=buffer; zstr->avail_in=size; do { if(zstr->avail_out==0) { mm->fwrite(ctx,zstr+1,BUFSIZE); zstr->next_out=(void *)(zstr+1); zstr->avail_out=BUFSIZE; } rts=deflate(zstr,Z_NO_FLUSH); } while((rts==Z_OK)&&(zstr->avail_in>0)); if(rts==Z_OK) return 1; else { mm->setioerrmsg(ctx,zstr->msg,rts); return 0; } } |
© 2001-2024 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.