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

Definition of type 'date' and subroutines for accessing it

Description
Language extensions provided by this module:
  • constants: boolean
  • type: system
  • subroutines: procedures and functions
  • operators: constructor, assignment, comparators
  • services: reset, accessing and enumerating parameters
  • parameter: boolean


Source Files

Data Files





date.c

/******************************************
  Mosel NI Examples
  =================

  File date.c
  ```````````
  Example module defining a new type
    date
  with functions for accessing it and a
  control parameter for the style.

  (c) 2008 Fair Isaac Corporation
      author: Y. Colombani, 2002
*******************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "xprm_ni.h"

#ifdef _WIN32
#define snprintf _snprintf
#endif

#define NDTL 20               /* Number of dates to allocate at once */

/**** Function prototypes ****/
static int dt_getpar(XPRMcontext ctx,void *libctx);
static int dt_setpar(XPRMcontext ctx,void *libctx);
static int dt_new0(XPRMcontext ctx,void *libctx);
static int dt_asgn(XPRMcontext ctx,void *libctx);
static int dt_eql(XPRMcontext ctx,void *libctx);
static int dt_less(XPRMcontext ctx,void *libctx);
static int dt_leq(XPRMcontext ctx,void *libctx);
static int dt_gettoday(XPRMcontext ctx,void *libctx);
static int dt_getyear(XPRMcontext ctx,void *libctx);
static int dt_getmonth(XPRMcontext ctx,void *libctx);
static int dt_getday(XPRMcontext ctx,void *libctx);
static int dt_gethour(XPRMcontext ctx,void *libctx);
static int dt_getminute(XPRMcontext ctx,void *libctx);
static int dt_getsecond(XPRMcontext ctx,void *libctx);
static void *dt_create(XPRMcontext ctx,void *,void *,int);
static void dt_delete(XPRMcontext ctx,void *,void *,int);
static int dt_tostr(XPRMcontext ctx,void *,void *,char *,int,int);
static int dt_fromstr(XPRMcontext ctx,void *libctx,void *toinit,const char *str,int,const char **endp);
static int dt_copy(XPRMcontext ctx,void *libctx,void *toinit,void *src,int typnum);
static void *dt_reset(XPRMcontext ctx,void *libctx,int version);
static int dt_findparm(const char *name,int *type);
static void *dt_nextparm(void *ref,const char **name,const char **desc,
                                                                    int *type);
/**** Structures for passing info to Mosel ****/
/* Constants */
static XPRMdsoconst tabconst[]=
        {
         XPRM_CST_BOOL("DATE_EU",XPRM_TRUE),XPRM_CST_BOOL("DATE_US",XPRM_FALSE)
        };

/* Subroutines */
static XPRMdsofct tabfct[]=
        { /* Implementing Mosel subroutines get/setparam for this module: */
         {"",XPRM_FCT_GETPAR,XPRM_TYP_NOT,0,NULL,dt_getpar},
         {"",XPRM_FCT_SETPAR,XPRM_TYP_NOT,0,NULL,dt_setpar},
  /* Operators: */
         {"@&",1000,XPRM_TYP_EXTN,1,"date:|date|",dt_new0},
         {"@:",1001,XPRM_TYP_NOT,2,"|date||date|",dt_asgn},
         {"@=",1002,XPRM_TYP_BOOL,2,"|date||date|",dt_eql},
         {"@<",1003,XPRM_TYP_BOOL,2,"|date||date|",dt_less},
         {"@l",1004,XPRM_TYP_BOOL,2,"|date||date|",dt_leq},
  /* Functions for accessing date info: */
         {"getdatenow",1005,XPRM_TYP_EXTN,0,"date:",dt_gettoday},
         {"getyear",1006,XPRM_TYP_INT,1,"|date|",dt_getyear},
         {"getmonth",1007,XPRM_TYP_INT,1,"|date|",dt_getmonth},
         {"getday",1008,XPRM_TYP_INT,1,"|date|",dt_getday},
         {"gethour",1009,XPRM_TYP_INT,1,"|date|",dt_gethour},
         {"getminute",1010,XPRM_TYP_INT,1,"|date|",dt_getminute},
         {"getsecond",1011,XPRM_TYP_INT,1,"|date|",dt_getsecond}
        };

/* Types */
static XPRMdsotyp tabtyp[]=
        {
         {"date",1,XPRM_DTYP_PNCTX,dt_create,dt_delete,dt_tostr,dt_fromstr,dt_copy}
        };

