FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Using the 'zlib' library to provide IO driver 'compress' functionality

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:
  • service: 2 I/O drivers
Further explanation of this example: Whitepaper 'Generalized file handling in Mosel', Section 8.1 Example: compression


Source Files





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;
 }
}


Back to examples browserPrevious exampleNext example