/***********************************************************************
*           See Accompanying licence file QSAS_licence                 *
***********************************************************************/


/* ensure cdf.h is included before declaractions dependent on CDF types */

#if !defined(___cdf_h___)
#include <cdf.h>
#endif
 
#ifndef _QIE_H_  
#define _QIE_H_

/* c++ compliance... */

  #ifdef   __cplusplus
  extern "C" {
  #endif
  
/* include files */

#include <stddef.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <time.h> 
#include <math.h>
#include <ctype.h>

/* 'environment' variables */

#define INTERVAL_TOLERANCE 1.5
#define MAX_NUM_ITERATIONS 5
#define OVERWRITE_SKT  "TO BE OVERWRITTEN"
#define GEN_BY  "Generated by QSAS/Qtran"
#define QIE_VERSION  "QIE V_3.5.5 [May 2009]"
#define CAA_VERSION  "CEF-2.0"
#define MISSING 0
#define EXISTS 1
#define BY_PTR 10
#define BY_MEM 20
#define IGNORE -1
#define IGNORE_REC_NUMBERS -2
#define KEEP 0
#define DELIM 0
#define NO_DELIM 0
#define NOT_SET  (-2147483647-1)
#define ISO_TIME 3030 
#define MAX_N_INC_FILES 300 

/* messages */

#define QMW_OK 0         /* must be 0 for use of |= in accumulating errors */
#define QMW_WARNING -1
#define QMW_ERROR 1
#define BAD_STRUCT 101
#define CDF_OPEN_ERR 102
#define SPARSE_RECS 103
#define CDF_N_VAR_ERR 104
#define CDF_SELECT_ERR 105
#define EMPTY_STRUCT 106
#define CDF_VAR_N_ERR 107
#define CDF_VAR_NAME_ERR 108 
#define CDF_VAR_TYPE_ERR 109 
#define CDF_VAR_RVARY_ERR 110 
#define CDF_VAR_ELEMS_ERR 111 
#define CDF_VAR_DIMS_ERR 112 
#define CDF_VAR_SIZES_ERR 113
#define CDF_VAR_DVARY_ERR 114
#define BAD_CDF_DATATYPE 115
#define CDF_VAR_SELECT_ERR 116
#define CDF_VAR_GET_DATA_ERR 117
#define NEW_GLOBAL_ATTR 118
#define NO_GLOBAL_ATTR 119
#define FAIL_TO_SELECT_ENTRY 120
#define FAIL_G_ATTR_PUT 121
#define FAIL_GET_MAX_ENTRY 122
#define FAIL_VERSION_WRITE 123 
#define BAD_VARIABLE_NAME 124
#define NEW_VAR_ATTR 125
#define NO_VAR_ATTR 126
#define FAIL_V_ATTR_PUT 127
#define FAIL_WRITE_DATA 128
#define EXTRA_ENTRY 129
#define FILE_EXISTS 130
#define CANNOT_OPEN_FILE 131
#define BAD_VAR_HEADER 132
#define BAD_SYNTAX 133
#define FAIL_ON_CDF_READ 134
#define FAIL_ON_SELECT_ATTR 135 
#define FAIL_ON_G_ATTR_READ 136 
#define FAIL_ON_V_ATTR_READ 137 
#define MAX_DIM_ERROR 138 
#define FILE_READ_ERR 139 
#define FILE_POSN_ERR 140 
#define DEFAULT_TYPE_REAL8 141 
#define EXCEED_MAX_NUM_G_ATTRS 142
#define OPERATION_NOT_ALLOWED 143
#define G_ATTR_OBJECT_EXISTS 144
#define BAD_ISO_TIME_STR 145
#define EXCEED_MAX_NUM_VARS 146
#define EXCEED_MAX_ENTRIES 147
#define NOISY_DATA 148
#define EXCEED_MAX_INTERVALS 149
#define QIE_NO_DATA 150
#define BAD_HEADER 151
#define INCONSISTENT_HEADER 152
#define FILE_TYPE_UNKNOWN 153
#define DATA_NOT_SET 154
#define SHORT_RECORD 155
#define NOT_TS 156
#define VAR_NAME_CHECK_ERR 157
#define GLOBAL_NAME_CHECK_ERR 158
#define BAD_DOY_TO_DATE 159
#define DATE_COMPLETE_BUT_LIST_NOT_EXHAUSTED 160
#define BAD_MONTH_STRING 161
#define MONTH_NEEDED_NOT_FOUND 162
#define OVER_RAN_DATE_ITEM_LIST 163
#define LIST_EXHAUSTED_BUT_DAY_OF_MONTH_REQUIRED 164
#define FT_STRINGS_TOO_LONG_TO_CAT 165
#define ALL_RECORDS_STRING_TOO_LONG 166
#define FREE_TIME_FORMAT_STRING_NOT_FOUND 167
#define ERROR_COUNTING_ALL_RECS_ATTRIBUTES 168
#define FREE_TIME_FORMAT_STRING_ERROR 169
#define INCOMPATIBLE_ALL_RECS_FORMAT_AND_STRING 170
#define ALL_RECS_COMPONENT_MISSING 171
#define FORMAT_LEN_NE_TIME_STR 172
#define MONTH_OUT_OF_RANGE 173
#define DAY_OUT_OF_RANGE 174
#define UNKNOWN_TIME_FORMAT 175
#define BAD_YEAR_STR 176
#define NO_YEAR_OFFSET 177
#define BAD_Y_OFFSET 178
#define NO_HEADER_FOUND 179
#define BAD_CEF2_TEXT 180
#define CEF2_REC_NUM_ON 181

/* sizes */

#define LINE_LEN 40000
#define ISO_TIME_LEN 30
#define WINDOW_LEN 80
#define MAX_ENTRIES 1000
#define MAX_INTERVALS 300
#define REAL_WIDTH 13
#define DOUBLE_WIDTH 20
#define BYTE_WIDTH 5
#define SHORT_WIDTH 13
#define LONG_WIDTH 13
#define REC_N_WIDTH 11
#define INT_WIDTH 13
#define EPOCH_WIDTH 30
#define MAX_N_ATTRS 200
#define MAX_N_VARS 300
#define MAX_N_G_ENTRIES 5000
#define SPARE 11
#define N_FT_DATE_STRINGS  6    /*SJS re FT*/
#define N_FT_TIME_STRINGS  9	/*SJS re FT*/
#define MAX_FT_LENGTH    256	/*SJS re FT*/
#define MAX_STR_LEN_CEF2    256	/* CEF 2 only */
#define MAX_STR_MESSAGE    256

/* Globals */

/* Free Time enums :      	SJS re FT*/
/* See also qie_ft.h for globals and other private qie_ft things */

/* safe ptrs: can be dereferenced as well as trapped */

static char STR_NULL[]="";  

typedef enum QiSFTdatestrings_e {
	YYYY_FTe=0,
	YY_FTe,
	DOY_FTe,
	MON_FTe,
	MO_FTe,
	DD_FTe
} QiFTdatestrings_e;

typedef enum QiSFTtimestrings_e {
	H_FTe = 0, /* need to be sure starts at zero since use i=0,...  cntr */
	MI_FTe,
	S_FTe,
	MC_FTe,
	d_FTe,
	h_FTe,
	m_FTe,
	s_FTe,
	c_FTe
} QiFTtimestrings_e;

typedef enum QiSFTAllRecordsFlag_e {   /* flag to indicate if common time  */
	No_all_records_time = 0,       /* srting to be appended to that of */
	All_records_time_found         /* each record                      */
} QiFTAllRecordsFlag_e;

/* end of Free Time enums       SJS re FT*/

/* Structure to hold data from a single variable.
** The data array holds all entries from the variable.
** All variables are stored and written as z-variables.
*/

typedef enum QiSCDFVariable_novary{
  WRITE_ONCE, 
  EVERY_RECORD
} QiCDFVariable_novary;

typedef struct QiSCDFVariable
{ 
  QiCDFVariable_novary novary_opt;
  long sizeofentry;   /* number of bytes for each entry in data array */
  long number;        /* variable number in cdf */     
  char *name;         /* variable name */
  long data_type;     /* CDF data type */
  long rec_vary;      /* CDF record vary value = VARY or NOVARY */
  long max_rec_num;   /* record number of last record (first record is at 0) */
  long num_dims;      /* number of CDF dimensions */
  long *dim_sizes;    /* ptr to array of sizes for each dimension */
  long *dim_varys;    /* ptr to array of dim vary's, VARY/NOVARY */
  long num_v_attrs;   /* number of variable attributes held */
  long num_elems;     /* number of elements per entry */
  
  void * data;        /* pointer to array of data entries */

  struct QiSVarAttribute *attribute;
  int isPtrType;
  int isTensorRep_i;
  int isDepend_i;
  int isLabel_i;
  int hasUnits;
  int hasFrame;
  int hasSI_conversion;
  int hasFieldnam;
  int hasLablaxis;
  int hasDepend_0;
  int hasDeltaPlus;
  int hasDeltaMinus;
  int hasTensorFrame;
  int hasTensorRank;
  int numTensorRep_i;
  int numLabel_i;
  int numDepend_i;
  int ErrDepend_i;
  int ErrLabel_i;
  int ErrTensorRep_i;

} QiCDFVariable;

typedef struct QiSGAttrEntry
{
  long exists;
  long data_type;
  long num_elems;
  void *data;
} QiGAttrEntry;

typedef struct QiSGlobalAttribute
{
  long number;
  char *name;
  long num_entries;
  QiGAttrEntry *entry;
} QiGlobalAttribute;

 typedef struct QiSVarAttribute
  {
    long number;
    char *name;
    long data_type;
    long num_elems;   /* for an attribute this is the number of items for ALL data types */
    void *data;
  } QiVarAttribute;


/* Structure to hold both data and metadata. For assembly of object for
** writing whole file contents.
*/

typedef struct QiSCDFContents
{
  long n_vars;               /* number of variables */
  long n_recs;               /* number of data records */
  long time_var_num;         /* var number of time variable */
  char *io_f_name;         /* file name for new file */
  char *io_f_path;         /* path to directory to hold new file */
  char *io_f_extn;      /* 4 char data file ext, .cdf, .qft, .qfd, .qfh .cef */
  long num_g_attrs;          /* number of global attrs */

  QiCDFVariable ** vardata;    /* ptr to array of QiSCDFVariable structures */
  QiGlobalAttribute ** g_attr;      /* structure holding file metadata */

} QiCDFContents;

typedef enum QiSOptions_f_type {
  UNSET, 
  TABULAR, 
  DELIMITED,
  EXCHANGE,
  CAA
} QiOptions_f_type;

typedef enum QiSOptions_header {
  ATTACHED, 
  DETACHED, 
  NO_HEADER
} QiOptions_header;

typedef enum QiSOptions_rec_num {
  NUM_OFF, 
  NUM_ON
} QiOptions_rec_num;

typedef enum QiSOptions_priority {
  REPLACE=1, 
  WARN
} QiOptions_priority;

typedef enum QiSOptions_object {
  TS, 
  DS
} QiOptions_object;

typedef enum QiSTimeFormat_e {   /* cope with more time formats  SJS*/
  NOT_A_TIME,
  ISO,
  FREE_TIME_FORMAT
} QiFTTimeFormat_e;

typedef struct QiSOptions
{
  QiOptions_header header;
  QiOptions_f_type f_type;  /*if UNSET uses file clues */
  QiOptions_rec_num rec_numbering; /* flag to set record numbering on */
  QiOptions_priority priority;     /* flag for overwrite on new file */
  QiOptions_object object_type;         /* qsas obj type */
  char attr_delim;          /* delimiter to use in header */
  char data_delim;          /* delimiter to use in data */
  char rec_end;             /* end of record delimiter */
  char row_end;             /* end of row in array delimiter */
  QiOptions_f_type type_guess;           /* file type guess from context */
  FILE * fp_display;        /* file pointer for output display */
  FILE * fp_null;           /* file pointer to null for losing things */
  char debug_choice;        /* 'f'= fp_display, 'w' = QSAS fn, else = off */
  double sample_H_interval; /* sampling interval, normally Half_interval */
  char * start_after;       /* string that identifies last line before data */
  char time_sep_attr;       /* character separator in ISO time in attributes */
  char time_sep_data;       /* character separator in ISO time in data recs */
  char * header_path;       /* path to header file if detached */
  char * header_name;       /* name of header file if detached */
  char * get_only;          /* name of single variable to fetch, if STR_NULL gets all */

  char EXTN_CDF[5];         /* strings for known file extensions */
  char EXTN_QFT[5];         /* these are initialised in QiMakeOptionsObj */
  char EXTN_QFD[5];
  char EXTN_QHD[5];
  char EXTN_CEF[5];
  char EXTN_CEFGZ[8];
  
  char * data_until;       /* cef 2 end of data file marker (optional) */
  long Nstart;            /* record number to start reading at (inclusive) first record is zero */
  long Nend;              /* record number to end reading at (inclusive)*/
    
} QiOptions;

#ifndef _QTUI_h

typedef struct QiSCDFepoch{                 /* moved by SJS re FT */
                 double tsince0;
                 long   year;
                 long   month;
                 long   day;
                 long   hour;
                 long   minute;
                 long   second;
                 long   msec;
} cdf_epoch;
#endif

/* Free Time Parser structures (needed now; */
/* also cdf_epoch moved earlier SJS re FT   */

typedef struct QiSFTParser               /* info to parse FT string */
{
   int	            n_found_date;        /* number of date strings to get */
   QiFTdatestrings_e  found_date[N_FT_DATE_STRINGS];   /* which ones found  */
   int	            date_start_in_FT[N_FT_DATE_STRINGS]; /* start pos (fr 0)*/
   int	            date_width_in_FT[N_FT_DATE_STRINGS];  /* field widths */
   int	            n_found_time;        /* and all same stuff for time   */
   QiFTtimestrings_e  found_time[N_FT_TIME_STRINGS];
   int	            time_start_in_FT[N_FT_TIME_STRINGS];
   int	            time_width_in_FT[N_FT_TIME_STRINGS];
} QiFTParser;

typedef struct QiSFTpacket            /* holds all info; goes into rec fmt */
{
	QiFTTimeFormat_e	timeformat;
	QiFTAllRecordsFlag_e	AllRecordsFlag;
	char			AllRecordsFormatString[MAX_FT_LENGTH];
	char			AllRecordsTimeString[MAX_FT_LENGTH];
	char			FreeTimeFormatString[MAX_FT_LENGTH];
	cdf_epoch		epoch;
	QiFTParser		ft_parser_s;   
	double			time2msecs_factors_adjusted[N_FT_TIME_STRINGS];
} QiFTpacket;

/* end of Free Time additions; */
/* QiSRecord_format modified to incl QiFTpacket  SJS re FT*/


typedef struct QiSRecord_format
{
  char *title;          /* title string for var names */
  int total_width;     /* total width of record in columns */
  int *col_start;     /* ptr to array of posns for var in record, start at 0 */
  int *col_width;      /* ptr to array of column widths of var in record */
  long *n_items;        /* ptr to array of number of values for each variable */
  long *ignore;  /* ptr to array of flags for each variable for skipping cols */
  QiFTpacket *ftpackets; /* ptr to array of info for FreeTime->epoch conv SJS*/

} QiRecord_format;


typedef struct QiSTimeFormats
{
  char * Date_zero_str;     /* zero point used to set other times */
  cdf_epoch *epoch;          /* epoch structure */
  
} QiTimeFormats;





/* **************************************************************************
** 
** Function Prototypes
**
** ************************************************************************* 
*/

long  QiRemoveEpoch(QiCDFContents *QiSCDF);

/**********************************/

long  QiRemoveISO_TIME(QiCDFContents *QiSCDF);

/**********************************/

long  QiGetVarByName(QiCDFContents *QiSCDF, const char * name);

/**********************************/

void  QiCheckCEFstructure(QiCDFContents *QiSCDF);

/**********************************/

void QiCEFvalidate(QiCDFContents *QiSCDF);   /* utility to test QiCDF structure is CEF2 compliant */

/**********************************/

int QiLooksLikeVector(const char *name);   /* utility to test var name for signs of being vector or tensor: used for warnings only */

/**********************************/

int QiCEFmsg (int mode,  /* 0 = warning, 1 = failure */
              const char * txt0,
              const char * txt1,
              const char * txt2 );     /* message to output if cef 2 compliance testing on */

/**********************************/

long QiWriteCSDSgenCDF (QiCDFContents *QiSCDF, /* ptr to file contents struct */
                        QiOptions *QiOpt);     /* ptr to write options */

/**********************************/
                 
long QiCreateCDF(char *full_file_name,   /* string with new path/file name */
                 QiOptions *QiSOpt);     /* flag to force overwrite of file */

/**********************************/
                
int QiGetCSDSgenCDF(const char *file_name,     /* name of cdf file with path */
                 QiCDFContents *Scdf_data); /* ptr to struct for data return */


/**********************************/

long QiWriteCSDSgenFlat (QiCDFContents *QiSCDF, /* ptr to struct for data return */
                        QiOptions *QiSOpt);      /* ptr to write options */

/**********************************/

long WriteHeaderFlat(QiCDFContents *QiSCDF,   /* ptr to struct of contents */ 
                     FILE *fp,                /* ptr to output file */
                     QiOptions *QiSOpt);     /* ptr to structure of write options */

/**********************************/

long QiWriteRecsTabular(QiCDFContents *QiSCDF,   /* ptr to struct of contents */  
                        QiRecord_format *QiSfmt, /* ptr to record formatting struct */
                        QiOptions *QiSOpt,       /* ptr to structure of write options */
                        FILE *fp);               /* ptr to flat output file */
/**********************************/

long QiWriteRecsParsed(QiCDFContents *QiSCDF,   /* ptr to struct of contents */  
                       QiRecord_format *QiSfmt, /* ptr to record formatting struct */
                       QiOptions *QiSOpt,       /* ptr to structure of write options */
                       FILE *fp);               /* ptr to flat output file */
   
/**********************************/
long QiWriteRecsExchange(QiCDFContents *QiSCDF,   /* ptr to struct of contents */  
                       QiRecord_format *QiSfmt,   /* ptr to record formatting struct */
                       QiOptions *QiSOpt,         /* ptr to structure of write options */
                       FILE *fp);                 /* ptr to flat output file */
   
/**********************************/

long QiWriteRecsCAA(QiCDFContents *QiSCDF,      /* ptr to struct of contents */ 
                       QiRecord_format *QiSfmt, /* ptr to record formatting struct */
                       QiOptions *QiSOpt,       /* ptr to structure of write options */
                       FILE *fp);               /* ptr to flat output file */

/**********************************/

QiCDFContents * QiFreeCDFContentsObj(QiCDFContents *QiSCDF); /* ptr to struct of contents */ 
                                            
/**********************************/


long QiGetCSDSgenFlat (QiCDFContents *QiSCDF, /* ptr to struct of contents */ 
                       QiOptions *QiSOpt); /* ptr to structure of i/o options */

/**********************************/

long QiReadData(QiCDFContents *QiSCDF,    
                QiRecord_format *QiSfmt, 
                QiOptions *QiSOpt);

/**********************************/

long QiReadRecsTabular(QiCDFContents *QiSCDF,    
                       QiRecord_format *QiSfmt, 
                       QiOptions *QiSOpt,
                       long j);

/**********************************/

long QiReadRecsParsed(QiCDFContents *QiSCDF,    
                      QiRecord_format *QiSfmt, 
                      QiOptions *QiSOpt,
                       long j);
                                          
/**********************************/

long QiReadRecsExchange(QiCDFContents *QiSCDF,    
                      QiRecord_format *QiSfmt, 
                      QiOptions *QiSOpt,
                       long j);
                                          
/**********************************/

long QiReadRecsCAA(QiCDFContents *QiSCDF,    
                      QiRecord_format *QiSfmt, 
                      QiOptions *QiSOpt,
                       long j);
                                          
/**********************************/

double QiISOStringToEpoch(char *Time_str);


/**********************************/

char * QiCtoISO(char *time, 
                char *iso_time);


/**********************************/


long QiInitGlobalContents(QiCDFContents * QiSCDF);

/**********************************/

FILE * QiOpenFile( char * mode,
                   char * path,
                   char * file_stem,
                   char * extn);

/**********************************/

QiRecord_format * QiFreeFormatSpace(QiRecord_format *QiSfmt);

/**********************************/

long QiReadHeader (QiCDFContents *QiSCDF, 
                    QiOptions *QiSOpt, 
                    QiRecord_format *QiSfmt,
                    FILE *fp_hdr);

/**********************************/

long QiCloseFile( long check,
                  char * path,
                  char * file_stem,
                  char * extn,
                  FILE * fp);
                  
/**********************************/

QiCDFContents * QiMakeCDFContentsObj();

/**********************************/

QiCDFVariable ** QiMakeQiVariablePtrs(long n_vars);

/**********************************/

QiGlobalAttribute ** QiMakeQiGAttrPtrs(long n_Gattrs);

/**********************************/

QiCDFVariable * QiMakeQiVariable();

/**********************************/

QiVarAttribute * QiMakeQiVAttr(long n_Vattrs);

/**********************************/

QiGlobalAttribute * QiMakeQiGAttr( );

/**********************************/

QiGAttrEntry * QiMakeEntries(long n_entries);

/**********************************/

QiOptions * QiMakeOptionsObj();

/**********************************/

QiRecord_format * QiMakeFmtObj();

/**********************************/

long QiCountRecords(QiOptions *QiSOpt);

/**********************************/

double QiFindSampleSpacing(double * data,
                           long num_recs,
                           long iterate,
                           double discard);
                          
/**********************************/

char * QiNewStr(const char * old_str);

/**********************************/

char * QiReadLine(char *skip_until);

/**********************************/

char * QiGetLine(FILE *fp);

/**********************************/

void QiEpochBreakdown (cdf_epoch *epoch_ptr);

/**********************************/

char * QiEpochToISOString ( double tsince0,
                            char space );

/**********************************/

long  QiFindVersion(QiOptions *QiSOpt);

/**********************************/

long  QiDisplayMessage(char *line,              /* string to write */
                       QiOptions *QiSOpt);      /* i/o options */

/**********************************/

long   QiEnsureHeader(QiCDFContents *QiSCDF,   
                      QiOptions *QiSOpt);

/**********************************/

long   QiEnsureFileName(QiCDFContents *QiSCDF,   
                        QiOptions *QiSOpt);

/**********************************/

int   QistrNULL(char *string);


/**********************************/

long QiWriteVarData(FILE *fp,
                    QiCDFVariable **vardata,
                    long n,         /* var number */
                    long mm,        /* number of data elements */
                    long record,    /* record number */
                    long call,      /* zero if first call of record */
                    QiOptions* QiSOpt,
		    char delim);
		    
/**********************************/

long QiWriteVarDataNRV(FILE *fp,
                    QiCDFVariable **vardata,
                    long n,         /* var number */
                    long mm,        /* number of data elements */
                    long record,    /* record number */
                    long call,      /* zero if first call of record */
                    QiOptions* QiSOpt,
		    char delim);

/**********************************/

char * QiFindHeader(char *dir_path,
                    QiOptions *QiSOpt);

/**********************************/

long QiSetVarToGet(QiCDFContents * QiSCDF, 
                   QiRecord_format * QiSfmt, 
                   char * var_to_get);
                   
/**********************************/
         
 QiCDFContents * QiMakeSafe (QiCDFContents *QiSCDF);
 
/**********************************/

char QiGetDelim (char * value);

/**********************************/

long QiPutDelim (FILE *fp, char delim);

/**********************************/
         
QiOptions * QiFreeOptionsObj(QiOptions * QiSOpt);

/**********************************/

char * QiSafePath(char * path);

/**********************************/

char * QiUserHomeDir(char * user_id);

/**********************************/

char * QiErrStr (int err_n);
   
/**********************************/

void QieAlertBox (char * title, char * text);

/**********************************/

char * QieVersion();

/**********************************/

long QiAppendGlobalTxtAttr(QiCDFContents * QiSCDF,
                            char * attr_name, 
                            const char * txt_entry);

/**********************************/

/************** Free Time Format Prototypes foloow - SJS re FT */

long QiParseFreeTimeFormatString_date (
	char * ft_format_str,
	QiFTParser *ftparser
);

/**********************************/

long QiParseFreeTimeFormatString_time (
	char * ft_format_str,
	QiFTParser *ftparser
);

/**********************************/

long QiFTCpyCalcmsecsFactors( QiFTParser *ftparser, 
                               double t2ms_factors[] );


/**********************************/

long QiFTtoEPOCH ( QiFTpacket *ftpackp, char *ftstr);

/**********************************/

long QiFTGetDate(QiFTParser *ftparser,
                 char * ftstr, 
                 long *yp, 
                 long *mp,
                 long *dp);

/**********************************/

long QiYearDoyToDate( long year, long doy, long* month, long* day );

/**********************************/

long QiFTGetMsecs( QiFTpacket *ftpackp,
                   char       *ftstr,
                   double     *msecs);

/**********************************/

double QiFTComputeEpoch( long year, 
                         long month, 
                         long day, 
                         double msec);

/**********************************/

long QiFTCatTime_All ( char *record,
                       char *all );


long QiFTinit_parsers(QiCDFContents* QiSCDF,
                      QiRecord_format* QiSfmt);


char * QiToUpper(const char *string);


long QiVarSafe (QiCDFContents *QiSCDF, long n);     


void make_uppercase(char *string);

int QiIsDivisible(long m, long n, long *mdiv);

long QiWriteVarBlocked(FILE *fp,
                    QiCDFVariable **vardata,
                    long n,         /* var number */
                    long nn,        /* number of vars total */
                    long mm,        /* number of data elements */
                    long record,    /* record number */
                    QiOptions* QiSOpt,
		    char delim);
		    
long QiWriteDataValue(FILE *fp,
                    QiCDFVariable **vardata,
                    long n,         /* var number */
                    long m,         /* data element in series */
                    long mm,        /* number of data element in array */
                    long record,    /* record number */
                    QiOptions* QiSOpt);

int QiStrcpy(char * To, char * From, int ToLen);
int QiStrcat(char * To, char * From, int ToLen);
char * QiStripQuotes(const char * value);
int QiIsISOtime(const char * value);
int QiIsNumber(const char *ptr);
int maxEntryLength(const char *value, const char delim);
int Qifgetpos(fpos_t *file_posn, int *fpRewind);
int Qifsetpos(fpos_t *file_posn, int fpRewind);
int QiFindAlreadyOpen(const char *name, int *which_fp);
void QiRemoveStrArrays(QiCDFContents *QiSCDF);
void QiFixThemisEpoch(QiCDFContents * QiSCDF, long tnum);

  #ifdef   __cplusplus
  }
  #endif

#endif