/* Services */
static XPRMdsoserv tabserv[]=
        {
         {XPRM_SRV_RESET,(void *)dt_reset},
         {XPRM_SRV_PARAM,(void *)dt_findparm},
         {XPRM_SRV_PARLST,(void *)dt_nextparm}
        };

/* Interface structure */
static XPRMdsointer dsointer= 
        { 
         sizeof(tabconst)/sizeof(XPRMdsoconst),tabconst,
         sizeof(tabfct)/sizeof(XPRMdsofct),tabfct,
         sizeof(tabtyp)/sizeof(XPRMdsotyp),tabtyp,
         sizeof(tabserv)/sizeof(XPRMdsoserv),tabserv
        };

/**** Structures used by this module ****/
static XPRMnifct mm;             /* To store the Mosel NI function table */

typedef struct tm s_date;       /* A date */

typedef union Freelist          /* List of allocated but not used dates */
        {
         s_date dt;
         union Freelist *next;
        } u_freelist;
        
typedef struct Nmlist           /* A block of memory */
        {
         s_date list[NDTL];
         int nextfree;
         struct Nmlist *next;
        } s_nmlist;

typedef struct                  /* A context for this module */
        {
         u_freelist *freelist;
         s_nmlist *nmlist;
         int in_eu;             /* Date style (EU/US) */
        } s_dtctx;


/************************************************/
/* Initialize the library just after loading it */
/************************************************/
DSO_INIT date_init(XPRMnifct nifct, int *interver,int *libver, XPRMdsointer **interf)
{
 mm=nifct;                      /* Save the table of Mosel NI functions */
 *interver=XPRM_NIVERS;         /* The Mosel NI version we are using */
 *libver=XPRM_MKVER(0,0,1);     /* The version of the module: 0.0.1 */
 *interf=&dsointer;             /* Our interface */

 return 0;
}

/******** Functions implementing subroutines and operators ********/

/****************************/
/* Read a control parameter */
/****************************/
static int dt_getpar(XPRMcontext ctx,void *libctx)
{
 s_dtctx *dtctx;
 int n;

 n=XPRM_POP_INT(ctx);
 if(n!=0) return XPRM_RT_ERROR;
 else
 {
  dtctx=libctx;
  XPRM_PUSH_INT(ctx,dtctx->in_eu);
  return XPRM_RT_OK;
 }
}

/***************************/
/* Set a control parameter */
/***************************/
static int dt_setpar(XPRMcontext ctx,void *libctx)
{
 s_dtctx *dtctx;
 int n;

 n=XPRM_POP_INT(ctx);
 if(n!=0) return XPRM_RT_ERROR;
 else
 {
  dtctx=libctx;
  dtctx->in_eu=XPRM_POP_INT(ctx);
  return XPRM_RT_OK;
 }
}

/****************/
/* Clone a date */
/****************/
static int dt_new0(XPRMcontext ctx,void *libctx)
{
 s_date *date,*new_date;

 date=XPRM_POP_REF(ctx);
 if(date!=NULL)
 {
  new_date=dt_create(ctx,libctx,NULL,0);
  *new_date=*date;
  XPRM_PUSH_REF(ctx,new_date);
 }
 else
  XPRM_PUSH_REF(ctx,NULL);
 return XPRM_RT_OK;
}

/*************************/
/* Assignment date:=date */
/*************************/
static int dt_asgn(XPRMcontext ctx,void *libctx)
{
 s_date *d1,*d2;

 d1=XPRM_POP_REF(ctx);
 d2=XPRM_POP_REF(ctx);
 *d1=*d2;
 dt_delete(ctx,libctx,d2,0);
 return XPRM_RT_OK;
}

/************************/
/* Comparison date=date */
/************************/
static int dt_eql(XPRMcontext ctx,void *libctx)
{
 s_date *d1,*d2;
 int b;

 d1=XPRM_POP_REF(ctx);
 d2=XPRM_POP_REF(ctx);
 if(d1!=NULL)
 {
  if(d2!=NULL)
   b=memcmp(d1,d2,sizeof(s_date))==0;
  else
   b=0;
 }
 else
  b=(d2==NULL);
 XPRM_PUSH_INT(ctx,b);
 return XPRM_RT_OK;
}

