/* sui_dinfo.h
 *
 * Header file for DINFO (data info structures) common functions
 * 
 * Version 0.1
 * Copyright holders and project originators
 *   (C) 2002 by Roman Bartosinski, bartosr@centrum.cz
 *   (C) 2002 by PiKRON Ltd. http://www.pikron.com
 *   (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz
 *
 * The SUITK project can be used and copied under next licenses
 *   - MPL - Mozilla Public License
 *   - GPL - GNU Public License
 *   - LGPL - Lesser GNU Public License
 *   - and other licenses added by project originators
 * Code can be modified and re-distributed under any combination
 * of the above listed licenses. If contributor does not agree with
 * some of the licenses, he can delete appropriate line.
 * Warning, if you delete all lines, you are not allowed to
 * distribute code or build project.
 *
 */

#ifndef _SUI_DINFO_H_
#define _SUI_DINFO_H_

#include "sui_internal.h"
  
#ifdef __cplusplus
extern "C" {
#endif
  
#ifndef SUI_STATIC
  #define SUI_STATIC (-2)  /* static reference counter */
#endif /*SUI_STATIC*/


typedef int sui_tinfo_t;
// datainfo
struct sui_dinfo;
struct sui_event;
struct evc_tx_hub;

typedef void sui_dinfo_hevent_t(struct sui_dinfo *dinfo, struct sui_event *event);


typedef int sui_datai_rdfnc_t( struct sui_dinfo *dinfo, long idx, void *buf);
typedef int sui_datai_wrfnc_t( struct sui_dinfo *dinfo, long idx, const void *buf);

typedef struct sui_dinfo {
  int  refcnt;
  sui_tinfo_t tinfo;
  sui_datai_rdfnc_t *rdval;
  sui_datai_wrfnc_t *wrval;
  void *ptr;
  sui_dinfo_hevent_t *hevent;
  short evmask;
  struct evc_tx_hub *tx_hub;
  long info;
  long idxsize;
  long minval;
  long maxval;
  int  fdigits;
} sui_dinfo_t;

enum {
  SUDI_TINFO_UNKNOWN = 0,
  SUDI_TINFO_CHAR,   
  SUDI_TINFO_UCHAR,  
  SUDI_TINFO_SHORT,  
  SUDI_TINFO_USHORT, 
  SUDI_TINFO_INT,
  SUDI_TINFO_UINT,   
  SUDI_TINFO_LONG,   
  SUDI_TINFO_ULONG,  
  SUDI_TINFO_LLONG,  
  SUDI_TINFO_ULLONG, 
  SUDI_TINFO_FIXED,  
  SUDI_TINFO_UFIXED, 
  SUDI_TINFO_UTF8,
  SUDI_TINFO_DBUFF = 100
};

enum {
  SUDI_DATA_OK    = 0,	/* successful data transfer */
  SUDI_DATA_ERR   = 1,	/* unspecified error */
  SUDI_DATA_NRDY  = 2,	/* data source is not ready or destination is full */
  SUDI_DATA_NCON  = 3,	/* data target not connected */
  SUDI_DATA_EPERM = 4,	/* read/write or other permission problem */
  SUDI_DATA_ETYPE = 5,	/* value cannot be transformed to requested type */
  SUDI_DATA_EINDX = 6,	/* index value is out of range or forbidden */
  SUDI_DATA_EOORP = 7,	/* positive value out of range */
  SUDI_DATA_EOORN = 8,	/* negative value out of range */
};

/********************************************************************/
// refcnt
void sui_dinfo_inc_refcnt( sui_dinfo_t *datai);
void sui_dinfo_dec_refcnt( sui_dinfo_t *datai);

/********************************************************************/
// dynamic struct
sui_dinfo_t *sui_create_dinfo( void *data, int fdigits, long min, long max, long info,
                               sui_datai_rdfnc_t *rd, sui_datai_wrfnc_t *wr);
sui_dinfo_t *sui_create_dinfo_int( void *adata, long aidxsize, int asize);
sui_dinfo_t *sui_create_dinfo_uint( void *adata, long aidxsize, int asize);
#define sui_end_dinfo sui_dinfo_dec_refcnt
                   
/********************************************************************/
// static struct
#ifdef WIN32
  #define sui_dinfo_static( name, p, rd, wr, if, mi, ma, fd) \
    sui_dinfo_t name = { SUI_STATIC, 0, rd, wr, p, NULL, 0, if, mi, ma, fd}

#else
  #define sui_dinfo_static( name, p, rd, wr, if, mi, ma, fd) \
    sui_dinfo_t name = { \
      refcnt: SUI_STATIC, \
      ptr:    p, \
      rdval:  rd, \
      wrval:  wr, \
      info:   if, \
      minval: mi, \
      maxval: ma, \
      fdigits:fd \
    }
#endif

/********************************************************************/
// data connection
int sui_long_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_long_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_int_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_int_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_short_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_short_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_char_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_char_wrval( sui_dinfo_t *datai, long idx, const void *buf);

int sui_ulong_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_ulong_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_uint_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_uint_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_ushort_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_ushort_wrval( sui_dinfo_t *datai, long idx, const void *buf);
int sui_uchar_rdval( sui_dinfo_t *datai, long idx, void *buf);
int sui_uchar_wrval( sui_dinfo_t *datai, long idx, const void *buf);

// with TINFO
int sui_rd_long( sui_dinfo_t *datai, long idx, long *buf);
int sui_wr_long( sui_dinfo_t *datai, long idx, const long *buf);

/********************************************************************/
// events and events connectors

void sui_dinfo_do_changed( sui_dinfo_t *datai);

static inline
void sui_dinfo_changed( sui_dinfo_t *datai)
{
  if(datai->tx_hub)
    sui_dinfo_do_changed(datai);
}


/********************************************************************/
// scale_proxy and simple_proxy

typedef struct sui_dinfo_scale {
  sui_dinfo_t di;
  long multiply;
  long divide;
} sui_dinfo_scale_t;

int sui_scale_rdval(sui_dinfo_t *dinfo, long indx, void *buf);
int sui_scale_wrval(sui_dinfo_t *dinfo, long indx, const void *buf);
void sui_scale_minmax_update(sui_dinfo_t *dinfo);
void dinfo_simple_proxy_hevent(struct sui_dinfo *dinfo, struct sui_event *event);

sui_dinfo_t *dinfo_simple_proxy( sui_dinfo_t *dfrom, long ainfo);

sui_dinfo_t *dinfo_scale_proxy( sui_dinfo_t *dfrom, long ainfo, 
                                long amultiply, long adivide);
                                
int sui_simple_proxy_rdval(sui_dinfo_t *dinfo, long indx, void *buf);
int sui_simple_proxy_wrval(sui_dinfo_t *dinfo, long indx, const void *buf);

// change datainfo value
//long sui_data_change( sui_dinfo_t *datai, long newvalue, unsigned char flags);

#define sui_dinfo_scale_static( name, dfrom, if, mi, ma, fd, mul, div) \
  sui_dinfo_scale_t name = { \
    di: { \
      refcnt: SUI_STATIC, \
      ptr:    dfrom, \
      hevent: dinfo_simple_proxy_hevent, \
      evmask: SUEV_COMMAND | SUEV_FREE, \
      rdval:  sui_scale_rdval, \
      wrval:  sui_scale_wrval, \
      info:   if, \
      minval: mi, \
      maxval: ma, \
      fdigits:fd \
    }, \
    multiply : mul, \
    divide: div \
  }

sui_dinfo_t *dinfo_dinfopar_proxy(sui_dinfo_t *dfrom, long parinfo);


enum {
  SUDI_INFOPAR_INFO      = 1,
  SUDI_INFOPAR_MINVAL    = 2,
  SUDI_INFOPAR_MAXVAL    = 3,
  SUDI_INFOPAR_FDIGITS   = 4,
  SUDI_INFOPAR_TINFO     = 5,
};

#ifdef __cplusplus
} /* extern "C"*/
#endif

#endif /* _SUI_DINFO_H_ */
