##// END OF EJS Templates
Update html images routes
Update html images routes

File last commit:

r0:b84e1135c2c4
r14:8f437cc4b32c
Show More
madrec.c
1757 lines | 55.8 KiB | text/x-c | CLexer
Initial
r0 /* $Id: madrec.c 5647 2016-05-05 14:25:01Z brideout $ */
/*
modification history
--------------------
00a,22Apr96 original
*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cedarIO.h>
#include <madrec.h>
#include <cedar.h>
/***********************************************************************
*
* madrecCreate creates a madrec object
*
* arguments:
* None
*
* returns:
* pointer to the new madrec object
*
*/
Madrec *
madrecCreate ()
{
Madrec *madrecp;
madrecp = (Madrec *)malloc(sizeof(Madrec));
madrecp->filnam = (char *)NULL;
madrecp->fp = (FILE *)NULL;
madrecp->fd = 0;
madrecp->file_status = 0;
madrecp->iotype = 0;
madrecp->fileSize = 0;
madrecp->filep = (Int16 *)NULL;
madrecp->pos = 0;
madrecp->nrecords = 0;
madrecp->currentRecord = -1;
madrecp->indexp = (CedarIndex *)NULL;
madrecp->madrigalParms.blockSize = 6720;
madrecp->madrigalParms.sigWords = 0;
madrecp->madrigalParms.blockIndex = 0;
madrecp->madrigalParms.blockp = (Int16 *)NULL;
madrecp->madrigalParms.prevRec = 0;
madrecp->madrigalParms.thisRec = 0;
madrecp->blockedBinaryParms.pos = -1; /* must be 1 for put */
madrecp->blockedBinaryParms.lBlock = 2;
madrecp->blockedBinaryParms.maxBlock = 8000;
madrecp->blockedBinaryParms.lbuf = 2;
madrecp->blockedBinaryParms.blockp = (Int16 *)NULL;
madrecp->cbfParms.blockSize = 4096;
madrecp->cbfParms.pos = 0; /* must be 1 for put */
madrecp->cbfParms.cosRecordp = (Int16 *)NULL;
madrecp->cbfParms.lCosBlock = 0;
madrecp->cbfParms.fwi = 0;
madrecp->cbfParms.initPos8 = 0;
madrecp->cbfParms.initFwi = 0;
madrecp->cbfParms.initPos = 0;
madrecp->cbfParms.initLCosBlock = 0;
madrecp->cbfParms.lbuf = 2;
madrecp->cbfParms.blockNumber = 0;
madrecp->cbfParms.previousFileIndex = -1;
madrecp->cbfParms.previousRecordIndex = -1;
madrecp->cbfParms.lastControlWord = -1;
madrecp->unblockedBinaryParms.placeHolder = 0;
madrecp->asciiParms.placeHolder = 0;
madrecp->recordp = (Int16 *)NULL;
madrecp->recordpInMem = 0;
madrecp->earliestStartTime = 0.0;
madrecp->latestEndTime = 0.0;
madrecp->numParms = 0;
madrecp->numKinst = 0;
madrecp->numKindat = 0;
madrecp->parmsListp = (int *)NULL;
madrecp->parmLocp = (int *)NULL;
madrecp->parmMinp = (double *)NULL;
madrecp->parmMaxp = (double *)NULL;
madrecp->parmMissing = (int *)NULL;
madrecp->pflag = 0;
madrecp->startJday0 = 0;
madrecp->lastError = (char *)malloc(strlen(NO_ERR_STR)+1);
(void) strcpy(madrecp->lastError, "No errors");
madrecp->sortedRecnoList = (int *)NULL;
return(madrecp);
}
/***********************************************************************
*
* madrecDestroy destroys a madrec object
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns
* 0
*
*/
int
madrecDestroy (Madrec *madrecp)
{
if (madrecp->filnam != (char *)NULL)
free(madrecp->filnam);
if (madrecp->filep != (Int16 *)NULL)
free(madrecp->filep);
if (madrecp->indexp != (CedarIndex *)NULL)
free(madrecp->indexp);
if (madrecp->sortedRecnoList != (int *)NULL)
free(madrecp->sortedRecnoList);
if (madrecp->madrigalParms.blockp != (Int16 *)NULL)
free(madrecp->madrigalParms.blockp);
if (madrecp->blockedBinaryParms.blockp != (Int16 *)NULL)
free(madrecp->blockedBinaryParms.blockp);
if (madrecp->cbfParms.cosRecordp != (Int16 *)NULL)
free(madrecp->cbfParms.cosRecordp);
if (madrecp->recordp != (Int16 *)NULL && !(madrecp->recordpInMem))
free(madrecp->recordp);
if (madrecp->parmsListp != (int *)NULL)
free(madrecp->parmsListp);
if (madrecp->parmLocp != (int *)NULL)
free(madrecp->parmLocp);
if (madrecp->parmMinp != (double *)NULL)
free(madrecp->parmMinp);
if (madrecp->parmMaxp != (double *)NULL)
free(madrecp->parmMaxp);
if (madrecp->parmMissing != (int *)NULL)
free(madrecp->parmMissing);
free(madrecp->lastError);
free(madrecp);
return(0);
}
/***********************************************************************
*
* madrecOpen opens a madrec data file
*
* arguments:
* madrecp - pointer to the madrec object
* iotype - file type as described below
* filnam - file name
*
* The following file types (iotype) are supported:
*
* Open Cedar file for sequential reading:
* 1 - Determine file type automatically
* 10 - Madrigal file
* 11 - Blocked Binary file
* 12 - Cbf file
* 13 - Unblocked Binary file
* 14 - Ascii file
*
* Create Cedar file for update; discard previous contents if any:
* 2 - Madrigal file
* 20 - Madrigal file
* 21 - Blocked Binary file
* 22 - Cbf file
* 23 - Unblocked Binary file
* 24 - Ascii file
*
* Create Cedar file in memory for sequential and random read and write.
* 30 - Determine file type automatically
* 40 - Madrigal file
* 41 - Blocked Binary file
* 42 - Cbf file
* 43 - Unblocked Binary file
* 44 - Ascii file
*
* Fast create Cedar file in memory for sequential and random read and write.
* Does not calculate min and and max parameter values
* 50 - Determine file type automatically
* 60 - Madrigal file
* 61 - Blocked Binary file
* 62 - Cbf file
* 63 - Unblocked Binary file
* 64 - Ascii file
*
* returns:
* 0 - File opened successfully
* 1 - Invalid file type (iotype)
* 2 - unable to open data file
* 3 - data file already open
* 4 - input file name too long
* 5 - error writing file to memory
*
*/
int
madrecOpen (Madrec *madrecp, int iotype, char *filnam)
{
int stat=0, ind=0;
long fileType=0;
int memPos = 0; /* used only in loading files into memory */
static const char *err1="madrecOpen error - invalid file type";
static const char *err2="madrecOpen error - unable to open file";
static const char *err3="madrecOpen error - file already open";
static const char *err4="madrecOpen error - file name too long";
static const char *err5="madrecOpen error - error writing file to memory";
static const char *err6="madrecOpen error - file not a valid CEDAR file";
if (madrecp->file_status == 1) {
(void) madrecSetError(madrecp,err3);
return(3);
}
/* Set madrigal file name */
if (iotype == 1 || iotype == 2 || iotype == 3 ||
(iotype>= 10 && iotype <= 14) || (iotype>= 20 && iotype <= 24) ||
(iotype>= 30 && iotype <= 64)) {
if (strlen(filnam) >= MAXFCH) {
(void) madrecSetError(madrecp,err4);
return(4);
}
madrecp->filnam = (char *)malloc(strlen(filnam)+1);
(void) strcpy(madrecp->filnam, filnam);
}
else {
(void) madrecSetError(madrecp,err1);
return(1);
}
/* Determine file type */
if (iotype == 1) {
fileType = cedarFileType(filnam, MADRIGALBLOCKSIZE, CBFBLOCKSIZE);
if (fileType == -1) {
(void) madrecSetError(madrecp,err6);
return(6);
} else if (fileType == -2) {
(void) madrecSetError(madrecp,err2);
return(2);
}
iotype = 10*iotype + fileType;
}
madrecp->iotype = iotype;
/* Open data input file for reading */
if (iotype>= 10 && iotype <= 14) {
/* These initial values differ for reading and writing */
madrecp->cbfParms.pos = 0;
madrecp->blockedBinaryParms.pos = -1;
if ((madrecp->fd = open(filnam, O_RDONLY)) == -1) {
(void) madrecSetError(madrecp,err2);
return(2);
}
if ((madrecp->fp = fdopen (madrecp->fd, "r")) == NULL) {
(void) madrecSetError(madrecp,err2);
return(2);
}
/* Open new output file for update */
} else if (iotype == 2 || (iotype>= 20 && iotype <= 24)) {
(void) remove(filnam);
/* These initial values differ for reading and writing */
madrecp->cbfParms.pos = 1;
madrecp->blockedBinaryParms.pos = 1;
if ((madrecp->fd = open(filnam, O_RDWR|O_CREAT, 0664)) == -1) {
(void) madrecSetError(madrecp,err2);
return(2);
}
if ((madrecp->fp = fdopen (madrecp->fd, "w+")) == NULL) {
(void) madrecSetError(madrecp,err2);
return(2);
}
/* Open data input file for random reading using memory image of file */
} else if (iotype>= 30 && iotype <= 44) {
/* Determine file type automatically if iotype == 30*/
if (iotype == 30) {
fileType = cedarFileType(filnam, MADRIGALBLOCKSIZE, CBFBLOCKSIZE);
if (fileType == -1) {
(void) madrecSetError(madrecp,err6);
return(6);
} else if (fileType == -2) {
(void) madrecSetError(madrecp,err2);
return(2);
}
iotype = 40 + fileType;
}
madrecp->iotype = iotype;
/* These initial values differ for reading and writing */
madrecp->cbfParms.pos = 0;
madrecp->blockedBinaryParms.pos = -1;
if ((madrecp->fd = open(filnam, O_RDONLY)) == -1) {
(void) madrecSetError(madrecp,err2);
return(2);
}
if ((madrecp->fp = fdopen (madrecp->fd, "r")) == NULL) {
(void) madrecSetError(madrecp,err2);
return(2);
}
madrecp->iotype = madrecp->iotype - 30; /* Temporary to read file */
madrecp->nrecords = 0;
madrecp->recordpInMem = 0;
memPos = 0; /* keeps track of how much allocated mem used so far */
while ((stat=madrecGetNextRec(madrecp)) == 0) {
ind = putMemFastNextCedarUnblockedRecord(&madrecp->filep,
&madrecp->recordp,
&madrecp->fileSize,
&madrecp->pos,
&memPos);
if (ind != 0) {
(void) madrecSetError(madrecp,err5);
return(5);
}
madrecp->nrecords++;
ind = cedarUpdateParmsList(madrecp->recordp,
&madrecp->numParms,
&madrecp->parmsListp,
&madrecp->parmLocp,
&madrecp->parmMinp,
&madrecp->parmMaxp,
&madrecp->parmMissing,
&madrecp->startJday0,
&madrecp->earliestStartTime,
&madrecp->latestEndTime,
&madrecp->numKinst,
madrecp->kinstArr,
&madrecp->numKindat,
madrecp->kindatArr);
if (ind != 0)
fprintf(stderr, "Record %i has par code 0\n", madrecp->nrecords);
}
/* realloc madrecp->filep since putMemFastNextCedarUnblockedRecord */
/* allocates in large blocks for speed */
madrecp->filep = (Int16 *)realloc(madrecp->filep, (memPos + 1)*2);
madrecp->fileSize = (memPos+1)*2;
madrecp->iotype = madrecp->iotype + 30; /* Reset to correct value */
if (stat != -1) {
(void) madrecSetError(madrecp,err5);
return(5);
}
/* Rapidly open data input file for random reading using memory image of file */
/* Skip calculation of min and max of all parameters */
} else if (iotype>= 50 && iotype <= 64) {
/* Determine file type automatically if iotype == 50*/
if (iotype == 50) {
fileType = cedarFileType(filnam, MADRIGALBLOCKSIZE, CBFBLOCKSIZE);
if (fileType == -1) {
(void) madrecSetError(madrecp,err6);
return(6);
} else if (fileType == -2) {
(void) madrecSetError(madrecp,err2);
return(2);
}
iotype = 60 + fileType;
}
madrecp->iotype = iotype;
/* These initial values differ for reading and writing */
madrecp->cbfParms.pos = 0;
madrecp->blockedBinaryParms.pos = -1;
if ((madrecp->fd = open(filnam, O_RDONLY)) == -1) {
(void) madrecSetError(madrecp,err2);
return(2);
}
if ((madrecp->fp = fdopen (madrecp->fd, "r")) == NULL) {
(void) madrecSetError(madrecp,err2);
return(2);
}
madrecp->iotype = madrecp->iotype - 50; /* Temporary to read file */
madrecp->nrecords = 0;
madrecp->recordpInMem = 0;
memPos = 0; /* keeps track of how much allocated mem used so far */
while ((stat=madrecGetNextRec(madrecp)) == 0) {
ind = putMemFastNextCedarUnblockedRecord(&madrecp->filep,
&madrecp->recordp,
&madrecp->fileSize,
&madrecp->pos,
&memPos);
if (ind != 0) {
(void) madrecSetError(madrecp,err5);
return(5);
}
madrecp->nrecords++;
}
/* realloc madrecp->filep since putMemFastNextCedarUnblockedRecord */
/* allocates in large blocks for speed */
madrecp->filep = (Int16 *)realloc(madrecp->filep, (memPos + 1)*2);
madrecp->fileSize = (memPos+1)*2;
madrecp->iotype = madrecp->iotype + 50; /* Reset to correct value */
if (stat != -1) {
(void) madrecSetError(madrecp,err5);
return(5);
}
} else {
madrecp->file_status = 1;
(void) madrecSetError(madrecp,err1);
return(1);
}
madrecp->file_status = 1;
madrecp->iotype = iotype;
(void) fseek (madrecp->fp, 0L, SEEK_SET);
return(0);
}
/***********************************************************************
*
* madrecClose closes a madrec data file
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 - File closed successfully
* 1 - error closing file
* 2 - file not open
* 3 - error flushing file
*
*/
int
madrecClose (Madrec *madrecp)
{
static const char *err1="madrecClose error - error closing file";
static const char *err2="madrecClose error - file not open";
static const char *err3="madrecClose error - error flushing file";
if (madrecp->file_status == 1) {
if (madrecp->iotype == 21) { /* Flush blocked binary */
if(flushCedarBlockedRecord(madrecp->fp, &madrecp->recordp,
&madrecp->blockedBinaryParms.maxBlock,
&madrecp->blockedBinaryParms.lbuf,
&madrecp->blockedBinaryParms.pos,
&madrecp->blockedBinaryParms.blockp) != 0) {
(void) madrecSetError(madrecp,err3);
return(3);
}
}
if (madrecp->iotype == 22) { /* Flush Cbf */
if(flushCedarCbfRecord(madrecp->fp, &madrecp->recordp,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.lbuf,
&madrecp->cbfParms.pos,
&madrecp->cbfParms.cosRecordp,
&madrecp->cbfParms.blockNumber,
&madrecp->cbfParms.previousFileIndex,
&madrecp->cbfParms.previousRecordIndex,
&madrecp->cbfParms.lastControlWord) != 0) {
(void) madrecSetError(madrecp,err3);
return(3);
}
if(endFileCedarCbfRecord(madrecp->fp, &madrecp->recordp,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.previousFileIndex,
&madrecp->cbfParms.lastControlWord) != 0) {
(void) madrecSetError(madrecp,err1);
return(3);
}
if(endDataCedarCbfRecord(madrecp->fp, &madrecp->recordp,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.lastControlWord) != 0) {
(void) madrecSetError(madrecp,err1);
return(3);
}
}
if (madrecp->fp != (FILE *)NULL && fclose(madrecp->fp) != 0) {
(void) madrecSetError(madrecp,err1);
return(1);
}
madrecp->fp = (FILE *)NULL;
if (madrecp->filnam != (char *)NULL) {
free(madrecp->filnam);
madrecp->filnam = (char *)NULL;
}
madrecp->fd = 0;
madrecp->file_status = 0;
madrecp->iotype = 0;
madrecp->fileSize = 0;
madrecp->pos = 0;
madrecp->nrecords = 0;
madrecp->currentRecord = -1;
(void) madrecDeleteKeys (madrecp);
madrecp->madrigalParms.blockSize = 6720;
madrecp->madrigalParms.sigWords = 0;
madrecp->madrigalParms.blockIndex = 0;
if (madrecp->madrigalParms.blockp != (Int16 *)NULL) {
free(madrecp->madrigalParms.blockp);
madrecp->madrigalParms.blockp = (Int16 *)NULL;
}
madrecp->madrigalParms.prevRec = 0;
madrecp->madrigalParms.thisRec = 0;
madrecp->blockedBinaryParms.pos = 1;
madrecp->blockedBinaryParms.lBlock = -1;
madrecp->blockedBinaryParms.maxBlock = 0;
madrecp->blockedBinaryParms.lbuf = 2;
if (madrecp->blockedBinaryParms.blockp != (Int16 *)NULL) {
free(madrecp->blockedBinaryParms.blockp);
madrecp->blockedBinaryParms.blockp = (Int16 *)NULL;
}
madrecp->cbfParms.blockSize = 4096;
madrecp->cbfParms.pos = 0; /* must be 1 for put */
if (madrecp->cbfParms.cosRecordp != (Int16 *) NULL) {
free(madrecp->cbfParms.cosRecordp);
madrecp->cbfParms.cosRecordp = (Int16 *)NULL;
}
madrecp->cbfParms.lCosBlock = 0;
madrecp->cbfParms.fwi = 0;
madrecp->cbfParms.initPos8 = 0;
madrecp->cbfParms.initFwi = 0;
madrecp->cbfParms.initPos = 0;
madrecp->cbfParms.initLCosBlock = 0;
madrecp->cbfParms.lbuf = 2;
madrecp->cbfParms.blockNumber = 0;
madrecp->cbfParms.previousFileIndex = -1;
madrecp->cbfParms.previousRecordIndex = -1;
madrecp->cbfParms.lastControlWord = -1;
madrecp->unblockedBinaryParms.placeHolder = 0;
madrecp->asciiParms.placeHolder = 0;
return(0);
}
else {
(void) madrecSetError(madrecp,err2);
madrecp->fd = 0;
madrecp->file_status = 0;
return(2);
}
}
/***********************************************************************
*
* madrecGetNextRec reads a cedar record and fills a Madrec structure
* with the information in the record.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 - Record read successfully
* 1 - Illegal file type (bad iotype in madrec)
* -n - Error in CedarIO package
*
*/
int
madrecGetNextRec (Madrec *madrecp)
{
int ind=0;
static const char *err1="madrecGetNextRec error - illegal file type";
char err[132];
if (madrecp->iotype == 10) { /* Read Madrigal */
ind = getNextMadrigalRecord(madrecp->fp, &madrecp->recordp,
madrecp->madrigalParms.blockSize,
&madrecp->madrigalParms.sigWords);
if (ind != 0 && ind != -1) {
if (ind == -6)
(void) sprintf(err, "Impossibly short record found in getNextMadrigalRecord\n");
else if (ind == -9)
(void) sprintf(err, "lprol != 21 found in getNextMadrigalRecord\n");
else
(void) sprintf(err, "Error %d in getNextMadrigalRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
madrecp->pos = ftell(madrecp->fp)/2;
} else if (madrecp->iotype == 11) { /* Read blocked binary */
ind = getNextCedarBlockedRecord(madrecp->fp, &madrecp->recordp,
&madrecp->blockedBinaryParms.lBlock,
&madrecp->blockedBinaryParms.pos);
if (ind != 0 && ind != -1) {
(void) sprintf(err, "Error %d in getNextCedarBlockedRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
madrecp->pos = ftell(madrecp->fp)/2;
} else if (madrecp->iotype == 12) { /* Read Cbf */
/* Cbf files can contain multiple Cedar files. Here we ignore ind=-1
which indicates end of Cedar file. The end of the Cbf file is
indicated by ind=-2. This is changed to ind=-1 to indicate
end of file. Thus, all the Cedar records in the Cbf file appear
as a single file. Typically header records will appear at the
beginning of each of the Cedar files included in the Cbf file */
while ((
ind = getNextCedarCbfRecord(madrecp->fp, &madrecp->recordp, 0,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.initPos8,
&madrecp->cbfParms.initFwi,
&madrecp->cbfParms.initPos,
&madrecp->cbfParms.initLCosBlock,
&madrecp->cbfParms.lCosBlock,
&madrecp->cbfParms.pos,
&madrecp->cbfParms.fwi,
&madrecp->cbfParms.cosRecordp))==-1);
if (ind != 0 && ind != -1 && ind != -2) {
(void) sprintf(err, "Error %d in getNextCedarCbfRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
madrecp->pos = ftell(madrecp->fp)/2;
if (ind == -2) {
ind = -1;
}
} else if (madrecp->iotype == 13) { /* Read unblocked binary */
ind = getNextCedarUnblockedRecord(madrecp->fp, &madrecp->recordp);
if (ind != 0 && ind != -1) {
(void) sprintf(err, "Error %d in getNextCedarUnblockedRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
madrecp->pos = ftell(madrecp->fp)/2;
} else if (madrecp->iotype == 14) { /* Read ascii */
ind = getNextCedarAsciiRecord(madrecp->fp, &madrecp->recordp);
if (ind != 0 && ind != -1) {
if (ind == -4)
(void) sprintf(err, "Integer out of 16 bit range found in getNextCedarAsciiRecord\n");
else
(void) sprintf(err, "Error %d in getNextCedarAsciiRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
madrecp->pos = ftell(madrecp->fp);
} else if (madrecp->iotype == 40 ||
madrecp->iotype == 41 ||
madrecp->iotype == 42 ||
madrecp->iotype == 43 ||
madrecp->iotype == 44 ||
madrecp->iotype == 60 ||
madrecp->iotype == 61 ||
madrecp->iotype == 62 ||
madrecp->iotype == 63 ||
madrecp->iotype == 64) { /* Read memory */
ind = getMemNextCedarUnblockedRecord(&madrecp->filep,
&madrecp->recordp,
&madrecp->pos,
&madrecp->recordpInMem);
if (ind != 0 && ind != -1) {
(void) sprintf(err, "Error %d in getMemNextCedarUnblockedRecord\n", ind);
(void) madrecSetError(madrecp,err);
}
} else {
ind = 1;
(void) madrecSetError(madrecp,err1);
}
madrecp->currentRecord++;
return(ind);
}
/***********************************************************************
*
* madrecPutNextRec writes a cedar record.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
* 1 - Illegal file type (bad iotype in madrec)
* -n - Error in CedarIO package
*
*/
int
madrecPutNextRec (Madrec *madrecp)
{
int ind=0;
static const char *err1="madrecPutNextRec error - illegal file type";
static const char *err2="madrecPutNextRec error - error in cedarIO package";
if (madrecp->iotype == 2 ||
madrecp->iotype == 20) { /* Write Madrigal */
ind = putNextMadrigalRecord(madrecp->fp, &madrecp->recordp,
madrecp->madrigalParms.blockSize,
&madrecp->madrigalParms.blockIndex,
&madrecp->madrigalParms.blockp,
&madrecp->madrigalParms.prevRec,
&madrecp->madrigalParms.thisRec);
} else if (madrecp->iotype == 21) { /* Write blocked binary */
ind = putNextCedarBlockedRecord(madrecp->fp, &madrecp->recordp,
&madrecp->blockedBinaryParms.maxBlock,
&madrecp->blockedBinaryParms.lbuf,
&madrecp->blockedBinaryParms.pos,
&madrecp->blockedBinaryParms.blockp);
} else if (madrecp->iotype == 22) { /* Write Cbf */
ind = putNextCedarCbfRecord(madrecp->fp, &madrecp->recordp,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.lbuf,
&madrecp->cbfParms.pos,
&madrecp->cbfParms.cosRecordp,
&madrecp->cbfParms.blockNumber,
&madrecp->cbfParms.previousFileIndex,
&madrecp->cbfParms.previousRecordIndex,
&madrecp->cbfParms.lastControlWord);
} else if (madrecp->iotype == 23) { /* Write unblocked binary */
ind = putNextCedarUnblockedRecord(madrecp->fp, &madrecp->recordp);
} else if (madrecp->iotype == 24) { /* Write ascii */
ind = putNextCedarAsciiRecord(madrecp->fp, &madrecp->recordp);
} else if (madrecp->iotype == 40 ||
madrecp->iotype == 41 ||
madrecp->iotype == 42 ||
madrecp->iotype == 43 ||
madrecp->iotype == 44 ||
madrecp->iotype == 60 ||
madrecp->iotype == 61 ||
madrecp->iotype == 62 ||
madrecp->iotype == 63 ||
madrecp->iotype == 64) {
/* Write memory */
ind = putMemNextCedarUnblockedRecord(&madrecp->filep,
&madrecp->recordp,
&madrecp->fileSize,
&madrecp->pos);
} else {
ind = 1;
(void) madrecSetError(madrecp,err1);
}
if (ind != 0 && ind != -1 && ind != 1) {
(void) madrecSetError(madrecp,err2);
}
return(ind);
}
/***********************************************************************
*
* madrecRewind rewinds a cedar record.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
* 1 - Illegal file type (bad iotype in madrec)
* -n - Error in CedarIO package
*
*/
int
madrecRewind (Madrec *madrecp)
{
int iotype=0, nrecords=0;
char *filnam;
static const char *err1="madrecRewind error - No file to rewind";
if (madrecp->iotype > 24 && madrecp->iotype < 65) { /* Rewind memory file */
madrecp->pos = 0;
} else { /* Just close and open file */
iotype = madrecp->iotype;
if (madrecp->filnam != (char *)NULL) {
filnam = (char *)malloc(strlen(madrecp->filnam)+1);
(void) strcpy(filnam, madrecp->filnam);
nrecords = madrecp->nrecords;
(void) madrecClose(madrecp);
(void) madrecOpen(madrecp, iotype, filnam);
free(filnam);
madrecp->nrecords = nrecords;
} else {
(void) madrecSetError(madrecp,err1);
return(1);
}
}
return(0);
}
/***********************************************************************
*
* madrecGetPreviousRec reads an madrigal record and fills a Mad
* structure with the information in the record.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
*
*/
int
madrecGetPreviousRec(Madrec *madrecp)
{
int ind=0;
ind = madrecGetRecByRecno(madrecp, madrecp->currentRecord - 1);
return(ind);
}
/***********************************************************************
*
* madrecGetRecByRecno reads a madrigal record and fills a Mad
* structure with the information in the record.
* The record number is specified by the second
* argument. The first record is recno=0.
*
* arguments:
* madrecp - pointer to the madrec object
* recno - the record number to get. The first record is recno=0.
*
* returns:
* 0 - Record read successfully
* -1 - Specified record not in file
*
*/
int
madrecGetRecByRecno(Madrec *madrecp, int recno)
{
int i=0, ind=0;
static const char *err1="madrecGetRecByRecno error - Specified record is not in file";
static const char *err2="madrecGetRecByRecno error - Operation not supported for this file type";
static const char *err3="madrecGetRecByRecno error - error in cedarIO package";
if (recno < 0) {
(void) madrecSetError(madrecp,err1);
return(-1);
}
/* Generate key table if necessary */
if (madrecp->indexp==(CedarIndex *)NULL && madrecp->iotype!=12) {
ind = madrecGenKeys(madrecp);
}
if ((recno < 0 || recno>madrecp->nrecords-1) && madrecp->iotype!=12) {
(void) madrecSetError(madrecp,err1);
return(-1);
}
if (madrecp->iotype == 10) {
madrecp->madrigalParms.blockSize = madrecp->indexp[recno].int1;
madrecp->madrigalParms.sigWords = madrecp->indexp[recno].int2;
madrecp->pos = madrecp->indexp[recno].pos;
(void) fseek(madrecp->fp, 2*madrecp->pos, SEEK_SET);
ind = getNextMadrigalRecord(madrecp->fp, &madrecp->recordp,
madrecp->madrigalParms.blockSize,
&madrecp->madrigalParms.sigWords);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
madrecp->pos = ftell(madrecp->fp)/2;
madrecp->currentRecord = recno;
} else if (madrecp->iotype == 11) {
madrecp->blockedBinaryParms.pos = madrecp->indexp[recno].int1;
madrecp->blockedBinaryParms.lBlock = madrecp->indexp[recno].int2;
madrecp->pos = madrecp->indexp[recno].pos;
(void) fseek(madrecp->fp, 2*madrecp->pos, SEEK_SET);
ind = getNextCedarBlockedRecord(madrecp->fp, &madrecp->recordp,
&madrecp->blockedBinaryParms.lBlock,
&madrecp->blockedBinaryParms.pos);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
madrecp->currentRecord = recno;
madrecp->pos = ftell(madrecp->fp)/2;
} else if (madrecp->iotype == 12) {
/* Start non-working code */
/* The problem seems to be with reading the cosRecord. */
/*
if (0) {
madrecp->cbfParms.cosRecordp = madrecp->indexp[recno].int16p1;
madrecp->cbfParms.blockSize = madrecp->indexp[recno].int1;
madrecp->cbfParms.pos = madrecp->indexp[recno].int2;
madrecp->cbfParms.lCosBlock = madrecp->indexp[recno].int3;
madrecp->cbfParms.fwi = madrecp->indexp[recno].int4;
madrecp->cbfParms.initPos8 = madrecp->indexp[recno].int5;
madrecp->cbfParms.initFwi = madrecp->indexp[recno].int6;
madrecp->cbfParms.initPos = madrecp->indexp[recno].int7;
madrecp->cbfParms.initLCosBlock = madrecp->indexp[recno].int8;
madrecp->pos = madrecp->indexp[recno].pos;
if (madrecp->cbfParms.cosRecordp != (Int16 *)NULL) {
free(madrecp->cbfParms.cosRecordp);
madrecp->cbfParms.cosRecordp = (Int16 *)NULL;
}
pos = ftell(madrecp->fp);
(void) printf("*%3d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d\n",
madrecp->currentRecord,
madrecp->cbfParms.blockSize,
madrecp->cbfParms.initPos8,
madrecp->cbfParms.initFwi,
madrecp->cbfParms.initPos,
madrecp->cbfParms.initLCosBlock,
madrecp->cbfParms.lCosBlock,
madrecp->cbfParms.pos,
madrecp->cbfParms.fwi,
madrecp->cbfParms.cosRecordp[0],
pos);
madrecp->cbfParms.fwi = madrecp->cbfParms.initFwi;
ind = getNextCedarCbfRecord(madrecp->fp, &madrecp->recordp, 1,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.initPos8,
&madrecp->cbfParms.initFwi,
&madrecp->cbfParms.initPos,
&madrecp->cbfParms.initLCosBlock,
&madrecp->cbfParms.lCosBlock,
&madrecp->cbfParms.pos,
&madrecp->cbfParms.fwi,
&madrecp->cbfParms.cosRecordp);
madrecp->currentRecord = recno;
pos = ftell(madrecp->fp);
(void) printf("*%3d %8d %8d %8d %8d %8d %8d %8d %8d %8d %8d\n",
madrecp->currentRecord,
madrecp->cbfParms.blockSize,
madrecp->cbfParms.initPos8,
madrecp->cbfParms.initFwi,
madrecp->cbfParms.initPos,
madrecp->cbfParms.initLCosBlock,
madrecp->cbfParms.lCosBlock,
madrecp->cbfParms.pos,
madrecp->cbfParms.fwi,
madrecp->cbfParms.cosRecordp[0],
pos);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
madrecp->pos = ftell(madrecp->fp)/2;
}
*/
/*** End non-working code ***/
/* For now, just emulate random read by reading sequentially to
the specified recoprd */
(void) madrecRewind(madrecp);
for (i=0; i<=recno; i++) {
ind = getNextCedarCbfRecord(madrecp->fp, &madrecp->recordp,
0,
madrecp->cbfParms.blockSize,
&madrecp->cbfParms.initPos8,
&madrecp->cbfParms.initFwi,
&madrecp->cbfParms.initPos,
&madrecp->cbfParms.initLCosBlock,
&madrecp->cbfParms.lCosBlock,
&madrecp->cbfParms.pos,
&madrecp->cbfParms.fwi,
&madrecp->cbfParms.cosRecordp);
if (ind != 0 && ind != -1 && ind != -2) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
if (ind == -1 || ind == -2) {
(void) madrecSetError(madrecp,err1);
madrecp->currentRecord = recno;
madrecp->pos = ftell(madrecp->fp)/2;
return(-1);
}
}
madrecp->currentRecord = recno;
} else if (madrecp->iotype == 13) {
madrecp->pos = madrecp->indexp[recno].pos;
(void) fseek(madrecp->fp, 2*madrecp->pos, SEEK_SET);
ind = getNextCedarUnblockedRecord(madrecp->fp, &madrecp->recordp);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
}
madrecp->pos = ftell(madrecp->fp)/2;
madrecp->currentRecord = recno;
} else if (madrecp->iotype == 14) {
madrecp->pos = madrecp->indexp[recno].pos;
(void) fseek(madrecp->fp, madrecp->pos, SEEK_SET);
ind = getNextCedarAsciiRecord(madrecp->fp, &madrecp->recordp);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
madrecp->pos = ftell(madrecp->fp);
madrecp->currentRecord = recno;
} else if (madrecp->iotype == 40 ||
madrecp->iotype == 41 ||
madrecp->iotype == 42 ||
madrecp->iotype == 43 ||
madrecp->iotype == 44 ||
madrecp->iotype == 60 ||
madrecp->iotype == 61 ||
madrecp->iotype == 62 ||
madrecp->iotype == 63 ||
madrecp->iotype == 64) {
madrecp->pos = madrecp->indexp[recno].pos;
ind = editMemNextCedarUnblockedRecord(&madrecp->filep,
&madrecp->recordp,
&madrecp->pos,
&madrecp->recordpInMem);
if (ind != 0 && ind != -1) {
(void) madrecSetError(madrecp,err3);
return(ind);
}
madrecp->currentRecord = recno;
} else {
(void) madrecSetError(madrecp,err2);
return(-2);
}
return(0);
}
/***********************************************************************
*
* madrecGetRecordByKey reads an madrigal record and fills a Mad
* structure with the information in the record.
* The record is the first data record for which key is
* greater than or equal to the start key of the
* record, and less than the start time of the
* following record. Thus, if the specified key
* corresponds to a time within a record, the
* first such record is returned. Header or catalog
* records are never returned.
*
*
* arguments:
* madrecp - pointer to the madrec object
* key - time in seconds since 1/1/1950
*
* returns:
* 0 - if record found
* -1 - if record not found
*
*/
int
madrecGetRecByKey(Madrec *madrecp, double key)
{
int i=0;
int low = 0;
int mid = 0;
int high = 0;
double endKey=0.0;
int beforeFirstDataRec = 0;
static const char *err1="madrecGetRecByKey error - Specified key is beyond last record in file";
/* Generate key table if necessary */
if (madrecp->indexp==(CedarIndex *)NULL) {
(void) madrecGenKeys(madrecp);
}
/* check if key is before first data record endKey. If so, set
beforeFirstDataRec = 1 to return first data record. */
for (i=0; i<madrecp->nrecords-1; i++) {
/* skip header and catalog records to find first data record */
if (!madrecp->indexp[i].isData)
continue;
else if (key <= madrecp->indexp[i].endKey)
{
beforeFirstDataRec = 1;
}
break;
}
/* set low to skip non-data records */
low = i;
high = madrecp->nrecords-1;
if (beforeFirstDataRec) {
/* the correct i has already been found */
mid = i;
} else if (key > madrecp->indexp[madrecp->nrecords-1].endKey) {
/* key after last record, error */
(void) madrecSetError(madrecp,err1);
return(-1);
} else {
/* speed up using binary search */
while (low <= high)
{
mid = (low + high)/2;
/* skip catalog or header records */
while (!madrecp->indexp[mid].isData)
{
/* if this is the last record, then throw an error */
if (mid == madrecp->nrecords-1)
{
(void) madrecSetError(madrecp,err1);
return(-1);
}
else
high++;
mid = (low + high)/2;
}
/* we have a data record , see if its the right one */
if (mid == madrecp->nrecords-1) {
endKey = madrecp->indexp[mid].endKey;
} else {
endKey = madrecp->indexp[mid+1].startKey;
}
if (key >= madrecp->indexp[mid].startKey && key < endKey)
{
/* right record found */
break;
}
else if (key < madrecp->indexp[mid].startKey)
{
/* too high */
high = mid - 1;
}
else
{
/* too low */
low = mid + 1;
}
}
}
(void) madrecGetRecByRecno(madrecp, madrecp->indexp[mid].recNo);
return(0);
}
/***********************************************************************
*
* madrecGenKeys Generates madrec key array. All information needed to
* access records randomly by key or record number is
* saved.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
*
*/
int
madrecGenKeys (Madrec *madrecp)
{
int i=0;
(void) madrecRewind(madrecp);
madrecp->indexp = (CedarIndex *) malloc(3*sizeof(CedarIndex));
/* Set intial iotype-independent state parameters */
madrecp->indexp[0].pos = 0;
madrecp->indexp[0].posPrev = -1;
/* Set initial state parameters for this iotype */
if (madrecp->iotype == 10) {
madrecp->indexp[0].int1 = madrecp->madrigalParms.blockSize;
madrecp->indexp[0].int2 = madrecp->madrigalParms.sigWords;
} else if (madrecp->iotype == 11) {
madrecp->indexp[0].int1 = madrecp->blockedBinaryParms.pos;
madrecp->indexp[0].int2 = madrecp->blockedBinaryParms.lBlock;
} else if (madrecp->iotype == 12) {
madrecp->indexp[0].int16p1 = madrecp->cbfParms.cosRecordp;
madrecp->indexp[0].int1 = madrecp->cbfParms.blockSize;
madrecp->indexp[0].int2 = madrecp->cbfParms.pos;
madrecp->indexp[0].int3 = madrecp->cbfParms.lCosBlock;
madrecp->indexp[0].int4 = madrecp->cbfParms.fwi;
madrecp->indexp[0].int5 = madrecp->cbfParms.initPos8;
madrecp->indexp[0].int6 = madrecp->cbfParms.initFwi;
madrecp->indexp[0].int7 = madrecp->cbfParms.initPos;
madrecp->indexp[0].int8 = madrecp->cbfParms.initLCosBlock;
}
/* Read file and store state parameters for each record */
i = 1;
while ((madrecGetNextRec(madrecp)) == 0) {
/* Set iotype-independent state parameters */
madrecp->indexp[i-1].recNo = i - 1;
madrecp->indexp[i-1].startKey = cedarGetStartIndex(madrecp->recordp);
madrecp->indexp[i-1].endKey = cedarGetEndIndex(madrecp->recordp);
madrecp->indexp[i].pos = madrecp->pos;
madrecp->indexp[i].posPrev = madrecp->indexp[i-1].pos;
if (cedarGetKrec(madrecp->recordp) == HEADERBIN || cedarGetKrec(madrecp->recordp) == HEADERASCII ||
cedarGetKrec(madrecp->recordp) == CATALOGBIN || cedarGetKrec(madrecp->recordp) == CATALOGASCII)
madrecp->indexp[i-1].isData = 0;
else
madrecp->indexp[i-1].isData = 1;
if (cedarGetKrec(madrecp->recordp) == CATALOGBIN || cedarGetKrec(madrecp->recordp) == CATALOGASCII)
madrecp->indexp[i-1].isCatalog = 1;
else
madrecp->indexp[i-1].isCatalog = 0;
/* Set state parameters for this iotype */
if (madrecp->iotype == 10) {
madrecp->indexp[i].int1 = madrecp->madrigalParms.blockSize;
madrecp->indexp[i].int2 = madrecp->madrigalParms.sigWords;
} else if (madrecp->iotype == 11) {
madrecp->indexp[i].int1 = madrecp->blockedBinaryParms.pos;
madrecp->indexp[i].int2 = madrecp->blockedBinaryParms.lBlock;
} else if (madrecp->iotype == 12) {
madrecp->indexp[i-1].int16p1 = madrecp->cbfParms.cosRecordp;
madrecp->indexp[i-1].int1 = madrecp->cbfParms.blockSize;
madrecp->indexp[i-1].int2 = madrecp->cbfParms.pos;
madrecp->indexp[i-1].int3 = madrecp->cbfParms.lCosBlock;
madrecp->indexp[i-1].int4 = madrecp->cbfParms.fwi;
madrecp->indexp[i-1].int5 = madrecp->cbfParms.initPos8;
madrecp->indexp[i-1].int6 = madrecp->cbfParms.initFwi;
madrecp->indexp[i-1].int7 = madrecp->cbfParms.initPos;
madrecp->indexp[i-1].int8 = madrecp->cbfParms.initLCosBlock;
}
/*
(void) printf("*** %4d %8d %4d %6d %f %f %8d %8d %i\n",
i, madrecp->pos, madrecp->nrecords,
madrecp->indexp[i-1].recNo,
madrecp->indexp[i-1].startKey,
madrecp->indexp[i-1].endKey,
madrecp->indexp[i-1].pos,
madrecp->indexp[i-1].posPrev,
madrecp->indexp[i-1].isCatalog);
*/
i++;
madrecp->indexp = (CedarIndex *)realloc(madrecp->indexp,
(i+2)*sizeof(CedarIndex));
}
madrecp->nrecords = i - 1;
return(0);
}
/***********************************************************************
*
* madrecDeleteKeys Deletes madrec key array.
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
*
*/
int
madrecDeleteKeys (Madrec *madrecp)
{
madrecp->pos = 0;
madrecp->nrecords = 0;
madrecp->currentRecord = 0;
if (madrecp->indexp != (CedarIndex *)NULL) {
free(madrecp->indexp);
}
madrecp->indexp = (CedarIndex *)NULL;
return(0);
}
/***********************************************************************
*
* madrecPrintKeys Prints madrec file key table
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
*
*/
int
madrecPrintKeys (Madrec *madrecp)
{
int i=0;
(void) printf("madrecp->nrecords = %d\n", madrecp->nrecords);
for (i=0; i<madrecp->nrecords; i++) {
(void) printf("%5d %f %f %7d %7d %7d %7d %7d %7d\n",
madrecp->indexp[i].recNo,
madrecp->indexp[i].startKey,
madrecp->indexp[i].endKey,
madrecp->indexp[i].pos,
madrecp->indexp[i].posPrev,
madrecp->indexp[i].int5,
madrecp->indexp[i].int6,
madrecp->indexp[i].int7,
madrecp->indexp[i].int8);
}
return(0);
}
/***********************************************************************
*
* madrecCheckFile checks the structure of a madrec data file
*
Block (Physical record) structure:
6720 16bit words (Int16)
word[0] = Total number of significant words in the block
record (all blocks are 13440 bytes long)
word[1] = Pointer to the first word of the first logical
record contained in the block.
(set to zero if the block doesn't contain
any complete logical records i.e. it just
contains the last part of a logical record.)
word[2] = Pointer to the first word of the last logical
record contained in block.
word[word[0]-1] = Checksum.
Logical Records:
word[0 - 15] = Same as NCAR binary logical records.
word[16] = Pointer to word 1 of previous logical record.
-could be contained in previous block.
-Set to zero in the first logical record of the file.
*/
int
madrecCheckFile(Madrec *madrecp)
{
/*
int i=0, nread=0, print=0, int j=0, recf=0, rp=0, ltot=0;
static const char *err1="madrecCheckFile error - Bad block - 1";
static const char *err2="madrecCheckFile error - Bad record - 1";
static const char *err3="madrecCheckFile error - Bad record - 2";
static const char *err4="madrecCheckFile error - Bad checksum";
*/
return(0);
}
/***********************************************************************
*
* madrecCopy Copies logical record from one madrec object to another
*
* arguments:
* madrec1p - pointer to the source madrec object
* madrec2p - pointer to the destination madrec object
*
* returns:
* 0 - Record copied successfully
* 1 - Empty source record
*
*/
int
madrecCopy (Madrec *madrec1p, Madrec *madrec2p)
{
int ltot=0, i=0;
static const char *err1="madrecCopy error - empty source record";
if (madrec1p->recordp == (Int16 *)NULL) {
(void) madrecSetError(madrec1p,err1);
return(1);
}
ltot = madrec1p->recordp[0];
if (madrec2p->recordp != (Int16 *)NULL && !(madrec2p->recordpInMem)) {
free(madrec2p->recordp);
}
madrec2p->recordp = (Int16 *)malloc(ltot*sizeof(Int16));
for (i=0; i<ltot; i++) {
madrec2p->recordp[i] = madrec1p->recordp[i];
}
return(0);
}
/***********************************************************************
*
* madrecGetFileType Gets file type
*
* arguments:
* madrecp - pointer to madrec object
*
*/
int
madrecGetFileType (Madrec *madrecp)
{
return(cedarFileType(madrecp->filnam, MADRIGALBLOCKSIZE, CBFBLOCKSIZE));
}
/***********************************************************************
*
* madrecSetError sets madrec error
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* 0 -
*
*/
int
madrecSetError (Madrec *madrecp, const char *error)
{
free(madrecp->lastError);
madrecp->lastError = (char *)malloc(strlen(error)+1);
(void) strcpy(madrecp->lastError, error);
/*if (madrecp->pflag != 0)
(void) fprintf(stderr, "%s\n", error);*/
madrecp->pflag = 1;
return(0);
}
/***********************************************************************
*
* madrecGetError gets last madrec error
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* error string
*
*/
char *
madrecGetError (Madrec *madrecp)
{
return(madrecp->lastError);
}
/***********************************************************************
*
* madrecGetMissing gets missing data value
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* double precision missing value
*
*/
double
madrecGetMissing (Madrec *madrecp)
{
return(missing);
}
/***********************************************************************
*
* madrecGetNumParms gets number of different parameters in file
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* number of distint parameters
*
*/
int
madrecGetNumParms (Madrec *madrecp)
{
return(madrecp->numParms);
}
/***********************************************************************
*
* madrecGetParmsList gets list (int array) of different parameters
* codes in file
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* codes of distinct parameter
*
* This returned array is a pointer to an internal structure in Madrec;
* it does not need to be freed by the user.
*
*/
int *
madrecGetParmsList (Madrec *madrecp)
{
return(madrecp->parmsListp);
}
/***********************************************************************
*
* madrecGetParmLoc gets location of parameter
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns:
* parameter location:
* 1 - 1D array
* 2 - 2D array
* 3 - Derived
*
*/
int *
madrecGetParmLoc (Madrec *madrecp)
{
return(madrecp->parmLocp);
}
/***********************************************************************
*
* madrecGetParmMin gets minimum value of parameter
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns - Minimum value of parameter in entire file
*
*/
double *
madrecGetParmMin (Madrec *madrecp)
{
return(madrecp->parmMinp);
}
/***********************************************************************
*
* madrecGetParmMax gets maximum value of parameter
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns - Maximum value of parameter in entire file
*
*/
double *
madrecGetParmMax (Madrec *madrecp)
{
return(madrecp->parmMaxp);
}
/***********************************************************************
*
* madrecHasCatalog returns 1 if file has catalog record, 0 otherwise
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns - 1 if file has catalog record, 0 otherwise
*
*/
int madrecHasCatalog(Madrec *madrecp)
{
int i;
/* Generate key table if necessary */
if (madrecp->indexp==(CedarIndex *)NULL) {
madrecGenKeys(madrecp);
}
for (i=0; i < madrecp->nrecords; i++)
{
if (madrecp->indexp[i].isCatalog == 1)
return(1);
}
/* none found */
return(0);
}
/***********************************************************************
*
* madrecHasHeader returns 1 if file has header record, 0 otherwise
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns - 1 if file has header record, 0 otherwise
*
*/
int madrecHasHeader(Madrec *madrecp)
{
int i;
/* Generate key table if necessary */
if (madrecp->indexp==(CedarIndex *)NULL) {
madrecGenKeys(madrecp);
}
for (i=0; i < madrecp->nrecords; i++)
{
if (madrecp->indexp[i].isData == 0 && madrecp->indexp[i].isCatalog == 0)
return(1);
}
/* none found */
return(0);
}
/***********************************************************************
*
* madrecGetSortedRecnoList gets int array of recno's sorted by start time key
*
* arguments:
* madrecp - pointer to the madrec object
*
* returns - int array of recno's sorted by start time key, length = nrecords
*
*/
int * madrecGetSortedRecnoList (Madrec *madrecp)
{
CedarIndex * sortedCedarIndex;
int i;
/* if sortedRecnoList already exists, return it */
if (madrecp->sortedRecnoList != (int *)NULL)
return(madrecp->sortedRecnoList);
/* Generate key table if necessary */
if (madrecp->indexp==(CedarIndex *)NULL) {
madrecGenKeys(madrecp);
}
/* create a temporary copy of madrecp->indexp that we can sort */
sortedCedarIndex = malloc(madrecp->nrecords * sizeof(CedarIndex));
memcpy(sortedCedarIndex, madrecp->indexp, madrecp->nrecords * sizeof(CedarIndex));
/* sort sortedCedarIndex */
qsort(sortedCedarIndex,
madrecp->nrecords,
sizeof(CedarIndex),
compareCedarIndices);
/* allocate memory for madrecp->sortedRecnoList */
madrecp->sortedRecnoList = malloc(madrecp->nrecords * sizeof(int));
/* copy sorted recno from sortedCedarIndex to madrecp->sortedRecnoList */
for (i=0; i < madrecp->nrecords; i++)
{
madrecp->sortedRecnoList[i] = sortedCedarIndex[i].recNo;
}
/* free temporary sorted copy of madrecp->indexp */
free(sortedCedarIndex);
return (madrecp->sortedRecnoList);
}
/***********************************************************************
*
* compareCedarIndices a private method to compare one CedarIndex to another
*
* arguments:
* void * cedarIndex1 - void pointer to the first CedarIndex
* void * cedarIndex2 - void pointer to the second CedarIndex
*
* returns - if cedarIndex1 before cedarIndex2, return -1
* if cedarIndex1 same as cedarIndex2, return 0
* if cedarIndex1 after cedarIndex2, return 1
*
*/
int compareCedarIndices(const void * index1, const void * index2)
{
CedarIndex * cedarIndexp1;
CedarIndex * cedarIndexp2;
/* cast both pointers to * CedarIndex */
cedarIndexp1 = (CedarIndex *)index1;
cedarIndexp2 = (CedarIndex *)index2;
if (cedarIndexp1->startKey < cedarIndexp2->startKey)
{
return -1;
}
else if (cedarIndexp1->startKey > cedarIndexp2->startKey)
{
return 1;
}
/* otherwise startKeys are equal - now compare endKeys
To make header record come first, a later end key comes first */
if (cedarIndexp1->endKey > cedarIndexp2->endKey)
{
return -1;
}
else if (cedarIndexp1->endKey < cedarIndexp2->endKey)
{
return 1;
}
/* both startKey and endKey are equal */
return 0;
}