/************************/
/* Comparison date<date */
/************************/
static int dt_less(XPRMcontext ctx,void *libctx)
{
 s_date *d1,*d2;
 int b;

 d1=XPRM_POP_REF(ctx);
 d2=XPRM_POP_REF(ctx);
 if(d1!=NULL)
 {
  if(d2!=NULL)
   b=mktime(d1)<mktime(d2);
  else
   b=0;
 }
 else
  b=(d2==NULL);
 XPRM_PUSH_INT(ctx,b);
 return XPRM_RT_OK;
}

/*************************/
/* Comparison date<=date */
/*************************/
static int dt_leq(XPRMcontext ctx,void *libctx)
{
 s_date *d1,*d2;
 int b;

 d1=XPRM_POP_REF(ctx);
 d2=XPRM_POP_REF(ctx);
 if(d1!=NULL)
 {
  if(d2!=NULL)
   b=mktime(d1)<=mktime(d2);
  else
   b=0;
 }
 else
  b=(d2==NULL);
 XPRM_PUSH_INT(ctx,b);
 return XPRM_RT_OK;
}

/************************/
/* Get the current date */
/************************/
static int dt_gettoday(XPRMcontext ctx,void *libctx)
{
 s_date *d,*ds;
 time_t t;

 d=dt_create(ctx,libctx,NULL,0);
 t=time(NULL);
 ds=localtime(&t);
 *d=*ds;
 XPRM_PUSH_REF(ctx,d);
 return XPRM_RT_OK;
}

/****************************/
/* Get the year from a date */
/****************************/
static int dt_getyear(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_year+1900);
 else
  XPRM_PUSH_INT(ctx,1900);
 return XPRM_RT_OK;
}

/*****************************/
/* Get the month from a date */
/*****************************/
static int dt_getmonth(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_mon+1);
 else
  XPRM_PUSH_INT(ctx,1);
 return XPRM_RT_OK;
}

/***************************/
/* Get the day from a date */
/***************************/
static int dt_getday(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_mday);
 else
  XPRM_PUSH_INT(ctx,1);
 return XPRM_RT_OK;
}

/****************************/
/* Get the hour from a date */
/****************************/
static int dt_gethour(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_hour);
 else
  XPRM_PUSH_INT(ctx,0);
 return XPRM_RT_OK;
}

/******************************/
/* Get the minute from a date */
/******************************/
static int dt_getminute(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_min);
 else
  XPRM_PUSH_INT(ctx,0);
 return XPRM_RT_OK;
}

/******************************/
/* Get the second from a date */
/******************************/
static int dt_getsecond(XPRMcontext ctx,void *libctx)
{
 s_date *d;

 d=XPRM_POP_REF(ctx);
 if(d!=NULL)
  XPRM_PUSH_INT(ctx,d->tm_sec);
 else
  XPRM_PUSH_INT(ctx,0);
 return XPRM_RT_OK;
}

/***************/
/* Copy a date */
/***************/
static int dt_copy(XPRMcontext ctx,void *libctx,void *toinit,void *src,int typnum)
{
 s_date *dst;

 dst=(s_date *)toinit;
 if(src!=NULL)
  *dst=*(s_date *)src;
 else
  memset(dst,0,sizeof(s_date));
 return 0;
}

/**************** Type-related functions ****************/

/*******************/
/* Allocate a date */
/*******************/
static void *dt_create(XPRMcontext ctx,void *libctx,void *todup,int typnum)
{
 s_dtctx *dtctx;
 s_date *date;
 s_nmlist *nmlist;

 dtctx=libctx;
 if(dtctx->freelist!=NULL)              /* We have got some free date */
 {
  date=&(dtctx->freelist->dt);
  dtctx->freelist=dtctx->freelist->next;
 }
 else                                   /* We must allocate a new block */
  if((dtctx->nmlist==NULL)||(dtctx->nmlist->nextfree>=NDTL))
  {
   nmlist=malloc(sizeof(s_nmlist));
   nmlist->next=dtctx->nmlist;
   dtctx->nmlist=nmlist;
   nmlist->nextfree=1;
   date=nmlist->list;
  }
  else                                  /* We can take one from the block */
   date=&(dtctx->nmlist->list[dtctx->nmlist->nextfree++]);
 memset(date,0,sizeof(s_date));
 return date;
}

