/****************************************************************************** * * NSSDC/CDF CDF library miscellaneous functions, part 2. * * Version 1.3b, 4-Mar-97, Hughes STX. * * Modification history: * * V1.0 15-Dec-94, J Love Original version. * V1.1 6-Jan-95, J Love Encode/decode changes. More cache-residency. * V1.1a 20-Jan-95, J Love IRIX 6.0 (64-bit). * V1.1b 15-Mar-95, J Love Solaris 2.3 IDL i/f. Fixed `recNum' parameter * of `LastAllocatedRecord'. Gnu C on OSF/1. * V1.2 21-Mar-95, J Love POSIX. * V1.2a 18-Apr-95, J Love More POSIX. * V1.2b 13-Jun-95, J Love Linux. * V1.2c 7-Sep-95, J Love CDFexport-related changes. Fixed possible * memory leak. * V1.3 5-Sep-96, J Love CDF V2.6. * V1.3a 21-Feb-97, J Love Removed RICE. * V1.3b 4-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC. * V2.0 08-Apr-04, M Liu Modified LocateCurrentVar function to save * the current selected variable's offset. * Modified FindVarByNumber and FindVarByName * functions to start searching for the variable * from the current selected variable, if it's * cwselected, instead of always from the * beginning. Remove the calls to FindVarByNumber * if a variable is already selected. * V2.1 04-May-04, M Liu Corrected Int32ToCDFid and CDFidToInt32 to * handle 64-bit on Solaris/sparc. * V2.2 29-Jun-04, M Liu Added LFS (Large File Support > 2G). * V3.2 20-Jun-07, D Berger Modified the "FindAttr...", "FindEntry..." * routines, and the "SetCUR..." routines and * added ResetReadOnlyState to handle READONLYon * mode. * ******************************************************************************/ #include "cdflib.h" #include "cdflib64.h" /****************************************************************************** * LocateCurrentVar64. ******************************************************************************/ STATICforIDL CDFstatus LocateCurrentVar64 (CDF, zOp, offset, zVar, Var) struct CDFstruct *CDF; /* In: Pointer to CDF. */ Logical zOp; /* In: TRUE if current zVariable is to be accessed; FALSE if current rVariable. N/A if zMode is on (since the current zVariable number will always be used). */ OFF_T *offset; /* Out: Offset of the current variable's VDR. This may be a NULL pointer. */ Logical *zVar; /* Out: TRUE if a true zVariable; FALSE if a true rVariable. This may be a NULL pointer. */ struct VarStruct **Var; /* Out: Pointer to variable. This will be NULL if the variable has yet to be initialized. This may be a NULL pointer. */ { CDFstatus tStatus; OFF_T tOffset; /**************************************************************************** * Pass back the offset of the VDR. ****************************************************************************/ if (zModeON(CDF)) { if (CDF->CURzVarNum < CDF->NrVars) { ASSIGNnotNULL(zVar, FALSE) tStatus = FindVarByNumber64 (CDF, CDF->CURzVarNum, FALSE, &tOffset); if (StatusOK(tStatus)) { ASSIGNnotNULL (Var, CDF->rVars[(int)CDF->CURzVarNum]) ASSIGNnotNULL (offset, tOffset) CDF->CURzVarOffset64 = tOffset; } } else { ASSIGNnotNULL(zVar, TRUE) tStatus = FindVarByNumber64 (CDF, CDF->CURzVarNum - CDF->NrVars, TRUE, &tOffset); if (StatusOK(tStatus)) { ASSIGNnotNULL (Var, CDF->zVars[(int)(CDF->CURzVarNum - CDF->NrVars)]) ASSIGNnotNULL (offset, tOffset) CDF->CURzVarOffset64 = tOffset; } } } else { ASSIGNnotNULL (zVar, zOp) tStatus = FindVarByNumber64 (CDF,BOO(zOp,CDF->CURzVarNum, CDF->CURrVarNum),zOp,&tOffset); if (StatusOK(tStatus)) { ASSIGNnotNULL (Var, BOO(zOp,CDF->zVars[(int)CDF->CURzVarNum], CDF->rVars[(int)CDF->CURrVarNum])) ASSIGNnotNULL (offset, tOffset) if (zOp) CDF->CURzVarOffset64 = tOffset; else CDF->CURrVarOffset64 = tOffset; } } return tStatus; } /****************************************************************************** * InitCurrentVar64. ******************************************************************************/ STATICforIDL CDFstatus InitCurrentVar64 (CDF, zOp, Var) struct CDFstruct *CDF; /* In: Pointer to CDF. */ Logical zOp; /* In: TRUE if current zVariable is to be accessed; FALSE if current rVariable. N/A if zMode is on (since the current zVariable number will always be used [even when a real rVariable is being accessed]). */ struct VarStruct **Var; /* Out: Pointer to variable. */ { CDFstatus tStatus; /**************************************************************************** * Pass back the pointer to its variable structure. The variable will * be initialized for access if necessary. ****************************************************************************/ if (zModeON(CDF)) if (CDF->CURzVarNum < CDF->NrVars) { tStatus = InitVar64 (CDF, CDF->CURzVarNum, FALSE, Var); } else { tStatus = InitVar64 (CDF, CDF->CURzVarNum - CDF->NrVars, TRUE, Var); } else { tStatus = InitVar64 (CDF,BOO(zOp,CDF->CURzVarNum,CDF->CURrVarNum),zOp,Var); }; return tStatus; } /****************************************************************************** * InitVar64. ******************************************************************************/ STATICforIDL CDFstatus InitVar64 (CDF, varN, zVar, VarP) struct CDFstruct *CDF; /* In: Pointer to CDF. */ Int32 varN; /* In: Real variable number (ignoring the zMode). */ Logical zVar; /* In: TRUE if a real zVariable (ignoring the zMode). */ struct VarStruct **VarP; /* Out: Pointer to variable. */ { CDFstatus pStatus = CDF_OK; struct VarStruct *Var = BOO(zVar,CDF->zVars[(int)varN], CDF->rVars[(int)varN]); /**************************************************************************** * Check if the variable has already been initialized. If not, allocate and * initialize its variable structure. ****************************************************************************/ if (Var == NULL) { /************************************************************************** * Allocate a variable structure. **************************************************************************/ Var = (struct VarStruct *) cdf_AllocateMemory (sizeof(struct VarStruct), NULL); if (Var == NULL) return BAD_MALLOC; /************************************************************************** * Determine offset of the VDR in the dotCDF file. **************************************************************************/ if (!sX(FindVarByNumber64(CDF,varN,zVar,&(Var->VDRoffset64)),&pStatus)) { cdf_FreeMemory (Var, NULL); return pStatus; } /************************************************************************** * Initialize miscellaneous fields of the variable structure. **************************************************************************/ Var->zVar = zVar; Var->varN = varN; Var->fp = NULL; Var->varCacheSize = NUMcacheVAR; /* N/A if single-file CDF. */ Var->accessed_at = CDF->pseudo_clock++; Var->firstRecInVVR = NO_RECORD; Var->lastRecInVVR = NO_RECORD; Var->offsetOfVVR64 = (OFF_T) NO_OFFSET64; /************************************************************************** * Read fields to be held in memory for efficiency. **************************************************************************/ if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_MAXREC,&(Var->maxRec), VDR_NULL),&pStatus)) { cdf_FreeMemory (Var, NULL); return pStatus; } /************************************************************************** * More initialization. **************************************************************************/ if (!sX(InitVar2_64(CDF,Var),&pStatus)) { cdf_FreeMemory (Var, NULL); return pStatus; } /************************************************************************** * Store pointer to variable structure. **************************************************************************/ if (zVar) CDF->zVars[(int)varN] = Var; else CDF->rVars[(int)varN] = Var; } /**************************************************************************** * Pass back pointer to variable. ****************************************************************************/ ASSIGNnotNULL (VarP, Var) return pStatus; } /****************************************************************************** * InitVar2_64. ******************************************************************************/ STATICforIDL CDFstatus InitVar2_64 (CDF, Var) struct CDFstruct *CDF; struct VarStruct *Var; { int dimN; CDFstatus pStatus = CDF_OK; struct CPRstruct64 CPR; int i; Int32 flags, dataType, numElems, sRecords; OFF_T CPRoffset; /**************************************************************************** * Read necessary fields from the VDR. ****************************************************************************/ if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_FLAGS,&flags, VDR_DATATYPE,&dataType, VDR_NUMELEMS,&numElems, VDR_sRECORDS,&sRecords, VDR_NULL),&pStatus)) return pStatus; /**************************************************************************** * Determine if the variable has a known data type. ****************************************************************************/ if (!ValidDataType(dataType)) return BAD_DATA_TYPE; /**************************************************************************** * Calculate the dimensionality and variances of the variable based on the * current zMode. ****************************************************************************/ if (!sX(CalcDimParms64(CDF,Var->VDRoffset64, Var->zVar,&(Var->numDims), Var->dimSizes,Var->dimVarys),&pStatus)) return pStatus; Var->recVary = BOO(RECvaryBITset(flags),VARY,NOVARY); /**************************************************************************** * Calculate the number of values for each dimension. ****************************************************************************/ CalcNumDimValues (CDF, Var); /**************************************************************************** * Calculate the element and value sizes. ****************************************************************************/ Var->NvalueElems = numElems; Var->NelemBytes = CDFelemSize (dataType); Var->NvalueBytes = Var->NvalueElems * Var->NelemBytes; /**************************************************************************** * Calculate the number of physical and virtual values per record. ****************************************************************************/ CalcRecValues (Var); /**************************************************************************** * Calculate the number of elements and the size (in bytes) of physical and * conceptual records. ****************************************************************************/ Var->NphyRecElems = Var->NphyRecValues * Var->NvalueElems; Var->NvirtRecElems = Var->NvirtRecValues * Var->NvalueElems; Var->NphyRecBytes = Var->NphyRecValues * Var->NvalueBytes; Var->NvirtRecBytes = Var->NvirtRecValues * Var->NvalueBytes; /************************************************************************** * Initialize current positioning. **************************************************************************/ Var->seqValueOffset64 = (OFF_T) 0; Var->zRD.recNumber = 0; Var->zRD.recCount = 1; Var->zRD.recInterval = 1; for (dimN = 0; dimN < Var->numDims; dimN++) { Var->zRD.dimIndices[dimN] = 0; Var->zRD.dimCounts[dimN] = Var->dimSizes[dimN]; Var->zRD.dimIntervals[dimN] = 1; } /**************************************************************************** * Determine variable type. ****************************************************************************/ if (!sX(VariableType64(CDF,Var->VDRoffset64, Var->zVar,&(Var->vType)),&pStatus)) return pStatus; /************************************************************************** * What to do if a record is missing. **************************************************************************/ Var->prevIfMissing = (sRecords == PREV_SPARSERECORDS); /************************************************************************** * Based on the variable type... **************************************************************************/ switch (Var->vType) { case STANDARD_: case SPARSE_RECORDS_: if (!sX(LastRecord64(CDF,Var->VDRoffset64,Var->zVar, &(Var->maxAllocated)),&pStatus)) return pStatus; Var->maxWritten = Var->maxAllocated; break; case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_CPRorSPR,&CPRoffset, VDR_NULL),&pStatus)) return pStatus; if (!sX(ReadCPR64(CDF->fp,CPRoffset, CPR_RECORD,&CPR, CPR_NULL),&pStatus)) return pStatus; Var->cType = CPR.cType; for (i = 0; i < CPR.pCount; i++) Var->cParms[i] = CPR.cParms[i]; Var->reservePct = 0; break; case SPARSE_ARRAYS_: case SPARSE_RECORDS_AND_ARRAYS_: return UNKNOWN_SPARSENESS; case IN_MULTI_: break; default: return CDF_INTERNAL_ERROR; } /************************************************************************** * Initialize staging area (although n/a for most variable types). **************************************************************************/ Var->stage.areaOffset64 = (OFF_T) NO_OFFSET64; Var->stage.firstRec = NO_RECORD; Var->stage.lastRec = NO_RECORD; Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64; Var->stage.modified = FALSE; /**************************************************************************** * Calculate the blocking factor based on variable type... ****************************************************************************/ if (!sX(CalcBF64(CDF,Var),&pStatus)) return pStatus; /**************************************************************************** * Determine the encoding and decoding functions to be used. ****************************************************************************/ if (!sX(ConversionFunction(dataType,HostEncoding(), CDF->encoding,CDF->negToPosFp0, &(Var->EncodeFunction)),&pStatus)) return pStatus; if (!sX(ConversionFunction(dataType,CDF->encoding, CDF->decoding,CDF->negToPosFp0, &(Var->DecodeFunction)),&pStatus)) return pStatus; return pStatus; } /****************************************************************************** * CalcBF64. ******************************************************************************/ STATICforIDL CDFstatus CalcBF64 (CDF, Var) struct CDFstruct *CDF; struct VarStruct *Var; { CDFstatus pStatus = CDF_OK; Int32 bF; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64, Var->zVar, VDR_BLOCKING,&bF, VDR_NULL),&pStatus)) return pStatus; switch (Var->vType) { case STANDARD_: if (Var->recVary) if (bF == 0) { Int32 min = ((MIN_BLOCKING_BYTES_standard-1)/Var->NphyRecBytes)+1; Var->blockingFactor = MAXIMUM(min,MIN_BLOCKING_RECS_standard); } else Var->blockingFactor = bF; else Var->blockingFactor = 1; break; case SPARSE_RECORDS_: if (Var->recVary) if (bF == 0) { Int32 min = ((MIN_BLOCKING_BYTES_sparse-1)/Var->NphyRecBytes)+1; Var->blockingFactor = MAXIMUM(min,MIN_BLOCKING_RECS_sparse); } else Var->blockingFactor = bF; else Var->blockingFactor = 1; break; case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: Var->blockingFactor = bF; break; case SPARSE_ARRAYS_: case SPARSE_RECORDS_AND_ARRAYS_: return UNKNOWN_SPARSENESS; case IN_MULTI_: Var->blockingFactor = 1; break; default: return CDF_INTERNAL_ERROR; } return pStatus; } /****************************************************************************** * UpdateConversions64. ******************************************************************************/ STATICforIDL CDFstatus UpdateConversions64 (CDF) struct CDFstruct *CDF; { CDFstatus pStatus = CDF_OK; Logical zVar; for (zVar = 0; zVar <= 1; zVar++) { int varN; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars); for (varN = 0; varN < nVars; varN++) { struct VarStruct *Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]); if (Var != NULL) { Int32 dataType; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64, Var->zVar, VDR_DATATYPE,&dataType, VDR_NULL),&pStatus)) return pStatus; if (!sX(ConversionFunction(dataType,HostEncoding(), CDF->encoding,CDF->negToPosFp0, &(Var->EncodeFunction)),&pStatus)) return pStatus; if (!sX(ConversionFunction(dataType,CDF->encoding, CDF->decoding,CDF->negToPosFp0, &(Var->DecodeFunction)),&pStatus)) return pStatus; } } } return pStatus; } /****************************************************************************** * UpdateNEWzMode64. ******************************************************************************/ STATICforIDL CDFstatus UpdateNEWzMode64 (CDF) struct CDFstruct *CDF; { CDFstatus pStatus = CDF_OK; Logical zVar; for (zVar = 0; zVar <= 1; zVar++) { int varN; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars); for (varN = 0; varN < nVars; varN++) { struct VarStruct *Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]); if (Var != NULL) { if (!sX(CalcDimParms64(CDF,Var->VDRoffset64, Var->zVar,&(Var->numDims), Var->dimSizes, Var->dimVarys),&pStatus)) return pStatus; CalcNumDimValues (CDF, Var); CalcRecValues (Var); Var->NvirtRecElems = Var->NvirtRecValues * Var->NvalueElems; Var->NvirtRecBytes = Var->NvirtRecValues * Var->NvalueBytes; } } } return pStatus; } /****************************************************************************** * OpenVar64. * Open a variable for read and/or write access (if this is a multi-file CDF * and the variable file is closed). It is assumed that the variable has been * initialized for access and that the variable is closed (and in a multi-file * CDF). ******************************************************************************/ STATICforIDL CDFstatus OpenVar64 (CDF, Var) struct CDFstruct *CDF; struct VarStruct *Var; { CDFstatus pStatus = CDF_OK; char a_mode[MAX_aMODE_LEN+1], pathname[DU_MAX_PATH_LEN+1]; /**************************************************************************** * Try to open the variable file. ****************************************************************************/ BuildFilePath (BOO(Var->zVar,Zt,Vt), CDF->CDFname, CDF->no_append, CDF->upper_case_ext, CDF->version_numbers, Var->varN, pathname); if (CDF->status == READ_WRITE) strcpyX (a_mode, READ_PLUS_a_mode, MAX_aMODE_LEN); else strcpyX (a_mode, READ_ONLY_a_mode, MAX_aMODE_LEN); Var->fp = V_open64 (pathname, a_mode); /**************************************************************************** * If the open failed, close a variable file and try. If that attempt fails * return an error. ****************************************************************************/ if (Var->fp == NULL) { if (!sX(CloseLRUvar(CDF),&pStatus)) return pStatus; Var->fp = V_open64 (pathname, a_mode); if (Var->fp == NULL) return VAR_OPEN_ERROR; } /**************************************************************************** * The open was successful - try to set the proper cache size. ****************************************************************************/ if (!CACHEv64(Var->fp,Var->varCacheSize)) { V_close64 (Var->fp, NULL, NULL); Var->fp = NULL; return BAD_CACHE_SIZE; } return pStatus; } /****************************************************************************** * LastRecord64. ******************************************************************************/ STATICforIDL CDFstatus LastRecord64 (CDF, VDRoffset, zVar, recNum) struct CDFstruct *CDF; /* In: Pointer to CDF. */ OFF_T VDRoffset; /* In: Offset of VDR. */ Logical zVar; /* In: TRUE if a real zVariable; FALSE if rVariable. */ Int32 *recNum; /* Out: Last record allocated. */ { CDFstatus pStatus = CDF_OK; Int32 nUsedEntries, lastRecs[MAX_VXR_ENTRIES]; OFF_T VXRoffset; if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar, VDR_VXRTAIL,&VXRoffset, VDR_NULL),&pStatus)) return pStatus; if (VXRoffset == 0) *recNum = NO_RECORD; else { if (!sX(ReadVXR64(CDF->fp,VXRoffset, VXR_NUSEDENTRIES,&nUsedEntries, VXR_LASTREC,lastRecs, VXR_NULL),&pStatus)) return pStatus; *recNum = lastRecs[(int)(nUsedEntries-1)]; } return pStatus; } /****************************************************************************** * RecordByteOffset64. ******************************************************************************/ STATICforIDL CDFstatus RecordByteOffset64 (CDF, Var, phyRecN, offsetP) struct CDFstruct *CDF; struct VarStruct *Var; Int32 phyRecN; OFF_T *offsetP; { CDFstatus pStatus = CDF_OK; Int32 firstRec=-1, lastRec=-1; OFF_T offset = (OFF_T) -1; switch (Var->vType) { case STANDARD_: case SPARSE_RECORDS_: { if (Var->firstRecInVVR <= phyRecN && phyRecN <= Var->lastRecInVVR) { *offsetP = Var->offsetOfVVR64 + (OFF_T) (VVR_BASE_SIZE64 + ((OFF_T) Var->NphyRecBytes) * (phyRecN - Var->firstRecInVVR)); break; } else { if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,Var->zVar, phyRecN,&firstRec,&lastRec, &offset,NULL),&pStatus)) return pStatus; *offsetP = offset + (OFF_T) (VVR_BASE_SIZE64 + ((OFF_T) Var->NphyRecBytes) * (phyRecN - firstRec)); Var->firstRecInVVR = firstRec; Var->lastRecInVVR = lastRec; Var->offsetOfVVR64 = offset; break; } } case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: case SPARSE_ARRAYS_: case SPARSE_RECORDS_AND_ARRAYS_: return CDF_INTERNAL_ERROR; case IN_MULTI_: *offsetP = ((OFF_T) phyRecN) * Var->NphyRecBytes; break; default: return CDF_INTERNAL_ERROR; } return pStatus; } /****************************************************************************** * ConfigureNEWzMode64. ******************************************************************************/ STATICforIDL CDFstatus ConfigureNEWzMode64 (CDF) struct CDFstruct *CDF; { CDFstatus pStatus = CDF_OK; if (!sX(UpdateNEWzMode64(CDF),&pStatus)) return pStatus; InitCURobjectsStates (CDF); return pStatus; } /****************************************************************************** * FindAttrByName64. ******************************************************************************/ STATICforIDL CDFstatus FindAttrByName64 (CDF, searchName, offset) struct CDFstruct *CDF; /* In: Pointer to CDF. */ char *searchName; /* In: Attribute name to find. */ OFF_T *offset; /* Out: Offset of ADR that was found. */ { Int32 numAttrs; OFF_T tOffset, nextADR, fstADR; char attrName[CDF_ATTR_NAME_LEN256+1]; CDFstatus pStatus = CDF_OK; Int32 attrN; long read_only_mode; pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; /************************************************************************** * If in READONLYon mode, set CurADRIndex to the referenced attribute number. ***************************************************************************/ if (read_only_mode == READONLYon) { for (attrN = 0; attrN < CDF->fp->GDR64->NumAttr; attrN++) { if (!strcmpITB(CDF->fp->ADRList64[attrN]->Name,searchName)) { CDF->fp->CurADRIndex = attrN; ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET); return CDF_OK; }; }; } else { /************************************************************************ * Read number of attributes and the offset of the first ADR from the GDR. *************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_NUMATTR,&numAttrs, GDR_ADRHEAD,&fstADR, GDR_NULL),&pStatus)) return pStatus; /************************************************************************ * Read from ADRs until a matching attribute name is found. * Note that if this is a V2.0 CDF, the last ADR will not have an * offset of zero for the next ADR. For that reason, we will loop * through the number of attributes read from the GDR (and then stop). ************************************************************************/ if (CDF->CURattrOffset64 != (OFF_T) (OFF_T) RESERVED_ATTROFFSET64) tOffset = CDF->CURattrOffset64; else tOffset = fstADR; for (attrN = 0; attrN < numAttrs; attrN++) { if (!sX(ReadADR64(CDF->fp,tOffset, ADR_NAME,attrName, ADR_ADRNEXT,&nextADR, ADR_NULL),&pStatus)) return pStatus; if (!strcmpITB(attrName,searchName)) { ASSIGNnotNULL (offset, tOffset) return CDF_OK; } if (nextADR != 0) tOffset = nextADR; else tOffset = fstADR; }; }; /**************************************************************************** * Attribute name not found, return error. ****************************************************************************/ return NO_SUCH_ATTR; } /****************************************************************************** * FindAttrByNumber64. ******************************************************************************/ STATICforIDL CDFstatus FindAttrByNumber64 (CDF, searchNum, offset) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ Int32 searchNum; /* In: The attribute number to be found. */ OFF_T *offset; /* Out: The offset of the located ADR. */ { Int32 numAttrs, attrNum; OFF_T tOffset, nextADR, fstADR; CDFstatus pStatus = CDF_OK; Int32 attrN; long read_only_mode; /**************************************************************************** * Validate. ****************************************************************************/ if (searchNum < 0) return BAD_ATTR_NUM; /**************************************************************************** * First check if the next attribute is the one being searched for. For this * to be the case, an attribute must currently be selected, the next attribute * must exist, and the next attribute's number must be the attribute number * being searched for. But don't try this if a V2.0 CDF because of the bad * terminating offset of the ADR linked list in those CDFs. ****************************************************************************/ /* if (!CDF->badTerminatingOffsets) { if (CDF->CURattrOffset64 != (OFF_T) (OFF_T) RESERVED_ATTROFFSET64) { OFF_T nextOffset; if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64, ADR_ADRNEXT,&nextOffset, ADR_NULL),&pStatus)) return pStatus; if (nextOffset != 0) { Int32 nextNum; if (!sX(ReadADR64(CDF->fp,nextOffset, ADR_NUM,&nextNum, ADR_NULL),&pStatus)) return pStatus; if (nextNum == searchNum) { *offset = nextOffset; return pStatus; } } } } */ pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; /*************************************************************************** * If in read only mode, set CurADRIndex to the searched for atribute number. ***************************************************************************/ if (read_only_mode == READONLYon) { if (CDF->fp->GDR64->NumAttr <= searchNum) return NO_SUCH_ATTR; if (searchNum < 0 || searchNum >= CDF->fp->GDR64->NumAttr) return NO_SUCH_ATTR; CDF->fp->CurADRIndex = searchNum; ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET); return CDF_OK; } else { /************************************************************************ * The next attribute isn't the one being searched for. First read the * number of attributes and the offset of the first ADR from the GDR. ************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_NUMATTR,&numAttrs, GDR_ADRHEAD,&fstADR, GDR_NULL),&pStatus)) return pStatus; if (numAttrs <= searchNum) return NO_SUCH_ATTR; if (searchNum < 0 || searchNum >= numAttrs) return NO_SUCH_ATTR; if (CDF->CURattrOffset64 != (OFF_T) RESERVED_ATTROFFSET64) tOffset = CDF->CURattrOffset64; else tOffset = fstADR; /************************************************************************* * Read from ADRs until a matching attribute number is found. * Note that if this is a V2.0 CDF, the last ADR will not have an * offset of zero for the next ADR. For that reason, we will loop * through the number of attributes read from the GDR (and then stop). *************************************************************************/ for (attrN = 0; attrN < numAttrs; attrN++) { if (!sX(ReadADR64(CDF->fp,tOffset, ADR_NUM,&attrNum, ADR_ADRNEXT,&nextADR, ADR_NULL),&pStatus)) return pStatus; if (attrNum == searchNum) { ASSIGNnotNULL (offset, tOffset) return CDF_OK; } if (nextADR != 0) tOffset = nextADR; else tOffset = fstADR; } /************************************************************************* * Attribute number not found, internal error or corrupted CDF. *************************************************************************/ return CORRUPTED_V3_CDF; }; } /****************************************************************************** * FindEntryByNumber64. ******************************************************************************/ STATICforIDL CDFstatus FindEntryByNumber64 (CDF, ADRoffset, zEntry, entryN, offset) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ OFF_T ADRoffset; /* In: Offset of attribute's ADR. */ Logical zEntry; /* In: TRUE if AzEDR list to be searched. FALSE if AgrEDR list to be searched. */ Int32 entryN; /* In: The entry number being searched for. */ OFF_T *offset; /* Out: The offset of the located AEDR. */ { Int32 numEntries, entryNum; OFF_T tOffset, nextADR; CDFstatus pStatus = CDF_OK; Int32 entryX; long read_only_mode; /**************************************************************************** * Read number of entries and the offset of the first AEDR from the ADR. ****************************************************************************/ if (!sX(ReadADR64(CDF->fp,ADRoffset, BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&numEntries, BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&tOffset, ADR_NULL),&pStatus)) return pStatus; pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; if (read_only_mode == READONLYon) { /*********************************************************************** * If the requested entry exists, set CurAEDRIndex to the entry number and * set CURzEntrySel to reflect if the entry is in the z list or the gr * list. ************************************************************************/ if (zEntry && entryN <= CDF->fp->ADRList64[CDF->fp->CurADRIndex]-> MAXzEntry) { if (CDF->fp->ADRList64[CDF->fp->CurADRIndex]->zAEDRList64[entryN] != NULL) { CDF->fp->CURzEntrySel = TRUE; CDF->fp->CurAEDRIndex = entryN; ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET) return pStatus; } else { return NO_SUCH_ENTRY; } } else if (!zEntry && entryN <= CDF->fp->ADRList64[CDF->fp->CurADRIndex]-> MAXgrEntry) { if (CDF->fp->ADRList64[CDF->fp->CurADRIndex]->grAEDRList64[entryN] != NULL) { CDF->fp->CURzEntrySel = FALSE; CDF->fp->CurAEDRIndex = entryN; ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET) return pStatus; } else { return NO_SUCH_ENTRY; }; } else { return NO_SUCH_ENTRY; }; }; /**************************************************************************** * Read from AEDRs until a matching entry number is found. * Note that if this is a V2.0 CDF, the last AEDR will not have an * offset of zero for the next AEDR. For that reason, we will loop * through the number of entries read from the ADR (and then stop). ****************************************************************************/ for (entryX = 0; entryX < numEntries; entryX++) { if (!sX(ReadAEDR64(CDF->fp,tOffset, AEDR_NUM,&entryNum, AEDR_AEDRNEXT,&nextADR, AEDR_NULL),&pStatus)) return pStatus; if (entryNum == entryN) { ASSIGNnotNULL (offset, tOffset) return CDF_OK; } tOffset = nextADR; } /**************************************************************************** * Entry number not found. ****************************************************************************/ return NO_SUCH_ENTRY; } /****************************************************************************** * FindLastAttr64. ******************************************************************************/ STATICforIDL CDFstatus FindLastAttr64 (CDF, lastOffset) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ OFF_T *lastOffset; /* Out: Offset of last attribute's ADR. */ { CDFstatus pStatus = CDF_OK; Int32 nAttrs; OFF_T offset; Int32 attrN; long read_only_mode; pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; /************************************************************************* * If in READONLYon mode, set CurADRIndex to the index of the last * attribute in menmory. *************************************************************************/ if (read_only_mode == READONLYon) { *lastOffset = DUMMY_ATTROFFSET; CDF->fp->CurADRIndex = CDF->fp->GDR64->NumAttr - 1; } else { /************************************************************************ * Read number of attributes and the offset of the first ADR. If there are * no attributes, return an offset of zero. ************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_NUMATTR,&nAttrs, GDR_NULL),&pStatus)) return pStatus; if (nAttrs == 0) { *lastOffset = 0; return pStatus; } /************************************************************************ * There is at least one attribute. * Note that if this is a V2.0 CDF, the last ADR will not have an offset of * zero for the next ADR. For that reason, we will loop through the number * of attributes read from the GDR (and then stop). ************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_ADRHEAD,&offset, GDR_NULL),&pStatus)) return pStatus; for (attrN = 0; attrN < nAttrs - 1; attrN++) { if (!sX(ReadADR64(CDF->fp,offset, ADR_ADRNEXT,&offset, ADR_NULL),&pStatus)) return pStatus; } *lastOffset = offset; }; return pStatus; } /****************************************************************************** * FindLastEntry64. ******************************************************************************/ STATICforIDL CDFstatus FindLastEntry64 (CDF, ADRoffset, zEntry, lastOffset) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ OFF_T ADRoffset; /* In: Offset of attribute's ADR. */ Logical zEntry; /* In: TRUE if (real) zEntry is being searched for; FALSE if gEntry/rEntry. */ OFF_T *lastOffset; /* Out: The offset of the last AEDR. */ { CDFstatus pStatus = CDF_OK; Int32 nEntries; OFF_T offset; Int32 entryX; long read_only_mode; pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; /*********************************************************************** * If in READONLYon mode, set CurAEDRIndex to MAXzEntry or MAXgrEntry, as * appropriate. ***********************************************************************/ if (read_only_mode == READONLYon) { *lastOffset = DUMMY_ENTRYOFFSET; if (zEntry == TRUE) { CDF->fp->CurAEDRIndex = CDF->fp->ADRList64[CDF->fp->CurADRIndex]->MAXzEntry; } else { CDF->fp->CurAEDRIndex = CDF->fp->ADRList64[CDF->fp->CurADRIndex]->MAXgrEntry; }; } else { /************************************************************************ * Read offset of first AEDR and determine if there are any entries (of the * specified type). If there are none, pass back an offset of zero. ************************************************************************/ if (!sX(ReadADR64(CDF->fp,ADRoffset, BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD), &offset,ADR_NULL),&pStatus)) return pStatus; if (offset == 0) { *lastOffset = 0; return pStatus; } /************************************************************************ * There is at least one entry. Read the actual number of entries and then * scan through to the last one. * Note that if this is a V2.0 CDF, the last AEDR will not have an * offset of zero for the next AEDR. For that reason, we will loop * through the number of entries (minus one) read from the ADR (and then * stop). ************************************************************************/ if (!sX(ReadADR64(CDF->fp,ADRoffset, BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&nEntries, ADR_NULL),&pStatus)) return pStatus; for (entryX = 0; entryX < nEntries - 1; entryX++) { if (!sX(ReadAEDR64(CDF->fp,offset, AEDR_AEDRNEXT,&offset, AEDR_NULL),&pStatus)) return pStatus; } *lastOffset = offset; }; return pStatus; } /****************************************************************************** * FindPrevEntry64. ******************************************************************************/ STATICforIDL CDFstatus FindPrevEntry64 (CDF, ADRoffset, searchOffset, zEntry, prevOffset) struct CDFstruct *CDF; /* Pointer to the CDF. */ OFF_T ADRoffset; /* Offset of attribute's ADR. */ OFF_T searchOffset; /* The entry offset being searched for. */ Logical zEntry; /* TRUE if (real) zEntry is being searched for; FALSE if gEntry/rEntry. */ OFF_T *prevOffset; /* The offset of the previous AEDR. */ { CDFstatus pStatus = CDF_OK; Int32 nEntries; OFF_T offset, nextOffset; int entryX; /**************************************************************************** * Read the offset of the first AEDR. If that offset is the same as the * search offset, return an offset of zero. ****************************************************************************/ if (!sX(ReadADR64(CDF->fp,ADRoffset, BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&offset, ADR_NULL),&pStatus)) return pStatus; if (offset == searchOffset) { *prevOffset = 0; return pStatus; } /**************************************************************************** * The first AEDR is not at the search offset. Read the actual number of * entries and then scan through them looking for the AEDR offset being * searched for. If the search offset is not found, then either the CDF is * corrupted or an internal logic error has occurred. * Note that if this is a V2.0 CDF, the last AEDR will not have an * offset of zero for the next AEDR. For that reason, we will loop * through the number of entries read from the ADR (and then stop). ****************************************************************************/ if (!sX(ReadADR64(CDF->fp,ADRoffset, BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&nEntries, ADR_NULL),&pStatus)) return pStatus; for (entryX = 0; entryX < nEntries; entryX++) { if (!sX(ReadAEDR64(CDF->fp,offset, AEDR_AEDRNEXT,&nextOffset, AEDR_NULL),&pStatus)) return pStatus; if (nextOffset == searchOffset) { *prevOffset = offset; return pStatus; } offset = nextOffset; } return CORRUPTED_V3_CDF; } /****************************************************************************** * FindVarByName64. * Both the rVariable and zVariable lists are searched (since variable names * are unique in a CDF). ******************************************************************************/ STATICforIDL CDFstatus FindVarByName64 (CDF, searchName, offset, zVar, Var) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ char *searchName; /* In: The variable name being searched for. */ OFF_T *offset; /* Out: Offset of the zVDR/rVDR. */ Logical *zVar; /* Out: TRUE if a zVariable. */ struct VarStruct **Var; /* Out: Pointer to variable structure. */ { int varN; char varName[CDF_VAR_NAME_LEN256+1]; CDFstatus pStatus = CDF_OK; OFF_T tOffset, nextVDR; OFF_T headOffset; /**************************************************************************** * Read from rVDRs until a matching variable name is found. * Note that if this is a V2.0 CDF, the last rVDR will not have an * offset of zero for the next rVDR. For that reason, we will loop * through the number of rVariables (and then stop). ****************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_rVDRHEAD,&headOffset, GDR_NULL),&pStatus)) return pStatus; if (CDF->CURrVarNum != RESERVED_VARNUM) tOffset = CDF->CURrVarOffset64; else tOffset = headOffset; for (varN = 0; varN < CDF->NrVars; varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,FALSE, VDR_NAME,varName, VDR_VDRNEXT,&nextVDR, VDR_NULL),&pStatus)) return pStatus; if (!strcmpITB(varName,searchName)) { ASSIGNnotNULL (offset, tOffset) ASSIGNnotNULL (zVar, FALSE) ASSIGNnotNULL (Var, CDF->rVars[varN]) return CDF_OK; } if (nextVDR == 0) tOffset = headOffset; else tOffset = nextVDR; } /**************************************************************************** * Read from zVDRs until a matching variable name is found. ****************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_zVDRHEAD,&headOffset, GDR_NULL),&pStatus)) return pStatus; /* if (CDF->CURzVarNum != RESERVED_VARNUM) tOffset = CDF->CURzVarOffset64; else */ tOffset = headOffset; for (varN = 0; varN < CDF->NzVars; varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,TRUE, VDR_NAME,varName, VDR_VDRNEXT,&nextVDR, VDR_NULL),&pStatus)) return pStatus; if (!strcmpITB(varName,searchName)) { ASSIGNnotNULL (offset, tOffset) ASSIGNnotNULL (zVar, TRUE) ASSIGNnotNULL (Var, CDF->zVars[varN]) return CDF_OK; } if (nextVDR == 0) tOffset = headOffset; else tOffset = nextVDR; } /**************************************************************************** * Variable name not found, return error. ****************************************************************************/ return NO_SUCH_VAR; } /****************************************************************************** * FindVarByNumber64. ******************************************************************************/ STATICforIDL CDFstatus FindVarByNumber64 (CDF, searchNum, zVar, offset) struct CDFstruct *CDF; /* In: Pointer to CDF. */ Int32 searchNum; /* In: Variable number to be searched for. */ Logical zVar; /* In: TRUE if a (real) zVariable number should be found. */ OFF_T *offset; /* Out: offset of the VDR. */ { CDFstatus pStatus = CDF_OK; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars); Int32 varNum; OFF_T tOffset, nextVDR, fstOffset; int varN; /**************************************************************************** * Read offset of first VDR. ****************************************************************************/ if (searchNum < 0) return BAD_VAR_NUM; if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&fstOffset, GDR_NULL),&pStatus)) return pStatus; if (nVars <= searchNum) return NO_SUCH_VAR; /**************************************************************************** * Read from VDRs until a matching variable number is found. * Note that if this is a V2.0 CDF, the last VDR will not have an * offset of zero for the next VDR. For that reason, we will loop * through the number of variables (and then stop). ****************************************************************************/ if (zModeON(CDF)) { tOffset = fstOffset; if (CDF->CURzVarNum != RESERVED_VARNUM) { long numT = BOO(zVar, CDF->CURzVarNum-CDF->NrVars, CDF->CURzVarNum); if (numT > -1 && numT <= searchNum) tOffset = CDF->CURzVarOffset64; } } else { if (zVar) { if (CDF->CURzVarNum != RESERVED_VARNUM && CDF->CURzVarNum < searchNum) tOffset = CDF->CURzVarOffset64; else tOffset = fstOffset; } else { if (CDF->CURrVarNum != RESERVED_VARNUM && CDF->CURrVarNum < searchNum) tOffset = CDF->CURrVarOffset64; else tOffset = fstOffset; } } /**************************************************************************** * Search for the variable from the current selected variabale, instead of * the top of the variable list. It will speed up the search process if the * variables are accessed in a orderly sequence. ****************************************************************************/ for (varN = 0; varN < nVars; varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,zVar, VDR_NUM,&varNum, VDR_VDRNEXT, &nextVDR, VDR_NULL),&pStatus)) return pStatus; if (varNum == searchNum) { ASSIGNnotNULL (offset, tOffset) return CDF_OK; } if (nextVDR != 0) /* Reaching the end of the list? */ tOffset = nextVDR; /* No.... Continue. */ else tOffset = fstOffset; /* Yes... Go back to the top. */ } /**************************************************************************** * Variable number not found, return error. ****************************************************************************/ return CORRUPTED_V3_CDF; } /****************************************************************************** * VerifyNoRecordsWritten64. * Verifies that no records have been written. Both the rVariable and * zVariable lists are searched. ******************************************************************************/ STATICforIDL CDFstatus VerifyNoRecordsWritten64 (CDF, no) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ Logical *no; /* Out: If TRUE, no records written. */ { CDFstatus pStatus = CDF_OK; Int32 maxRec; int varN; Logical zVar; OFF_T tOffset; /**************************************************************************** * Read from r/zVDRs until a maximum record greater than NO_RECORD is found. * Note that if this is a V2.0 CDF, the last rVDR will not have an * offset of zero for the next rVDR. For that reason, we will loop * through the number of variables (and then stop). ****************************************************************************/ for (zVar = 0; zVar <= 1; zVar++) { if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&tOffset, GDR_NULL),&pStatus)) return pStatus; for (varN = 0; varN < BOO(zVar,CDF->NzVars,CDF->NrVars); varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,zVar, VDR_MAXREC,&maxRec, VDR_VDRNEXT,&tOffset, VDR_NULL),&pStatus)) return pStatus; if (maxRec > NO_RECORD) { *no = FALSE; return pStatus; } } } /**************************************************************************** * No records written. ****************************************************************************/ *no = TRUE; return pStatus; } /****************************************************************************** * VerifyNoPadsSpecified64. * Verifies that no pad values have been specified. Both the rVariable * and zVariable lists are searched. ******************************************************************************/ STATICforIDL CDFstatus VerifyNoPadsSpecified64 (CDF, no) struct CDFstruct *CDF; /* In: Pointer to the CDF. */ Logical *no; /* Out: If TRUE, no pad values written. */ { CDFstatus pStatus = CDF_OK; Int32 flags32; OFF_T tOffset; int varN; /**************************************************************************** * Read from rVDRs until a pad value is found. * Note that if this is a V2.0 CDF, the last rVDR will not have an * offset of zero for the next rVDR. For that reason, we will loop * through the number of rVariables (and then stop). ****************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_rVDRHEAD,&tOffset, GDR_NULL),&pStatus)) return pStatus; for (varN = 0; varN < CDF->NrVars; varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,FALSE, VDR_FLAGS,&flags32, VDR_NULL),&pStatus)) return pStatus; if (PADvalueBITset(flags32)) { *no = FALSE; return pStatus; } if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,FALSE, VDR_VDRNEXT,&tOffset, VDR_NULL),&pStatus)) return pStatus; } /**************************************************************************** * Read from zVDRs until a pad value is found. ****************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_zVDRHEAD,&tOffset, GDR_NULL),&pStatus)) return pStatus; for (varN = 0; varN < CDF->NzVars; varN++) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,TRUE, VDR_FLAGS,&flags32, VDR_NULL),&pStatus)) return pStatus; if (PADvalueBITset(flags32)) { *no = FALSE; return pStatus; } if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,TRUE, VDR_VDRNEXT,&tOffset, VDR_NULL),&pStatus)) return pStatus; } /**************************************************************************** * No pad values specified. ****************************************************************************/ *no = TRUE; return pStatus; } /****************************************************************************** * VerifyNoEntriesWritten64. ******************************************************************************/ STATICforIDL CDFstatus VerifyNoEntriesWritten64 (CDF, no) struct CDFstruct *CDF; Logical *no; { CDFstatus pStatus = CDF_OK; Int32 numAttrs, nEntries; OFF_T tOffset; int attrN; /**************************************************************************** * Read number of attributes and the offset of the first ADR from the GDR. ****************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_NUMATTR,&numAttrs, GDR_ADRHEAD,&tOffset, GDR_NULL),&pStatus)) return pStatus; /**************************************************************************** * Read from ADRs until an entry is found. * Note that if this is a V2.0 CDF, the last ADR will not have an * offset of zero for the next ADR. For that reason, we will loop * through the number of attributes read from the GDR (and then stop). ****************************************************************************/ for (attrN = 0; attrN < numAttrs; attrN++) { if (!sX(ReadADR64(CDF->fp,tOffset, ADR_NgrENTRIES,&nEntries, ADR_NULL),&pStatus)) return pStatus; if (nEntries > 0) { *no = FALSE; return pStatus; } if (!sX(ReadADR64(CDF->fp,tOffset, ADR_NzENTRIES,&nEntries, ADR_NULL),&pStatus)) return pStatus; if (nEntries > 0) { *no = FALSE; return pStatus; } if (!sX(ReadADR64(CDF->fp,tOffset, ADR_ADRNEXT,&tOffset, ADR_NULL),&pStatus)) return pStatus; } /**************************************************************************** * No entries detected. ****************************************************************************/ *no = TRUE; return pStatus; } /****************************************************************************** * DefaultPadBuffer64. ******************************************************************************/ STATICforIDL CDFstatus DefaultPadBuffer64 (CDF, Var, nValues, buffer) struct CDFstruct *CDF; struct VarStruct *Var; Int32 nValues; void *buffer; { CDFstatus pStatus = CDF_OK; Byte *tBuffer = buffer; Int32 i; Int32 dataType, numElems; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_DATATYPE,&dataType, VDR_NUMELEMS,&numElems, VDR_NULL),&pStatus)) return pStatus; for (i = 0; i < nValues; i++, tBuffer += (int) Var->NvalueBytes) { DefaultPadValue (dataType, numElems, tBuffer); } return pStatus; } /****************************************************************************** * PadBuffer64. ******************************************************************************/ STATICforIDL CDFstatus PadBuffer64 (CDF, Var, nValues, buffer) struct CDFstruct *CDF; /* Pointer to CDF. */ struct VarStruct *Var; /* Pointer to variable. */ Int32 nValues; /* Number of values in buffer. */ void *buffer; /* Buffer to pad. */ { CDFstatus pStatus = CDF_OK; Int32 flags, dataType, numElems; /**************************************************************************** * Read the flags, data type, and number of elements fields of the VDR. ****************************************************************************/ if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_FLAGS,&flags, VDR_DATATYPE,&dataType, VDR_NUMELEMS,&numElems, VDR_NULL),&pStatus)) return pStatus; /**************************************************************************** * If a pad value has been specified for the variable, read the pad value * from the VDR and duplicate for the desired number of values. Otherwise, * copy the desired number of default pad values into the buffer. Then * convert the padded buffer into the desired decoding. ****************************************************************************/ if (PADvalueBITset(flags)) { Byte *tBuffer = buffer; Int32 valueN; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_PADVALUE,tBuffer, VDR_NULL),&pStatus)) return pStatus; for (valueN = 1; valueN < nValues; valueN++) { memmove (tBuffer + ((size_t) Var->NvalueBytes), tBuffer, (size_t) Var->NvalueBytes); tBuffer += (size_t) Var->NvalueBytes; } if (!sX(ConvertBuffer(CDF->encoding,CDF->decoding, CDF->negToPosFp0,dataType, (nValues * numElems), buffer,buffer),&pStatus)) return pStatus; } else { if (!sX(DefaultPadBuffer64(CDF,Var,nValues,buffer),&pStatus)) return pStatus; if (!sX(ConvertBuffer(HostEncoding(),CDF->decoding, CDF->negToPosFp0,dataType, (nValues * numElems), buffer,buffer),&pStatus)) return pStatus; } return pStatus; } /****************************************************************************** * CheckEntryOp64. ******************************************************************************/ STATICforIDL CDFstatus CheckEntryOp64 (CDF, entryType) struct CDFstruct *CDF; int entryType; { Int32 scope; CDFstatus pStatus = CDF_OK; if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64, ADR_SCOPE,&scope, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (GLOBALscope(scope)) { if (entryType != gENTRYt) return ILLEGAL_FOR_SCOPE; } else { if (entryType == gENTRYt) return ILLEGAL_FOR_SCOPE; if (BADzOP(CDF,entryType == rENTRYt)) return ILLEGAL_IN_zMODE; } return pStatus; } /****************************************************************************** * SetCURgrEntry64. ******************************************************************************/ STATICforIDL CDFstatus SetCURgrEntry64 (CDF, useCurrent, entryNum) struct CDFstruct *CDF; Logical useCurrent; /* TRUE if current g/rEntry offset can be used to speed up the search. */ Int32 entryNum; /* The new g/rEntry number. */ { CDFstatus pStatus = CDF_OK, tStatus; Int32 scope, attrNum, attrNumX, entryNumX; OFF_T offset, nextOffset; long read_only_mode; /**************************************************************************** * Check if the new g/rEntry number is the reserved entry number. ****************************************************************************/ if (entryNum == RESERVED_ENTRYNUM) { CDF->CURgrEntryNum = RESERVED_ENTRYNUM; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * Check that a current attribute is selected. ****************************************************************************/ if (CDF->CURattrOffset64 == (OFF_T) RESERVED_ATTROFFSET64) { CDF->CURgrEntryNum = entryNum; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * Read the scope and number of the current attribute. If READONLYon, they * are already in memory. ****************************************************************************/ pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; if (read_only_mode == READONLYon) { scope = CDF->fp->ADRList64[CDF->fp->CurADRIndex]->Scope; attrNum = CDF->fp->CurADRIndex; } else { if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64, ADR_SCOPE,&scope, ADR_NUM,&attrNum, ADR_NULL),&pStatus)) return pStatus; }; /**************************************************************************** * If the current attribute is variable-scoped and zMode is on, then the * current g/rEntry offset is n/a. ****************************************************************************/ if (VARIABLEscope(scope) && zModeON(CDF)) { CDF->CURgrEntryNum = entryNum; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * IF READONLYoff, check if the next entry is the one being searched for. * For this to be the case, an entry must currently be selected and must be * associated with the current attribute, the next entry must exist, and the * next entry's number must be the entry number being searched for. But * don't try this if a V2.0 CDF because of the bad terminating offset of the * AEDR linked lists in those CDFs. ****************************************************************************/ if (read_only_mode == READONLYoff && useCurrent && !CDF->badTerminatingOffsets) { if (CDF->CURgrEntryOffset64 != (OFF_T) RESERVED_ENTRYOFFSET64) { if (!sX(ReadAEDR64(CDF->fp,CDF->CURgrEntryOffset64, AEDR_ATTRNUM,&attrNumX, AEDR_AEDRNEXT,&nextOffset, AEDR_NULL),&pStatus)) return pStatus; if (attrNumX == attrNum && nextOffset != 0) { if (!sX(ReadAEDR64(CDF->fp,nextOffset, AEDR_NUM,&entryNumX, AEDR_NULL),&pStatus)) return pStatus; if (entryNumX == entryNum) { CDF->CURgrEntryNum = entryNum; CDF->CURgrEntryOffset64 = nextOffset; return pStatus; } } } } /**************************************************************************** * Search the list of AEDRs for the entry. ****************************************************************************/ tStatus = FindEntryByNumber64 (CDF, CDF->CURattrOffset64, FALSE, entryNum, &offset); switch (tStatus) { case CDF_OK: break; case NO_SUCH_ENTRY: offset = (OFF_T) RESERVED_ENTRYOFFSET64; break; default: return tStatus; } CDF->CURgrEntryNum = entryNum; CDF->CURgrEntryOffset64 = offset; return pStatus; } /****************************************************************************** * SetCURzEntry64. ******************************************************************************/ STATICforIDL CDFstatus SetCURzEntry64 (CDF, useCurrent, entryNum) struct CDFstruct *CDF; Logical useCurrent; /* TRUE if current zEntry offset can be used to speed up the search. */ Int32 entryNum; /* The new zEntry number. */ { CDFstatus pStatus = CDF_OK, tStatus; Int32 scope, attrNum, attrNumX, entryNumX; OFF_T offset, nextOffset; Logical zEntry; Int32 entryN; long read_only_mode; /**************************************************************************** * Check if the new zEntry number is the reserved entry number. ****************************************************************************/ if (entryNum == RESERVED_ENTRYNUM) { CDF->CURzEntryNum = RESERVED_ENTRYNUM; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * Check that a current attribute is selected. ****************************************************************************/ if (CDF->CURattrOffset64 == (OFF_T) RESERVED_ATTROFFSET64) { CDF->CURzEntryNum = entryNum; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * Read the scope and number of the current attribute. If READONLYon, they * are already in memory. ****************************************************************************/ pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_); if (pStatus != CDF_OK) return pStatus; if (read_only_mode == READONLYon) { scope = CDF->fp->ADRList64[CDF->fp->CurADRIndex]->Scope; attrNum = CDF->fp->CurADRIndex; } else { if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64, ADR_SCOPE,&scope, ADR_NUM,&attrNum, ADR_NULL),&pStatus)) return pStatus; }; /**************************************************************************** * If the current attribute is global-scoped, then the current zEntry offset * is n/a. ****************************************************************************/ if (GLOBALscope(scope)) { CDF->CURzEntryNum = entryNum; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; return pStatus; } /**************************************************************************** * Determine if a AgrEDR or AzEDR and the true entry number. ****************************************************************************/ if (zModeON(CDF)) { if (entryNum < CDF->NrVars) { zEntry = FALSE; entryN = entryNum; } else { zEntry = TRUE; entryN = entryNum - CDF->NrVars; } } else { zEntry = TRUE; entryN = entryNum; } /**************************************************************************** * IF READONLYoff, check if the next entry is the one being searched for. * For this to be the case, an entry must currently be selected and must be * associated with the current attribute, the next entry must exist, and the * next entry's number must be the entry number being searched for. But don't * try this if a V2.0 CDF because of the bad terminating offset of the AEDR * linked lists in those CDFs. ****************************************************************************/ if (read_only_mode == READONLYoff && useCurrent && !CDF->badTerminatingOffsets) { if (CDF->CURzEntryOffset64 != (OFF_T) RESERVED_ENTRYOFFSET64) { if (!sX(ReadAEDR64(CDF->fp,CDF->CURzEntryOffset64, AEDR_ATTRNUM,&attrNumX, AEDR_AEDRNEXT,&nextOffset, AEDR_NULL),&pStatus)) return pStatus; if (attrNumX == attrNum && nextOffset != 0) { if (!sX(ReadAEDR64(CDF->fp,nextOffset, AEDR_NUM,&entryNumX, AEDR_NULL),&pStatus)) return pStatus; if (entryNumX == entryN) { CDF->CURzEntryNum = entryNum; CDF->CURzEntryOffset64 = nextOffset; return pStatus; } } } } /**************************************************************************** * Search the list of AEDRs for the entry. ****************************************************************************/ tStatus = FindEntryByNumber64 (CDF, CDF->CURattrOffset64, zEntry, entryN, &offset); switch (tStatus) { case CDF_OK: break; case NO_SUCH_ENTRY: offset = (OFF_T) RESERVED_ENTRYOFFSET64; break; default: return tStatus; } CDF->CURzEntryNum = entryNum; CDF->CURzEntryOffset64 = offset; return pStatus; } /****************************************************************************** * VariableType64. ******************************************************************************/ STATICforIDL CDFstatus VariableType64 (CDF, vdrOffset, zVar, vType) struct CDFstruct *CDF; OFF_T vdrOffset; Logical zVar; int *vType; { CDFstatus pStatus = CDF_OK; Int32 flags, sRecords; if (!sX(ReadVDR64(CDF,CDF->fp,vdrOffset,zVar, VDR_FLAGS,&flags, VDR_sRECORDS,&sRecords, VDR_NULL),&pStatus)) return pStatus; if (CDF->singleFile) { if (VARcompressionBITset(flags) && SPARSEarraysBITset(flags)) { return CORRUPTED_V3_CDF; } if (sRecords == NO_SPARSERECORDS) { *vType = STANDARD_; if (VARcompressionBITset(flags)) *vType = COMPRESSED_; if (SPARSEarraysBITset(flags)) *vType = SPARSE_ARRAYS_; } else { *vType = SPARSE_RECORDS_; if (VARcompressionBITset(flags)) *vType = SPARSE_COMPRESSED_RECORDS_; if (SPARSEarraysBITset(flags)) *vType = SPARSE_RECORDS_AND_ARRAYS_; } } else { *vType = IN_MULTI_; if (VARcompressionBITset(flags)) return CORRUPTED_V3_CDF; if (SPARSEarraysBITset(flags)) return CORRUPTED_V3_CDF; if (sRecords != NO_SPARSERECORDS) return CORRUPTED_V3_CDF; } return pStatus; } /****************************************************************************** * Compress64. ******************************************************************************/ STATICforIDL CDFstatus Compress64 (iFp, iOffset, iSize, iError, cType, cParms, oFp, oOffset, oSize, oError) vFILE *iFp; OFF_T iOffset; OFF_T iSize; CDFstatus iError; Int32 cType; Int32 cParms[]; vFILE *oFp; OFF_T oOffset; OFF_T *oSize; CDFstatus oError; { CDFstatus pStatus = CDF_OK; switch (cType) { case RLE_COMPRESSION: { if (cParms[0] != RLE_OF_ZEROs) return UNKNOWN_COMPRESSION; if (!sX(CompressRLE0_64(iFp,iOffset,iSize,iError, oFp,oOffset,oSize,oError),&pStatus)) return pStatus; break; } case HUFF_COMPRESSION: if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION; if (!sX(CompressHUFF0_64(iFp,iOffset, iSize,iError,oFp, oOffset,oSize,oError),&pStatus)) return pStatus; break; case AHUFF_COMPRESSION: if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION; if (!sX(CompressAHUFF0_64(iFp,iOffset, iSize,iError,oFp, oOffset,oSize,oError),&pStatus)) return pStatus; break; case GZIP_COMPRESSION: if (!INCLUSIVE(1,cParms[0],9)) return UNKNOWN_COMPRESSION; if (!sX(CompressGZIP_64(iFp,iOffset,iSize,iError, oFp,oOffset,oSize, oError,cParms[0]),&pStatus)) return pStatus; break; /* case ZLIB_COMPRESSION: if (cParms[0] != ZLIB_OF_ZEROs) return UNKNOWN_COMPRESSION; if (!sX(CompressZLIB0_64(iFp,iOffset, iSize,iError,oFp, oOffset,oSize,oError),&pStatus)) return pStatus; break; */ default: return UNKNOWN_COMPRESSION; } return pStatus; } /****************************************************************************** * Decompress64. ******************************************************************************/ STATICforIDL CDFstatus Decompress64 (iFp, iOffset, iSize, iError, cType, cParms, oFp, oOffset, oError) vFILE *iFp; OFF_T iOffset; OFF_T iSize; CDFstatus iError; Int32 cType; Int32 cParms[]; vFILE *oFp; OFF_T oOffset; CDFstatus oError; { CDFstatus pStatus = CDF_OK; switch (cType) { case RLE_COMPRESSION: { if (cParms[0] != RLE_OF_ZEROs) return UNKNOWN_COMPRESSION; if (!sX(DecompressRLE0_64(iFp,iOffset,iSize,iError, oFp,oOffset,oError),&pStatus)) return pStatus; break; } case HUFF_COMPRESSION: if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION; if (!sX(DecompressHUFF0_64(iFp,iOffset,iError, oFp,oOffset,oError),&pStatus)) return pStatus; break; case AHUFF_COMPRESSION: if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION; if (!sX(DecompressAHUFF0_64(iFp,iOffset,iError, oFp,oOffset,oError),&pStatus)) return pStatus; break; case GZIP_COMPRESSION: if (!INCLUSIVE(1,cParms[0],9)) return UNKNOWN_COMPRESSION; if (!sX(DecompressGZIP_64(iFp,iOffset,iError, oFp,oOffset,oError),&pStatus)) return pStatus; break; /* case ZLIB_COMPRESSION: if (cParms[0] != ZLIB_OF_ZEROs) return UNKNOWN_COMPRESSION; if (!sX(DecompressZLIB0_64(iFp,iOffset,iSize,iError, oFp,oOffset,oError),&pStatus)) return pStatus; break; */ default: return UNKNOWN_COMPRESSION; } return pStatus; } /****************************************************************************** * DecompressToStage64. ******************************************************************************/ STATICforIDL CDFstatus DecompressToStage64 (CDF, Var, offset, uSize) struct CDFstruct *CDF; struct VarStruct *Var; OFF_T offset; OFF_T uSize; { CDFstatus pStatus = CDF_OK; Int32 irType; OFF_T tOffset; if (!sX(ReadIrType64(CDF->fp,offset,&irType),&pStatus)) return pStatus; switch (irType) { case VVR_: { tOffset = offset + VVR_BASE_SIZE64; if (!sX(CopyBytes64(CDF->fp,tOffset, CDF_READ_ERROR, uSize,CDF->stage.fp, Var->stage.areaOffset64, SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; break; } case CVVR_: { struct CVVRstruct64 CVVR; if (!sX(ReadCVVR64(CDF->fp,offset, CVVR_RECORDx,&CVVR, CVVR_NULL),&pStatus)) return pStatus; tOffset = offset + CVVR_BASE_SIZE64; if (!sX(Decompress64(CDF->fp,tOffset, CVVR.cSize,CDF_READ_ERROR, Var->cType,Var->cParms,CDF->stage.fp, Var->stage.areaOffset64, SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; break; } default: return CORRUPTED_V3_CDF; } return pStatus; } /****************************************************************************** * ResetReadOnlyState64. ******************************************************************************/ STATICforIDL void ResetReadOnlyState64 (CDF) struct CDFstruct *CDF; { int i, j; /************************************************************************* * Free all allocated memory associated with the metadata READONLYon data * structures and clear all the state variables. *************************************************************************/ if (CDF->fp != NULL && CDF->fp->GDR64 != NULL) { for (i = 0; i < CDF->fp->GDR64->NumAttr; i++) { if (CDF->fp->ADRList64[i] != NULL) { for (j = 0; j <= CDF->fp->ADRList64[i]->MAXgrEntry; j++) { if (CDF->fp->ADRList64[i]->grAEDRList64[j] != NULL) { if (CDF->fp->ADRList64[i]->grAEDRList64[j]->Value != NULL) { cdf_FreeMemory( CDF->fp->ADRList64[i]->grAEDRList64[j]->Value, NULL); CDF->fp->ADRList64[i]->grAEDRList64[j]->Value = NULL; }; cdf_FreeMemory( CDF->fp->ADRList64[i]->grAEDRList64[j], NULL); CDF->fp->ADRList64[i]->grAEDRList64[j] = NULL; }; }; for (j = 0; j <= CDF->fp->ADRList64[i]->MAXzEntry; j++) { if (CDF->fp->ADRList64[i]->zAEDRList64[j] != NULL) { if (CDF->fp->ADRList64[i]->zAEDRList64[j]->Value != NULL) { cdf_FreeMemory( CDF->fp->ADRList64[i]->zAEDRList64[j]->Value, NULL); CDF->fp->ADRList64[i]->zAEDRList64[j]->Value = NULL; }; cdf_FreeMemory(CDF->fp->ADRList64[i]->zAEDRList64[j], NULL); CDF->fp->ADRList64[i]->zAEDRList64[j] = NULL; }; }; }; cdf_FreeMemory(CDF->fp->ADRList64[i], NULL); CDF->fp->ADRList64[i] = NULL; }; if (CDF->fp->ADRList64 != NULL) { cdf_FreeMemory(CDF->fp->ADRList64, NULL); CDF->fp->ADRList64 = NULL; }; cdf_FreeMemory(CDF->fp->GDR64, NULL); CDF->fp->GDR64 = NULL; CDF->fp->CurADRIndex = 0; CDF->fp->CurADRIndex = RESERVED_ENTRYNUM; CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM; CDF->CURattrOffset64 = RESERVED_ATTROFFSET64; CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; }; }