/******************************************************************************
*
* NSSDC/CDF CDF library hyper functions.
*
* Version 1.4, 26-Jun-96, Hughes STX.
*
* Modification history:
*
* V1.0 20-May-92, J Love Original version. These functions were taken
* out of `cdflib.c'.
* V1.1 16-Sep-92, J Love CDF V2.3 (shareable/NeXT/zVar).
* V1.2 22-Nov-93, J Love CDF 2.4. New hyper algorithms.
* V1.3 7-Dec-94, J Love CDF V2.5.
* V1.3a 6-Jan-95, J Love Encode/decode changes. More cache-residency.
* V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f.
* V1.4 26-Jun-96, J Love CDF V2.6.
* V1.5 26-May-98, M Liu Add a parameter for HyperReadDim and
* HyperWriteDim function calls. For
* reading/writing data values of a non-full
* physical record, a temp. buffer is used to cut
* down the physical I/Os.
* V2.0 29-Jun-04, M Liu Added LFS (Large File Support > 2G).
*
******************************************************************************/
#include "cdflib.h"
#include "cdflib64.h"
/******************************************************************************
* HyperRead64.
******************************************************************************/
STATICforIDL CDFstatus HyperRead64 (CDF, Var, rd, buffer)
struct CDFstruct *CDF;
struct VarStruct *Var;
struct rdSTRUCT *rd;
void *buffer;
{
Int32 nHypRecValues, nHypRecBytes, nHypDimValues[CDF_MAX_DIMS];
Logical fullPhyRec, fullPhyDim[CDF_MAX_DIMS];
Int32 firstHypRec, lastHypRec, firstPhyRec;
Int32 recNum, nValues, nRecords, phyRecN, i; Byte *tBuffer, *phyBuffer;
CDFstatus pStatus = CDF_OK;
int dimN, dimNt;
int firstDim; /* Based on majority, the "highest" dimension
(changes the slowest in memory/on disk). */
int doneDim; /* When cycling through the dimensions, the
dimension at which to stop (the dimension
beyond the last). */
int dimIncr; /* How to cycle through the dimensions. Incr-
ementing (+1) for row-major, decrementing
(-1) for column-major. */
/****************************************************************************
* Determine dimension ordering.
****************************************************************************/
if (Var->numDims > 0) {
firstDim = (int) (CDF->rowMajor ? 0 : Var->numDims - 1);
doneDim = (int) (CDF->rowMajor ? Var->numDims : -1);
dimIncr = (CDF->rowMajor ? 1 : -1);
}
/****************************************************************************
* Determine if full physical dimensions can be read. In order for this to
* be so for a particular dimension...
* 1. If the dimension variance is TRUE, then the entire dimension must be
* read (the count equal to the size). If the dimension variance is
* FALSE, the count must be equal to one (only reading the single
* physical value).
* 2. For each `lower' dimension having a TRUE variance, the entire
* dimension must be read (the count equal to the size).
* 3. For each `lower' dimension having a FALSE variance, the count must
* be equal to one (only reading the single physical dimension).
* Also determine if full physical records can be read. If there are one or
* more dimensions, this depends on whether or not the first dimension can be
* read with a single physical read. If there are zero dimensions, then this
* is always true.
****************************************************************************/
if (Var->numDims > 0) {
for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
fullPhyDim[dimN] = TRUE;
for (dimNt = dimN; dimNt != doneDim; dimNt += dimIncr)
if ((Var->dimVarys[dimNt] &&
rd->dimCounts[dimNt] != Var->dimSizes[dimNt]) ||
(!Var->dimVarys[dimNt] && rd->dimCounts[dimNt] > 1)) {
fullPhyDim[dimN] = FALSE;
break;
}
}
fullPhyRec = fullPhyDim[firstDim];
}
else
fullPhyRec = TRUE;
/****************************************************************************
* Determine if only one read is needed. In order for this to be so...
* 1. Full physical records must be being read, and
* 2a. If the record variance is TRUE, then the record interval must be one
* (or a record count of one) so that there is no skipping of records
* 2b. If the record variance is FALSE.
****************************************************************************/
firstHypRec = rd->recNumber;
lastHypRec = firstHypRec + (rd->recInterval * (rd->recCount - 1));
firstPhyRec = (Var->recVary ? firstHypRec : 0);
if (fullPhyRec &&
((Var->recVary && (rd->recInterval == 1 || rd->recCount == 1))
||
(!Var->recVary))) {
nRecords = lastHypRec - firstHypRec + 1;
nValues = nRecords * Var->NphyRecValues;
if (!sX(ReadVarValues64(CDF,Var,firstPhyRec,
INT32_ZERO,nValues,buffer),&pStatus)) return pStatus;
return pStatus;
}
/****************************************************************************
* A single read was not possible - read one record at a time.
****************************************************************************/
if (Var->numDims > 0) {
for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
nHypDimValues[dimN] = 1;
for (dimNt = dimN + dimIncr; dimNt != doneDim; dimNt += dimIncr)
nHypDimValues[dimN] *= rd->dimCounts[dimNt];
}
nHypRecValues = nHypDimValues[firstDim] * rd->dimCounts[firstDim];
}
else
nHypRecValues = 1;
nHypRecBytes = nHypRecValues * Var->NvalueBytes;
for (i = 0, recNum = rd->recNumber, tBuffer = buffer; i < rd->recCount;
i++, recNum += rd->recInterval, tBuffer += (size_t) nHypRecBytes) {
phyRecN = BOO(Var->recVary,recNum,0);
if (fullPhyRec) {
/*******************************************************************
* The full physical record is being read, use one physical read.
*******************************************************************/
if (!sX(ReadVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,
tBuffer),&pStatus)) return pStatus;
}
else {
/*******************************************************************
* Less than the full physical record is to be read. Allocate a
* physical record buffer if possible and read in the whole record
* and extract values from the buffer. Otherwise, get one value at a
* time from the file
*******************************************************************/
phyBuffer = (Byte *) cdf_AllocateMemory((size_t) Var->NphyRecBytes,NULL);
if (phyBuffer != NULL) {
if (!sX(ReadVarValues64(CDF,Var,phyRecN,INT32_ZERO,Var->NphyRecValues,
phyBuffer),&pStatus)) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
}
if (!sX(HyperReadDim64(Var->numDims,Var->dimSizes,
Var->dimVarys,rd->dimIndices,
rd->dimCounts,rd->dimIntervals,
nHypDimValues,Var->nPhyDimValues,
fullPhyDim,firstDim,dimIncr,
phyRecN,INT32_ZERO,tBuffer,phyBuffer,
CDF,Var),&pStatus)) {
if (phyBuffer != NULL) cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
if (phyBuffer != NULL) cdf_FreeMemory(phyBuffer,NULL);
}
}
return pStatus;
}
/******************************************************************************
* HyperReadDim64. DANGER, DANGER, I'm recursive.
* NOTE: This routine could be called for a record which is virtual.
******************************************************************************/
STATICforIDL CDFstatus HyperReadDim64 (numDims, dimSizes, dimVarys, indices,
counts, intervals, nHypDimValues,
nPhyDimValues, fullPhyDim, firstDim,
dimIncr, recNum, offset, buffer, phyBuffer,
CDF, Var)
Int32 numDims;
Int32 *dimSizes;
Int32 *dimVarys;
Int32 *indices;
Int32 *counts;
Int32 *intervals;
Int32 *nHypDimValues;
Int32 *nPhyDimValues;
Logical *fullPhyDim;
int firstDim;
int dimIncr;
Int32 recNum;
Int32 offset; /* Byte offset within record. */
void *buffer;
void *phyBuffer;
struct CDFstruct *CDF;
struct VarStruct *Var;
{
Int32 tOffset; Int32 nValues, i; Byte *tBuffer; CDFstatus pStatus = CDF_OK;
/****************************************************************************
* What to do depends on the number of dimensions. Note that this function
* should never be called with zero dimensions.
****************************************************************************/
switch (numDims) {
case 1: {
/************************************************************************
* One dimension - read the values along the dimension.
************************************************************************/
if (dimVarys[0]) {
/**********************************************************************
* Dimension variance of TRUE, no virtual values to deal with - read
* physical values.
**********************************************************************/
if (intervals[0] == 1) {
/********************************************************************
* A contiguous strip of values.
********************************************************************/
tOffset = offset + (indices[0] * Var->NvalueBytes);
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,
tOffset,counts[0],
buffer),&pStatus)) return pStatus;
} else {
memmove (buffer, (size_t) tOffset + (Byte *) phyBuffer,
(size_t) (Var->NvalueBytes * counts[0]));
}
}
else {
/********************************************************************
* Not contiguous, read one value at a time skipping over unwanted
* values.
********************************************************************/
tOffset = offset + (indices[0] * Var->NvalueBytes);
tBuffer = buffer;
for (i = 0; i < counts[0]; i++) {
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,
tOffset,INT32_ONE,
tBuffer),&pStatus)) return pStatus;
} else {
memmove (tBuffer, (size_t) tOffset+(Byte *) phyBuffer,
(size_t) Var->NvalueBytes);
}
tOffset += (intervals[0] * Var->NvalueBytes);
tBuffer += (size_t) Var->NvalueBytes;
}
}
}
else {
/**********************************************************************
* Dimension variance of FALSE, only one physical value exists. If the
* count is greater than one, virtual values will have to be generated.
**********************************************************************/
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,offset,
INT32_ONE,buffer),&pStatus)) return pStatus;
} else {
memmove(buffer, (size_t) offset + (Byte *) phyBuffer,
(size_t) Var->NvalueBytes);
}
if (counts[0] > 1) {
for (i = 1, tBuffer = (Byte *) buffer + (size_t) Var->NvalueBytes;
i < counts[0]; i++, tBuffer += (size_t) Var->NvalueBytes) {
memmove (tBuffer, buffer, (size_t) Var->NvalueBytes);
}
}
}
break;
}
default: {
/************************************************************************
* Two or more dimensions.
************************************************************************/
Int32 nPhyDimBytes = nPhyDimValues[firstDim] * Var->NvalueBytes;
Int32 nHypDimBytes = nHypDimValues[firstDim] * Var->NvalueBytes;
int nextDim = firstDim + dimIncr;
if (dimVarys[firstDim]) {
/**********************************************************************
* The first dimension's variance is TRUE. If the interval is one and
* only a single read is necessary for the "lower" dimension, use a
* single read. Otherwise, cycle through that dimension physically
* reading each subarray below it (skipping subarrays if necessary).
**********************************************************************/
if (intervals[firstDim] == 1 && fullPhyDim[nextDim]) {
tOffset = offset + (indices[firstDim] * nPhyDimBytes);
nValues = counts[firstDim] * nPhyDimValues[firstDim];
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,
tOffset,nValues,
buffer),&pStatus)) return pStatus;
} else {
memmove(buffer, (size_t) tOffset + (Byte *) phyBuffer,
(size_t) (Var->NvalueBytes * nValues));
}
}
else {
tOffset = offset + (indices[firstDim] * nPhyDimBytes);
tBuffer = buffer;
for (i = 0; i < counts[firstDim]; i++) {
if (fullPhyDim[nextDim]) {
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,
tOffset,nPhyDimValues[firstDim],
tBuffer),&pStatus)) return pStatus;
} else {
memmove(tBuffer, (size_t) tOffset + (Byte *) phyBuffer,
(size_t) (Var->NvalueBytes * nPhyDimValues[firstDim]));
}
}
else {
int numDimsT = (int) (numDims - 1);
int firstDimT = (CDF->rowMajor ? 0 : numDimsT - 1);
int passDimT = (CDF->rowMajor ? 1 : 0);
if (!sX(HyperReadDim64(numDimsT,&dimSizes[passDimT],
&dimVarys[passDimT],
&indices[passDimT],
&counts[passDimT],
&intervals[passDimT],
&nHypDimValues[passDimT],
&nPhyDimValues[passDimT],
&fullPhyDim[passDimT],firstDimT,
dimIncr,recNum,tOffset,tBuffer,phyBuffer,
CDF,Var),&pStatus)) return pStatus;
}
tOffset += (intervals[firstDim] * nPhyDimBytes);
tBuffer += (size_t) nHypDimBytes;
}
}
}
else {
/**********************************************************************
* The first dimension's variance is FALSE, physically read the only
* existing subarray and generate virtual subarrays if necessary.
**********************************************************************/
if (fullPhyDim[nextDim]) {
if (phyBuffer == NULL) {
if (!sX(ReadVarValues64(CDF,Var,recNum,offset,
nPhyDimValues[firstDim],
buffer),&pStatus)) return pStatus;
} else {
memmove(buffer, (size_t) offset + (Byte *) phyBuffer,
(size_t) (Var->NvalueBytes * nPhyDimValues[firstDim]));
}
}
else {
int numDimsT = (int) (numDims - 1);
int firstDimT = (CDF->rowMajor ? 0 : numDimsT - 1);
int passDimT = (CDF->rowMajor ? 1 : 0);
if (!sX(HyperReadDim64(numDimsT,&dimSizes[passDimT],
&dimVarys[passDimT],&indices[passDimT],
&counts[passDimT],&intervals[passDimT],
&nHypDimValues[passDimT],
&nPhyDimValues[passDimT],
&fullPhyDim[passDimT],firstDimT,
dimIncr,recNum,offset,buffer,phyBuffer,
CDF,Var),&pStatus)) return pStatus;
}
if (counts[firstDim] > 1) {
for (i = 1, tBuffer = (Byte *) buffer + (size_t) nHypDimBytes;
i < counts[firstDim]; i++, tBuffer += (size_t) nHypDimBytes) {
memmove (tBuffer, buffer, (size_t) nHypDimBytes);
}
}
}
break;
}
}
return pStatus;
}
/******************************************************************************
* HyperWrite64.
******************************************************************************/
STATICforIDL CDFstatus HyperWrite64 (CDF, Var, rd, buffer)
struct CDFstruct *CDF;
struct VarStruct *Var;
struct rdSTRUCT *rd;
void *buffer;
{
Int32 nHypRecValues, nHypRecBytes, nHypDimValues[CDF_MAX_DIMS];
Logical fullPhyRec, fullPhyDim[CDF_MAX_DIMS];
Int32 firstPhyRec, phyRecN, nValues; Byte *tBuffer; int dimN; Int32 i;
CDFstatus pStatus = CDF_OK; Byte *phyBuffer;
int firstDim; /* Based on majority, the "highest" dimension
(changes the slowest in memory/on disk). */
int doneDim; /* When cycling through the dimensions, the
dimension at which to stop (the dimension
beyond the last). */
int dimIncr; /* How to cycle through the dimensions. Incr-
ementing (+1) for row-major, decrementing
(-1) for column-major. */
/****************************************************************************
* Determine dimension ordering.
****************************************************************************/
if (Var->numDims > 0) {
firstDim = (int) (CDF->rowMajor ? 0 : Var->numDims - 1);
doneDim = (int) (CDF->rowMajor ? Var->numDims : -1);
dimIncr = (CDF->rowMajor ? 1 : -1);
}
/****************************************************************************
* Determine if full physical dimensions can be written. In order for this to
* be so for a particular dimension...
* 1. If the dimension variance is TRUE, then the entire dimension must be
* written (the count equal to the size). If the dimension variance is
* FALSE, the count must be equal to one (only writing the single
* physical value).
* 2. For each `lower' dimension having a TRUE variance, the entire
* dimension must be written (the count equal to the size).
* 3. For each `lower' dimension having a FALSE variance, the count must
* be equal to one (only writing the single physical dimension).
* Also determine if full physical records can be written. If there are one
* or more dimensions, this depends on whether or not the first dimension can
* be written with a single physical write. If there are zero dimensions,
* then this is always true.
****************************************************************************/
if (Var->numDims > 0) {
for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
int dimNt;
fullPhyDim[dimN] = TRUE;
for (dimNt = dimN; dimNt != doneDim; dimNt += dimIncr)
if ((Var->dimVarys[dimNt] &&
rd->dimCounts[dimNt] != Var->dimSizes[dimNt]) ||
(!Var->dimVarys[dimNt] && rd->dimCounts[dimNt] > 1)) {
fullPhyDim[dimN] = FALSE;
break;
}
}
fullPhyRec = fullPhyDim[firstDim];
}
else
fullPhyRec = TRUE;
/****************************************************************************
* Determine if only one write is needed. In order for this to be so...
* 1. Full physical records must be being written.
* 2. A record variance of FALSE, or if the record variance is TRUE, then
* the record interval must be one (or a record count of one) so that
* there is no skipping of records.
****************************************************************************/
phyRecN = 0;
if (fullPhyRec &&
((Var->recVary && (rd->recInterval == 1 || rd->recCount == 1)) ||
(!Var->recVary))) {
if (Var->recVary) {
phyRecN = rd->recNumber;
tBuffer = buffer;
nValues = rd->recCount * Var->NphyRecValues;
}
else {
tBuffer = (Byte *) buffer +
(size_t) (Var->NphyRecBytes * (rd->recCount-1));
nValues = Var->NphyRecValues;
}
if (!sX(WriteVarValues64(CDF,Var,phyRecN,INT32_ZERO,
nValues,tBuffer),&pStatus)) return pStatus;
return pStatus;
}
/****************************************************************************
* Only one write not possible - will have to write one record at a time.
* First calculate size of hyper records.
****************************************************************************/
if (Var->numDims > 0) {
for (dimN = firstDim; dimN != doneDim; dimN += dimIncr) {
int dimNt;
nHypDimValues[dimN] = 1;
for (dimNt = dimN + dimIncr; dimNt != doneDim; dimNt += dimIncr)
nHypDimValues[dimN] *= rd->dimCounts[dimNt];
}
nHypRecValues = nHypDimValues[firstDim] * rd->dimCounts[firstDim];
}
else
nHypRecValues = 1;
nHypRecBytes = nHypRecValues * Var->NvalueBytes;
firstPhyRec = BOO(Var->recVary,rd->recNumber,0);
/****************************************************************************
* Write each record.
****************************************************************************/
if (Var->recVary) {
/**************************************************************************
* A TRUE record variance - write each physical record.
**************************************************************************/
for (i = 0, phyRecN = firstPhyRec, tBuffer = buffer;
i < rd->recCount;
i++, phyRecN += rd->recInterval, tBuffer += (size_t) nHypRecBytes) {
if (fullPhyRec) {
/*********************************************************************
* The full physical record is being written, use one physical write.
*********************************************************************/
if (!sX(WriteVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,
tBuffer),&pStatus)) return pStatus;
}
else {
/*********************************************************************
* Less than the full physical record is to be written.
* physical record buffer if possible and fill in the whole record
* with values from the buffer. Otherwise, write one value at a
* time to the file
*********************************************************************/
phyBuffer = (Byte *) cdf_AllocateMemory((size_t) Var->NphyRecBytes,NULL);
if (phyBuffer != NULL) {
if (!sX(ReadVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,
phyBuffer),&pStatus)) {
if (pStatus != VIRTUAL_RECORD_DATA) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
else { /* Don't want it to stop. */
pStatus = CDF_OK;
}
}
}
if (!sX(HyperWriteDim64(Var->numDims,Var->dimSizes,
Var->dimVarys,rd->dimIndices,
rd->dimCounts,rd->dimIntervals,
nHypDimValues,Var->nPhyDimValues,
fullPhyDim,firstDim,
dimIncr,phyRecN,INT32_ZERO,tBuffer,phyBuffer,
CDF,Var),&pStatus)) {
if (phyBuffer != NULL) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
}
if (phyBuffer != NULL) {
if (!sX(WriteVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,phyBuffer),&pStatus)) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
cdf_FreeMemory(phyBuffer,NULL);
}
}
}
}
else {
/**************************************************************************
* A FALSE record variance. Only one physical record to actually be
* written. No need to check if a full physical record can be written
* since that case would have been handled above (because of the FALSE
* record variance). If the record count is greater than one, the LAST
* record in the buffer will be written (as if the records before it had
* been written but then overwritten by the last one).
**************************************************************************/
tBuffer = (Byte *) buffer + (size_t) (nHypRecBytes * (rd->recCount - 1));
phyBuffer = (Byte *) cdf_AllocateMemory((size_t) Var->NphyRecBytes,NULL);
if (phyBuffer != NULL) {
if (!sX(ReadVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,
phyBuffer),&pStatus)) {
if (pStatus != VIRTUAL_RECORD_DATA) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
else { /* Don't want it to stop */
pStatus = CDF_OK;
}
}
}
if (!sX(HyperWriteDim64(Var->numDims,Var->dimSizes,Var->dimVarys,
rd->dimIndices,rd->dimCounts,
rd->dimIntervals,nHypDimValues,
Var->nPhyDimValues,fullPhyDim,
firstDim,dimIncr,
INT32_ZERO,INT32_ZERO,tBuffer,phyBuffer,
CDF,Var),&pStatus)) {
if (phyBuffer != NULL) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
}
if (phyBuffer != NULL) {
if (!sX(WriteVarValues64(CDF,Var,phyRecN,INT32_ZERO,
Var->NphyRecValues,phyBuffer),&pStatus)) {
cdf_FreeMemory(phyBuffer,NULL);
return pStatus;
}
cdf_FreeMemory(phyBuffer,NULL);
}
}
return pStatus;
}
/******************************************************************************
* HyperWriteDim64. DANGER, DANGER, I'm recursive.
******************************************************************************/
STATICforIDL CDFstatus HyperWriteDim64 (numDims, dimSizes, dimVarys, indices,
counts, intervals, nHypDimValues,
nPhyDimValues, fullPhyDim, firstDim,
dimIncr, recNum, offset, buffer,
phyBuffer, CDF, Var)
Int32 numDims;
Int32 *dimSizes;
Int32 *dimVarys;
Int32 *indices;
Int32 *counts;
Int32 *intervals;
Int32 *nHypDimValues;
Int32 *nPhyDimValues;
Logical *fullPhyDim;
int firstDim;
int dimIncr;
Int32 recNum; /* Record number for this write. */
Int32 offset; /* Byte offset within record at which to begin. */
void *buffer;
void *phyBuffer;
struct CDFstruct *CDF;
struct VarStruct *Var;
{
Int32 tOffset; Int32 i, nValues; Byte *tBuffer;
CDFstatus pStatus = CDF_OK;
/****************************************************************************
* What to do depends on the number of dimensions. Note that this function
* should never be called with zero dimensions.
****************************************************************************/
switch (numDims) {
case 1: {
/************************************************************************
* One dimension - write the values along the dimension.
************************************************************************/
if (dimVarys[0]) {
/**********************************************************************
* Dimension variance of TRUE, there are no virtual values to deal
* with (skip) - read physical values.
**********************************************************************/
if (intervals[0] == 1) {
/********************************************************************
* A contiguous strip of values.
********************************************************************/
tOffset = offset + (indices[0] * Var->NvalueBytes);
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,
tOffset,counts[0],
buffer),&pStatus)) return pStatus;
} else {
memmove ((size_t) tOffset + (Byte *) phyBuffer, buffer,
(size_t) (Var->NvalueBytes * counts[0]));
}
}
else {
/********************************************************************
* Not contiguous, write one value at a time skipping over physical
* values not being written.
********************************************************************/
tOffset = offset + (indices[0] * Var->NvalueBytes);
tBuffer = buffer;
for (i = 0; i < counts[0]; i++) {
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,
tOffset,INT32_ONE,
tBuffer),&pStatus)) return pStatus;
} else {
memmove ((size_t) tOffset+(Byte *) phyBuffer, tBuffer,
(size_t) Var->NvalueBytes);
}
tOffset += (intervals[0] * Var->NvalueBytes);
tBuffer += (size_t) Var->NvalueBytes;
}
}
}
else {
/**********************************************************************
* Dimension variance of FALSE, only one physical value to be written.
* If the count is greater than one, skip to the last value in the
* buffer (this is an unlikely situation).
**********************************************************************/
tBuffer = (Byte *) buffer +
(size_t) (Var->NvalueBytes * (counts[0] - 1));
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,offset,
INT32_ONE,tBuffer),&pStatus)) return pStatus;
} else {
memmove((size_t) offset + (Byte *) phyBuffer, tBuffer,
(size_t) Var->NvalueBytes);
}
}
break;
}
default: {
/************************************************************************
* Two or more dimensions.
************************************************************************/
Int32 nPhyDimBytes = nPhyDimValues[firstDim] * Var->NvalueBytes;
Int32 nHypDimBytes = nHypDimValues[firstDim] * Var->NvalueBytes;
int nextDim = firstDim + dimIncr;
if (dimVarys[firstDim]) {
/**********************************************************************
* The first dimension's variance is TRUE. If the interval is one and
* only a single write is necessary for the "lower" dimension, use a
* single write. Otherwise, cycle through that dimension physically
* writing each subarray below it (skipping subarrays if necessary).
**********************************************************************/
if (intervals[firstDim] == 1 && fullPhyDim[nextDim]) {
tOffset = offset + (indices[firstDim] * nPhyDimBytes);
nValues = counts[firstDim] * nPhyDimValues[firstDim];
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,
tOffset,nValues,
buffer),&pStatus)) return pStatus;
} else {
memmove((size_t) tOffset + (Byte *) phyBuffer, buffer,
(size_t) (Var->NvalueBytes * nValues));
}
}
else {
tOffset = offset + (indices[firstDim] * nPhyDimBytes);
tBuffer = buffer;
for (i = 0; i < counts[firstDim]; i++) {
if (fullPhyDim[nextDim]) {
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,tOffset,
nPhyDimValues[firstDim],
tBuffer),&pStatus)) return pStatus;
} else {
memmove((size_t) tOffset + (Byte *) phyBuffer, tBuffer,
(size_t) (Var->NvalueBytes * nPhyDimValues[firstDim]));
}
}
else {
int numDimsT = (int) (numDims - 1);
int firstDimT = (CDF->rowMajor ? 0 : numDimsT - 1);
int passDimT = (CDF->rowMajor ? 1 : 0);
if (!sX(HyperWriteDim64(numDimsT,&dimSizes[passDimT],
&dimVarys[passDimT],
&indices[passDimT],
&counts[passDimT],
&intervals[passDimT],
&nHypDimValues[passDimT],
&nPhyDimValues[passDimT],
&fullPhyDim[passDimT],
firstDimT,dimIncr,recNum,
tOffset,tBuffer,phyBuffer,
CDF,Var),&pStatus)) return pStatus;
}
tOffset += (intervals[firstDim] * nPhyDimBytes);
tBuffer += (size_t) nHypDimBytes;
}
}
}
else {
/**********************************************************************
* The first dimension's variance is FALSE, skip to the last subarray
* and write the single physical subarray.
**********************************************************************/
tBuffer = (Byte *) buffer +
(size_t) (nHypDimBytes * (counts[firstDim] - 1));
if (fullPhyDim[nextDim]) {
if (phyBuffer == NULL) {
if (!sX(WriteVarValues64(CDF,Var,recNum,offset,
nPhyDimValues[firstDim],
tBuffer),&pStatus)) return pStatus;
} else {
memmove((size_t) offset + (Byte *) phyBuffer, tBuffer,
(size_t) (Var->NvalueBytes * nPhyDimValues[firstDim]));
}
}
else {
int numDimsT = (int) (numDims - 1);
int firstDimT = (CDF->rowMajor ? 0 : numDimsT - 1);
int passDimT = (CDF->rowMajor ? 1 : 0);
if (!sX(HyperWriteDim64(numDimsT,&dimSizes[passDimT],
&dimVarys[passDimT],
&indices[passDimT],
&counts[passDimT],
&intervals[passDimT],
&nHypDimValues[passDimT],
&nPhyDimValues[passDimT],
&fullPhyDim[passDimT],firstDimT,
dimIncr,recNum,offset,tBuffer,phyBuffer,
CDF,Var),&pStatus)) return pStatus;
}
}
break;
}
}
return pStatus;
}
syntax highlighted by Code2HTML, v. 0.9.1