/*********************/
/* Deallocate a date */
/*********************/
static void dt_delete(XPRMcontext ctx,void *libctx,void *todel,int typnum)
{
 s_dtctx *dtctx;
 u_freelist *freelist;

 if(todel!=NULL)
 {
  dtctx=libctx;
  freelist=todel;
  freelist->next=dtctx->freelist;
  dtctx->freelist=freelist;
 }
}

/******************/
/* Date -> String */
/******************/
static int dt_tostr(XPRMcontext ctx,void *libctx,void *toprt,char *str,int len,int typnum)
{
 s_dtctx *dtctx;
 s_date *d;

 if(toprt==NULL)
 {
  strncpy(str,"1/1/1900 00:00:00",len);
  return 17;
 }
 else
 {
  dtctx=libctx;
  d=toprt;
  if(dtctx->in_eu)
   return snprintf(str,len,"%d/%d/%d %02d:%02d:%02d",d->tm_mday,d->tm_mon+1,
                 d->tm_year+1900,d->tm_hour,d->tm_min,d->tm_sec);
  else
   return snprintf(str,len,"%d/%d/%d %02d:%02d:%02d",d->tm_mon+1,d->tm_mday,
                 d->tm_year+1900,d->tm_hour,d->tm_min,d->tm_sec);
 }
}

/******************/
/* String -> Date */
/******************/
static int dt_fromstr(XPRMcontext ctx,void *libctx,void *toinit,const char *str,int typnum,const char **endp)
{
 s_dtctx *dtctx;
 int day,month,year,cnt;
 int hour,minute,second;
 s_date *d;
 struct Info
 {
  char dummy[4];
  s_date *d;
 } *ref;

 hour=minute=second=0;
 dtctx=libctx;
 d=toinit;

 if((str[0]=='r') && (str[1]=='a') && (str[2]=='w') && (str[3]=='\0'))
 {
  if(endp!=NULL) *endp=NULL;
  ref=(struct Info *)str;
  if(ref->d==NULL)
   memset(d,0,sizeof(s_date));
  else
   *d=*ref->d;
  return XPRM_RT_OK;
 }
 else
  if(sscanf(str,"%d/%d/%d%n %d%n:%d%n:%d%n",&day,&month,&year,&cnt,
  				&hour,&cnt,&minute,&cnt,&second,&cnt)<3)
  {
   if(endp!=NULL) *endp=str;
   return XPRM_RT_ERROR;
  }
  else
  {
   if(dtctx->in_eu)
   {
    d->tm_mday=day;
    d->tm_mon=month-1;
   }
   else
   {
    d->tm_mday=month;
    d->tm_mon=day-1;
   }
   d->tm_year=year-1900;
   d->tm_hour=hour;
   d->tm_min=minute;
   d->tm_sec=second;
   if(endp!=NULL) *endp=str+cnt;
   return XPRM_RT_OK;
  }
}

/******************** Services ********************/

/**************************************/
/* Reset the Complex module for a run */
/**************************************/
static void *dt_reset(XPRMcontext ctx,void *libctx,int version)
{
 s_dtctx *dtctx;
 s_nmlist *nmlist;

 if(libctx==NULL)               /* libctx==NULL => initialisation */
 {
  dtctx=malloc(sizeof(s_dtctx));
  memset(dtctx,0,sizeof(s_dtctx));
  dtctx->in_eu=XPRM_TRUE;       /* By default we are in Europe ! */
  return dtctx;
 }
 else                           /* otherwise release the resources we use */
 {
  dtctx=libctx;
  while(dtctx->nmlist!=NULL)
  {
   nmlist=dtctx->nmlist;
   dtctx->nmlist=nmlist->next;
   free(nmlist);
  }
  free(dtctx);
  return NULL;
 }
}

/****************************/
/* Find a control parameter */
/****************************/
static int dt_findparm(const char *name,int *type)
{
 if(strcmp(name,"date_style")==0)
 {
  *type=XPRM_TYP_BOOL|XPRM_CPAR_READ|XPRM_CPAR_WRITE;
  return 0;
 }
 else
  return -1;
}

/**********************************/
/* Return the next parameter name */
/**********************************/
static void *dt_nextparm(void *ref,const char **name,const char **desc,
                                                                     int *type)
{
 if(ref!=NULL)
  return NULL;
 else
 {
  *name="date_style";
  *type=XPRM_TYP_BOOL|XPRM_CPAR_READ|XPRM_CPAR_WRITE;
  *desc="Selects the date style (US/EU)";
 
  return (void *)(1);
 }
}


Back to examples browserPrevious exampleNext example