1 /******************************************************************************
2 *
3 * NSSDC/CDF CDF library miscellaneous functions, part 3.
4 *
5 * Version 1.0e, 29-Oct-97, Hughes STX.
6 *
7 * Modification history:
8 *
9 * V1.0 5-Sep-96, J Love Original version.
10 * V1.0a 21-Feb-97, J Love Removed RICE.
11 * V1.0b 4-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
12 * V1.0c 11-Sep-97, J Love Magic number are now uInt32.
13 * V1.0d 20-Oct-97, J Love Properly cast the uInt32 magic numbers. More
14 * Windows NT.
15 * V3.2 25-Apr-07, D Berger Changed COPYblockBYTES from 512.
16 *
17 ******************************************************************************/
18
19 #include "cdflib.h"
20
21 /******************************************************************************
22 * Macros/function prototypes.
23 ******************************************************************************/
24
25 #define COPYblockSIZE nCACHE_BUFFER_BYTEs
26
27 static CDFstatus SearchForRecord_r PROTOARGs((
28 vFILE *fp, Int32 vxrOffset, Int32 recNum, Int32 *firstRec, Int32 *lastRec,
29 Int32 *offset, Logical *found
30 ));
31 static CDFstatus IndexingStatistics_r PROTOARGs((
32 vFILE *fp, Int32 vxrOffset, Int32 maxRec, int level, Int32 *nLevels,
33 Int32 *nVXRs, Int32 *nEntries, Int32 *nAlloc, Int32 *nRecords
34 ));
35 static CDFstatus PrevRecord_r PROTOARGs((
36 vFILE *fp, Int32 vxrOffset, Int32 baseRec, Int32 *prevRec, Logical *found
37 ));
38 static CDFstatus NextRecord_r PROTOARGs((
39 vFILE *fp, Int32 vxrOffset, Int32 baseRec, Int32 *nextRec, Logical *found
40 ));
41 static CDFstatus CalcCompressionPct_r PROTOARGs((
42 vFILE *fp, Int32 vxrOffset, Int32 nPhyRecBytes, long *uTotal, long *cTotal
43 ));
44 static CDFstatus ModIndexOffset_r PROTOARGs((
45 vFILE *fp, Int32 vxrOffset, Int32 firstRec, Int32 lastRec, Int32 newOffset
46 ));
47 static CDFstatus ReadSparseFull PROTOARGs((
48 struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
49 void *buffer
50 ));
51 static CDFstatus ReadSparsePartial PROTOARGs((
52 struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, Int32 offset,
53 Int32 nValues, void *buffer
54 ));
55 static CDFstatus ReadCompressedFull PROTOARGs((
56 struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
57 void *buffer
58 ));
59 static CDFstatus ReadCompressedPartial PROTOARGs((
60 struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, Int32 offset,
61 Int32 nValues, void *buffer
62 ));
63 static CDFstatus BringToStage PROTOARGs((
64 struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, Logical *found
65 ));
66 static CDFstatus WriteCompressedRecords PROTOARGs((
67 struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
68 void *buffer, Int32 nValues, Int32 offset, Logical fullRecord
69 ));
70
71 /******************************************************************************
72 * DecompressCDF.
73 ******************************************************************************/
74
DecompressCDF(dotFp,uDotFp)75 STATICforIDL CDFstatus DecompressCDF (dotFp, uDotFp)
76 vFILE *dotFp; /* In: File pointer to dotCDF file. */
77 vFILE *uDotFp; /* In: Uncompressed CDF file pointer. */
78 {
79 CDFstatus pStatus = CDF_OK; struct CCRstruct CCR; struct CPRstruct CPR;
80 uInt32 magicNumber1 = V2magicNUMBER_1, magicNumber2u = V2magicNUMBER_2u;
81 Int32 cSize, cOffset;
82 /****************************************************************************
83 * Read/validate CCR.
84 ****************************************************************************/
85 if (!sX(ReadCCR(dotFp,V2_CCR_OFFSET,
86 CCR_RECORD,&CCR,
87 CCR_NULL),&pStatus)) return pStatus;
88 if (CCR.uSize == 0) return EMPTY_COMPRESSED_CDF;
89 /****************************************************************************
90 * Read CPR.
91 ****************************************************************************/
92 if (!sX(ReadCPR(dotFp,CCR.CPRoffset,
93 CPR_RECORD,&CPR,
94 CPR_NULL),&pStatus)) return pStatus;
95 /****************************************************************************
96 * Write magic numbers.
97 ****************************************************************************/
98 if (!SEEKv(uDotFp,V2_MAGIC_OFFSET_1,vSEEK_SET)) return CDF_WRITE_ERROR;
99 if (!Write32(uDotFp,(Int32 *)&magicNumber1)) return CDF_WRITE_ERROR;
100 if (!Write32(uDotFp,(Int32 *)&magicNumber2u)) return CDF_WRITE_ERROR;
101 /****************************************************************************
102 * Copy/decompress.
103 ****************************************************************************/
104 cOffset = V2_CCR_OFFSET + CCR_BASE_SIZE;
105 cSize = CCR.RecordSize - CCR_BASE_SIZE;
106 if (!sX(Decompress(dotFp,cOffset,
107 cSize,CDF_READ_ERROR,
108 CPR.cType,CPR.cParms,
109 uDotFp,FIRST_IR_OFFSET,
110 CDF_WRITE_ERROR),&pStatus)) return pStatus;
111 return pStatus;
112 }
113
114 /******************************************************************************
115 * WriteCompressedCDF.
116 ******************************************************************************/
117
WriteCompressedCDF(CDF,CPR,empty)118 STATICforIDL CDFstatus WriteCompressedCDF (CDF, CPR, empty)
119 struct CDFstruct *CDF;
120 struct CPRstruct *CPR;
121 Logical empty; /* In: If TRUE, write an empty CCR. */
122 {
123 uInt32 magicNumber1 = V2magicNUMBER_1;
124 uInt32 magicNumber2c = V2magicNUMBER_2c;
125 struct CCRstruct CCR; CDFstatus pStatus = CDF_OK;
126 /****************************************************************************
127 * Write magic numbers.
128 ****************************************************************************/
129 if (!SEEKv(CDF->dotFp,V2_MAGIC_OFFSET_1,vSEEK_SET)) return CDF_WRITE_ERROR;
130 if (!Write32(CDF->dotFp,(Int32 *)&magicNumber1)) return CDF_WRITE_ERROR;
131 if (!Write32(CDF->dotFp,(Int32 *)&magicNumber2c)) return CDF_WRITE_ERROR;
132 /****************************************************************************
133 * Write CCR.
134 ****************************************************************************/
135 if (empty) {
136 CCR.RecordSize = CCR_BASE_SIZE;
137 CCR.RecordType = CCR_;
138 CCR.CPRoffset = V2_CCR_OFFSET + CCR.RecordSize;
139 CCR.uSize = 0;
140 CCR.rfuA = 0;
141 if (!sX(WriteCCR(CDF->dotFp,V2_CCR_OFFSET,
142 CCR_RECORD,&CCR,
143 CCR_NULL),&pStatus)) return CDF_WRITE_ERROR;
144 }
145 else {
146 Int32 uSize, eof, cSize, cOffset, GDRoffset;
147 if (!sX(ReadCDR(CDF->uDotFp,V2_CDR_OFFSET,
148 CDR_GDROFFSET,&GDRoffset,
149 CDR_NULL),&pStatus)) return pStatus;
150 if (!sX(ReadGDR(CDF->uDotFp,GDRoffset,
151 GDR_EOF,&eof,
152 GDR_NULL),&pStatus)) return pStatus;
153 uSize = eof - FIRST_IR_OFFSET;
154 cOffset = V2_CCR_OFFSET + CCR_BASE_SIZE;
155 if (!sX(Compress(CDF->uDotFp,FIRST_IR_OFFSET,
156 uSize,CDF_READ_ERROR,CPR->cType,
157 CPR->cParms,CDF->dotFp,cOffset,
158 &cSize,CDF_WRITE_ERROR),&pStatus)) return pStatus;
159 CCR.RecordSize = CCR_BASE_SIZE + cSize;
160 CCR.RecordType = CCR_;
161 CCR.CPRoffset = V2_CCR_OFFSET + CCR.RecordSize;
162 CCR.uSize = uSize;
163 CCR.rfuA = 0;
164 if (!sX(WriteCCR(CDF->dotFp,V2_CCR_OFFSET,
165 CCR_RECORD,&CCR,
166 CCR_NULL),&pStatus)) return CDF_WRITE_ERROR;
167 }
168 /****************************************************************************
169 * Write CPR.
170 ****************************************************************************/
171 if (!sX(WriteCPR(CDF->dotFp,CCR.CPRoffset,
172 CPR_RECORD,CPR,
173 CPR_NULL),&pStatus)) return CDF_WRITE_ERROR;
174 return pStatus;
175 }
176
177 /******************************************************************************
178 * CopyCDF.
179 ******************************************************************************/
180
CopyCDF(srcFp,destFp)181 STATICforIDL CDFstatus CopyCDF (srcFp, destFp)
182 vFILE *srcFp;
183 vFILE *destFp;
184 {
185 Int32 nBytes, offset; Byte buffer[nCACHE_BUFFER_BYTEs];
186 CDFstatus pStatus = CDF_OK;
187 if (!SEEKv(srcFp,0L,vSEEK_END)) return CDF_READ_ERROR;
188 nBytes = V_tell (srcFp);
189 if (nBytes == EOF) return CDF_READ_ERROR;
190 if (!SEEKv(srcFp,0L,vSEEK_SET)) return CDF_READ_ERROR;
191 if (!SEEKv(destFp,0L,vSEEK_SET)) return CDF_WRITE_ERROR;
192 for (offset = 0; offset < nBytes; offset += nCACHE_BUFFER_BYTEs) {
193 Int32 nBytesRemaining = nBytes - offset;
194 size_t count = (size_t) MINIMUM (nBytesRemaining, nCACHE_BUFFER_BYTEs);
195 if (!READv(buffer,count,1,srcFp)) return CDF_READ_ERROR;
196 if (!WRITEv(buffer,count,1,destFp)) return CDF_WRITE_ERROR;
197 }
198 return pStatus;
199 }
200
201 /******************************************************************************
202 * WriteVarValues.
203 * NOTE: If more than one record is being written, full records are assumed
204 * and the `offset' must be zero.
205 ******************************************************************************/
206
WriteVarValues(CDF,Var,startRec,offset,nValues,buffer)207 STATICforIDL CDFstatus WriteVarValues (CDF, Var, startRec, offset, nValues,
208 buffer)
209 struct CDFstruct *CDF;
210 struct VarStruct *Var;
211 Int32 startRec; /* Physical record number at which to write. */
212 Int32 offset; /* Byte offset within (first) record at which to
213 begin writing. */
214 Int32 nValues; /* Number of values to write. */
215 void *buffer;
216 {
217 Int32 tOffset; Logical fullRecord; Byte *tBuffer = buffer;
218 Int32 numElems, firstRec, lastRec, lastRecInVVR, nBytes, padTo, recNum;
219 Int32 writeTo, recCount; CDFstatus pStatus = CDF_OK;
220 /****************************************************************************
221 * Determine first/last record(s) being written and if full physical
222 * record(s).
223 ****************************************************************************/
224 firstRec = startRec;
225 if (nValues < Var->NphyRecValues) {
226 fullRecord = FALSE;
227 lastRec = startRec;
228 }
229 else {
230 fullRecord = TRUE;
231 lastRec = startRec + ((nValues - 1) / Var->NphyRecValues);
232 }
233 /****************************************************************************
234 * Based on variable type...
235 ****************************************************************************/
236 switch (Var->vType) {
237 /**************************************************************************
238 * Standard variable in single-file CDF...
239 **************************************************************************/
240 case STANDARD_: {
241 /************************************************************************
242 * Allocate/pad records.
243 ************************************************************************/
244 if (lastRec > Var->maxAllocated) {
245 struct AllocStruct alloc;
246 Int32 nNeeded = lastRec - Var->maxAllocated;
247 Int32 nRecords = MAXIMUM(nNeeded,Var->blockingFactor);
248 LoadAllocVVR (alloc, Var->maxAllocated + 1,
249 Var->maxAllocated + nRecords, FALSE)
250 if (!sX(AllocateRecords(CDF,Var,alloc),&pStatus)) return pStatus;
251 Var->maxAllocated = alloc.last;
252 }
253 padTo = BOO(fullRecord,firstRec - 1,firstRec);
254 if (padTo > Var->maxWritten) {
255 Int32 padFrom = Var->maxWritten + 1;
256 if (!sX(PadUnRecords(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
257 Var->maxWritten = padTo;
258 }
259 /************************************************************************
260 * Write value(s).
261 ************************************************************************/
262 if (fullRecord) {
263 recNum = firstRec;
264 while (recNum <= lastRec) {
265 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
266 Var->zVar,recNum,
267 NULL,&lastRecInVVR,
268 NULL,NULL),&pStatus)) return pStatus;
269 writeTo = MINIMUM(lastRec,lastRecInVVR);
270 recCount = writeTo - recNum + 1;
271 if (!sX(RecordByteOffset(CDF,Var,
272 recNum,
273 &tOffset),&pStatus)) return pStatus;
274 numElems = recCount * Var->NphyRecElems;
275 if (!sX(WriteVarElems(Var,CDF->fp,tOffset,
276 numElems,tBuffer),&pStatus)) return pStatus;
277 recNum += recCount;
278 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
279 }
280 }
281 else {
282 if (!sX(RecordByteOffset(CDF,Var,
283 firstRec,
284 &tOffset),&pStatus)) return pStatus;
285 tOffset += (Int32) offset;
286 numElems = nValues * Var->NvalueElems;
287 if (!sX(WriteVarElems(Var,CDF->fp,tOffset,
288 numElems,buffer),&pStatus)) return pStatus;
289 }
290 /************************************************************************
291 * Update the maximum record written.
292 ************************************************************************/
293 Var->maxWritten = MAXIMUM(Var->maxWritten,lastRec);
294 break;
295 }
296 /**************************************************************************
297 * Sparse records...
298 **************************************************************************/
299 case SPARSE_RECORDS_: {
300 Int32 maxRecInStage, recordOffsetInStage, nextRec;
301 int how; void *padBuffer; Logical found;
302 /************************************************************************
303 * Pad records.
304 ************************************************************************/
305 padTo = BOO(fullRecord,firstRec - 1,firstRec);
306 if (padTo > Var->maxWritten) {
307 Int32 padFrom = Var->maxWritten + 1;
308 if (!sX(PadUnRecords(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
309 Var->maxWritten = padTo;
310 }
311 /************************************************************************
312 * Write value(s).
313 ************************************************************************/
314 recNum = firstRec;
315 while (recNum <= lastRec) {
316 /**********************************************************************
317 * Check if this record already exists (is allocated).
318 **********************************************************************/
319 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
320 Var->zVar,recNum,
321 NULL,&lastRecInVVR,
322 NULL,&found),&pStatus)) return pStatus;
323 if (found) {
324 writeTo = MINIMUM(lastRec,lastRecInVVR);
325 recCount = writeTo - recNum + 1;
326 if (!sX(RecordByteOffset(CDF,Var,
327 recNum,&tOffset),&pStatus)) return pStatus;
328 if (fullRecord)
329 numElems = recCount * Var->NphyRecElems;
330 else {
331 tOffset += offset;
332 numElems = nValues * Var->NvalueElems;
333 }
334 if (!sX(WriteVarElems(Var,CDF->fp,tOffset,
335 numElems,tBuffer),&pStatus)) return pStatus;
336 Var->maxWritten = MAXIMUM(Var->maxWritten,writeTo);
337 recNum += recCount;
338 tBuffer += (size_t) (numElems * Var->NelemBytes);
339 continue;
340 }
341 /**********************************************************************
342 * This record doesn't exist - initialize the staging area.
343 **********************************************************************/
344 if (Var->stage.areaOffset == NO_OFFSET) {
345 nBytes = Var->blockingFactor * Var->NphyRecBytes;
346 if (!sX(InitVarStage(CDF,Var,nBytes),&pStatus)) return pStatus;
347 }
348 /**********************************************************************
349 * Check if this record is in the staging area.
350 **********************************************************************/
351 if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
352 maxRecInStage = Var->stage.firstRec + Var->blockingFactor - 1;
353 writeTo = MINIMUM(lastRec,maxRecInStage);
354 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
355 recNum,&nextRec,&found),&pStatus)) return pStatus;
356 if (found) {
357 Int32 prevRecN = nextRec - 1;
358 writeTo = MINIMUM(writeTo,prevRecN);
359 }
360 recCount = writeTo - recNum + 1;
361 recordOffsetInStage = recNum - Var->stage.firstRec;
362 tOffset = Var->stage.areaOffset;
363 tOffset += (recordOffsetInStage * Var->NphyRecBytes);
364 if (fullRecord)
365 numElems = recCount * Var->NphyRecElems;
366 else {
367 tOffset += offset;
368 numElems = nValues * Var->NvalueElems;
369 }
370 if (!sX(WriteVarElems(Var,CDF->stage.fp,tOffset,
371 numElems,tBuffer),&pStatus)) return pStatus;
372 Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
373 Var->stage.modified = TRUE;
374 recNum += recCount;
375 tBuffer += (size_t) (numElems * Var->NelemBytes);
376 continue;
377 }
378 /**********************************************************************
379 * This record is not in the staging area. Check if it can be added.
380 **********************************************************************/
381 if (Var->stage.firstRec != NO_RECORD) {
382 if (recNum == Var->stage.lastRec + 1) {
383 maxRecInStage = Var->stage.firstRec + Var->blockingFactor - 1;
384 if (recNum <= maxRecInStage) {
385 writeTo = MINIMUM(lastRec,maxRecInStage);
386 if (!sX(NextRecord(CDF,Var->VDRoffset,
387 Var->zVar,recNum,
388 &nextRec,&found),&pStatus)) return pStatus;
389 if (found) {
390 Int32 prevRecN = nextRec - 1;
391 writeTo = MINIMUM(writeTo,prevRecN);
392 }
393 recCount = writeTo - recNum + 1;
394 recordOffsetInStage = recNum - Var->stage.firstRec;
395 tOffset = Var->stage.areaOffset;
396 tOffset += (recordOffsetInStage * Var->NphyRecBytes);
397 if (fullRecord)
398 numElems = recCount * Var->NphyRecElems;
399 else {
400 if (!sX(BuildPadBuffer(CDF,Var,recCount,
401 &how,&padBuffer,
402 TRUE),&pStatus)) return pStatus;
403 if (!sX(WritePadValues(Var,CDF->stage.fp,tOffset,
404 recCount,how,padBuffer),&pStatus)) {
405 cdf_FreeMemory (padBuffer, NULL);
406 return pStatus;
407 }
408 cdf_FreeMemory (padBuffer, NULL);
409 tOffset += offset;
410 numElems = nValues * Var->NvalueElems;
411 }
412 if (!sX(WriteVarElems(Var,CDF->stage.fp,
413 tOffset,numElems,
414 tBuffer),&pStatus)) return pStatus;
415 Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
416 Var->stage.modified = TRUE;
417 recNum += recCount;
418 tBuffer += (size_t) (numElems * Var->NelemBytes);
419 continue;
420 }
421 }
422 }
423 /**********************************************************************
424 * This record cannot be added to the staging area. First flush the
425 * staging area (if necessary)...
426 **********************************************************************/
427 if (!sX(FlushStage(CDF,Var),&pStatus)) return pStatus;
428 /**********************************************************************
429 * ...and then start a new staging area with this record.
430 **********************************************************************/
431 maxRecInStage = recNum + Var->blockingFactor - 1;
432 writeTo = MINIMUM(lastRec,maxRecInStage);
433 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
434 recNum,&nextRec,&found),&pStatus)) return pStatus;
435 if (found) {
436 Int32 prevRecN = nextRec - 1;
437 writeTo = MINIMUM(writeTo,prevRecN);
438 }
439 recCount = writeTo - recNum + 1;
440 tOffset = Var->stage.areaOffset;
441 if (fullRecord)
442 numElems = recCount * Var->NphyRecElems;
443 else {
444 if (!sX(BuildPadBuffer(CDF,Var,recCount,
445 &how,&padBuffer,
446 TRUE),&pStatus)) return pStatus;
447 if (!sX(WritePadValues(Var,CDF->stage.fp,tOffset,
448 recCount,how,padBuffer),&pStatus)) {
449 cdf_FreeMemory (padBuffer, NULL);
450 return pStatus;
451 }
452 cdf_FreeMemory (padBuffer, NULL);
453 tOffset += offset;
454 numElems = nValues * Var->NvalueElems;
455 }
456 if (!sX(WriteVarElems(Var,CDF->stage.fp,tOffset,
457 numElems,tBuffer),&pStatus)) return pStatus;
458 Var->stage.firstRec = recNum;
459 Var->stage.lastRec = writeTo;
460 Var->stage.modified = TRUE;
461 recNum += recCount;
462 tBuffer += (size_t) (numElems * Var->NelemBytes);
463 }
464 break;
465 }
466 /**************************************************************************
467 * Compressed records...
468 * Sparse/compressed records...
469 **************************************************************************/
470 case COMPRESSED_:
471 case SPARSE_COMPRESSED_RECORDS_: {
472 Logical sparseRecords = (Var->vType == SPARSE_COMPRESSED_RECORDS_);
473 /************************************************************************
474 * Initialize staging area.
475 ************************************************************************/
476 if (Var->stage.areaOffset == NO_OFFSET) {
477 if (Var->blockingFactor == 0) {
478 if (Var->recVary) {
479 Int32 bf = ((MIN_BLOCKING_BYTES_compressed-1)/Var->NphyRecBytes)+1;
480 Var->blockingFactor = MAXIMUM(bf,MIN_BLOCKING_RECS_compressed);
481 }
482 else
483 Var->blockingFactor = 1;
484 if (!sX(WriteVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
485 VDR_BLOCKING,&(Var->blockingFactor),
486 VDR_NULL),&pStatus)) return pStatus;
487 }
488 nBytes = Var->blockingFactor * Var->NphyRecBytes;
489 if (!sX(InitVarStage(CDF,Var,nBytes),&pStatus)) return pStatus;
490 }
491 /************************************************************************
492 * Pad records (if necessary).
493 ************************************************************************/
494 if (!sparseRecords) {
495 padTo = firstRec - 1;
496 if (Var->maxRec < padTo) {
497 Int32 nRecords = padTo + 1, recN, valueN; void *padBuffer; int how;
498 if (!sX(BuildPadBuffer(CDF,Var,
499 nRecords,&how,
500 &padBuffer,FALSE),&pStatus)) return pStatus;
501 switch (how) {
502 case ALLrecordsATonce:
503 if (!sX(WriteCompressedRecords(CDF,Var,Var->maxRec+1,
504 padTo,padBuffer,
505 nRecords*Var->NphyRecValues,
506 ZERO_OFFSET,
507 TRUE),&pStatus)) return pStatus;
508 break;
509 case ONErecordATaTIME:
510 for (recN = Var->maxRec + 1; recN <= padTo; recN++) {
511 if (!sX(WriteCompressedRecords(CDF,Var,recN,recN,
512 padBuffer,Var->NphyRecValues,
513 ZERO_OFFSET,TRUE),&pStatus)) {
514 cdf_FreeMemory (padBuffer, NULL);
515 return pStatus;
516 }
517 }
518 break;
519 case ONEvalueATaTIME:
520 for (recN = 0; recN < nRecords; recN++) {
521 for (valueN = 0; valueN < Var->NphyRecValues; valueN++) {
522 tOffset = valueN * Var->NvalueBytes;
523 if (!sX(WriteCompressedRecords(CDF,Var,recN,recN,
524 padBuffer,INT32_ONE,
525 tOffset,FALSE),&pStatus)) {
526 cdf_FreeMemory (padBuffer, NULL);
527 return pStatus;
528 }
529 }
530 }
531 break;
532 }
533 cdf_FreeMemory (padBuffer, NULL);
534 }
535 }
536 /************************************************************************
537 * Write the record(s).
538 ************************************************************************/
539 if (!sX(WriteCompressedRecords(CDF,Var,firstRec,lastRec,
540 buffer,nValues,offset,
541 fullRecord),&pStatus)) return pStatus;
542 break;
543 }
544 /**************************************************************************
545 * Can't do sparse arrays yet...
546 **************************************************************************/
547 case SPARSE_ARRAYS_:
548 case SPARSE_RECORDS_AND_ARRAYS_:
549 return UNKNOWN_SPARSENESS;
550 /**************************************************************************
551 * Variable in multi-file CDF...
552 **************************************************************************/
553 case IN_MULTI_: {
554 padTo = BOO(fullRecord,firstRec - 1,firstRec);
555 /************************************************************************
556 * Extend variable (if necessary).
557 ************************************************************************/
558 if (padTo > Var->maxRec) {
559 Int32 padFrom = Var->maxRec + 1;
560 if (!sX(PadUnRecords(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
561 }
562 /************************************************************************
563 * Write value(s).
564 ************************************************************************/
565 if (!sX(RecordByteOffset(CDF,Var,
566 firstRec,
567 &tOffset),&pStatus)) return pStatus;
568 tOffset += (Int32) offset;
569 numElems = nValues * Var->NvalueElems;
570 if (!sX(WriteVarElems(Var,Var->fp,tOffset,
571 numElems,buffer),&pStatus)) return pStatus;
572 break;
573 }
574 /**************************************************************************
575 * Unknown variable type - this should never happen.
576 **************************************************************************/
577 default:
578 return CDF_INTERNAL_ERROR;
579 }
580 /****************************************************************************
581 * Update maximum record numbers.
582 ****************************************************************************/
583 if (!sX(UpdateMaxRec(CDF,Var,lastRec),&pStatus)) return pStatus;
584 return pStatus;
585 }
586
587 /******************************************************************************
588 * WriteVarElems.
589 * NOTE: On IBM PCs, it is assumed that the number of bytes being written
590 * will not exceed 65535.
591 ******************************************************************************/
592
WriteVarElems(Var,fp,offset,numElems,buffer)593 STATICforIDL CDFstatus WriteVarElems (Var, fp, offset, numElems, buffer)
594 struct VarStruct *Var;
595 vFILE *fp;
596 Int32 offset;
597 Int32 numElems;
598 void *buffer;
599 {
600 CDFstatus pStatus = CDF_OK; Int32 elemCount;
601 /****************************************************************************
602 * Seek to the desired offset.
603 ****************************************************************************/
604 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return VAR_WRITE_ERROR;
605 /****************************************************************************
606 * If no encoding is necessary, simply write the buffer and return.
607 ****************************************************************************/
608 if (Var->EncodeFunction == NULL) {
609 Int32 nBytes = numElems * Var->NelemBytes;
610 if (!WRITEv(buffer,1,(size_t)nBytes,fp)) return VAR_WRITE_ERROR;
611 return pStatus;
612 }
613 /****************************************************************************
614 * Use as large a temporary buffer as possible for the encoding conversion.
615 * Start at the full number of elements and then halve that number until an
616 * allocation succeeds.
617 ****************************************************************************/
618 elemCount = numElems;
619 for (;;) {
620 size_t nBytes = (size_t) (elemCount * Var->NelemBytes);
621 void *tBuffer;
622 if ((int) nBytes <= 0) return VAR_READ_ERROR;
623 tBuffer = cdf_AllocateMemory (nBytes, NULL);
624 if (tBuffer != NULL) {
625 Int32 elemN = 0; Byte *bOffset = buffer;
626 while (elemN < numElems) {
627 Int32 thisElemCount = MinInt32 (elemCount, numElems - elemN);
628 size_t thisByteCount = (size_t) (thisElemCount * Var->NelemBytes);
629 memmove (tBuffer, bOffset, thisByteCount);
630 if (!sX(Var->EncodeFunction(tBuffer,thisElemCount),&pStatus)) {
631 cdf_FreeMemory (tBuffer, NULL);
632 return pStatus;
633 }
634 if (!WRITEv(tBuffer,1,thisByteCount,fp)) {
635 cdf_FreeMemory (tBuffer, NULL);
636 return VAR_WRITE_ERROR;
637 }
638 elemN += thisElemCount;
639 bOffset += thisByteCount;
640 }
641 cdf_FreeMemory (tBuffer, NULL);
642 return pStatus;
643 }
644 if (elemCount == 1) break;
645 elemCount = (elemCount + 1) / 2;
646 }
647 return BAD_MALLOC;
648 }
649
650 /******************************************************************************
651 * PrevRecord.
652 * Determine the last record allocated AT or BEFORE `baseRec'. This routine
653 * should only be used for single-file CDFs.
654 ******************************************************************************/
655
PrevRecord(CDF,VDRoffset,zVar,baseRec,prevRec,found)656 STATICforIDL CDFstatus PrevRecord (CDF, VDRoffset, zVar, baseRec, prevRec,
657 found)
658 struct CDFstruct *CDF;
659 Int32 VDRoffset;
660 Logical zVar;
661 Int32 baseRec;
662 Int32 *prevRec;
663 Logical *found; /* If NULL, return NO_SUCH_RECORD if the previous
664 record doesn't exist. Otherwise, set according to
665 whether or not the previous record exists and
666 return the pending status. */
667 {
668 CDFstatus pStatus = CDF_OK; Int32 VXRoffset;
669 /****************************************************************************
670 * If multi-file...
671 ****************************************************************************/
672 if (!CDF->singleFile) return CDF_INTERNAL_ERROR;
673 /****************************************************************************
674 * Single-file...read the offset of the first VXR.
675 ****************************************************************************/
676 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
677 VDR_VXRHEAD,&VXRoffset,
678 VDR_NULL),&pStatus)) return pStatus;
679 /****************************************************************************
680 * ...and start there (unless there are no VXRs).
681 ****************************************************************************/
682 if (VXRoffset != ZERO_OFFSET) {
683 if (!sX(PrevRecord_r(CDF->fp,VXRoffset,
684 baseRec,prevRec,found),&pStatus)) return pStatus;
685 }
686 else {
687 ASSIGNnotNULL (found, FALSE)
688 if (found == NULL) pStatus = NO_SUCH_RECORD;
689 }
690 return pStatus;
691 }
692
PrevRecord_r(fp,vxrOffset,baseRec,prevRec,found)693 static CDFstatus PrevRecord_r (fp, vxrOffset, baseRec, prevRec, found)
694 vFILE *fp;
695 Int32 vxrOffset;
696 Int32 baseRec;
697 Int32 *prevRec;
698 Logical *found;
699 {
700 CDFstatus pStatus = CDF_OK; int entryN = 0;
701 struct VXRstruct VXR, nextVXR; Int32 irType;
702 /****************************************************************************
703 * Read the first VXR.
704 ****************************************************************************/
705 if (!sX(ReadVXR(fp,vxrOffset,
706 VXR_RECORD,&VXR,
707 VXR_NULL),&pStatus)) return pStatus;
708 /****************************************************************************
709 * Check if there isn't a previous allocated record. This could only be the
710 * case at the top level of VXRs (ie. not when this routine is recursively
711 * called).
712 ****************************************************************************/
713 if (baseRec < VXR.First[0]) {
714 ASSIGNnotNULL (found, FALSE)
715 return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
716 }
717 /****************************************************************************
718 * Until it's time to return...
719 ****************************************************************************/
720 for (;;) {
721 /*************************************************************************
722 * If the record is in the current entry...
723 *************************************************************************/
724 if (INCLUSIVE(VXR.First[entryN],baseRec,VXR.Last[entryN])) {
725 if (!sX(ReadIrType(fp,VXR.Offset[entryN],&irType),&pStatus)) {
726 return pStatus;
727 }
728 switch (irType) {
729 case VXR_:
730 return PrevRecord_r(fp,VXR.Offset[entryN],baseRec,prevRec,found);
731 case VVR_:
732 case CVVR_:
733 *prevRec = baseRec;
734 ASSIGNnotNULL (found, TRUE)
735 return pStatus;
736 default:
737 return CORRUPTED_V2_CDF;
738 }
739 }
740 /*************************************************************************
741 * If this is the last entry in the current VXR...
742 *************************************************************************/
743 if (entryN == VXR.NusedEntries - 1) {
744 if (VXR.VXRnext == ZERO_OFFSET) {
745 *prevRec = VXR.Last[entryN];
746 ASSIGNnotNULL (found, TRUE)
747 return pStatus;
748 }
749 if (!sX(ReadVXR(fp,VXR.VXRnext,
750 VXR_RECORD,&nextVXR,
751 VXR_NULL),&pStatus)) return pStatus;
752 if (baseRec < nextVXR.First[0]) {
753 *prevRec = VXR.Last[entryN];
754 ASSIGNnotNULL (found, TRUE)
755 return pStatus;
756 }
757 VXR = nextVXR;
758 entryN = 0;
759 }
760 else {
761 if (baseRec < VXR.First[entryN+1]) {
762 *prevRec = VXR.Last[entryN];
763 ASSIGNnotNULL (found, TRUE)
764 return pStatus;
765 }
766 entryN++;
767 }
768 }
769 }
770
771 /******************************************************************************
772 * NextRecord.
773 * Determine the next allocated record AT or AFTER `baseRec'. I.e., if
774 * `baseRec' is allocated, it is returned as `nextRec'.
775 ******************************************************************************/
776
NextRecord(CDF,VDRoffset,zVar,baseRec,nextRec,found)777 STATICforIDL CDFstatus NextRecord (CDF, VDRoffset, zVar, baseRec, nextRec,
778 found)
779 struct CDFstruct *CDF;
780 Int32 VDRoffset;
781 Logical zVar;
782 Int32 baseRec;
783 Int32 *nextRec;
784 Logical *found; /* If NULL, return NO_SUCH_RECORD if the next record
785 doesn't exist. Otherwise, set according to whether
786 or not the next record exists and return the pending
787 status. */
788 {
789 CDFstatus pStatus = CDF_OK; Int32 VXRoffset, maxRec;
790 /****************************************************************************
791 * If multi-file...
792 ****************************************************************************/
793 if (!CDF->singleFile) {
794 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
795 VDR_MAXREC,&maxRec,
796 VDR_NULL),&pStatus)) return pStatus;
797 if (baseRec <= maxRec) {
798 *nextRec = baseRec;
799 ASSIGNnotNULL (found, TRUE)
800 }
801 else {
802 ASSIGNnotNULL (found, FALSE)
803 if (found == NULL) pStatus = NO_SUCH_RECORD;
804 }
805 return pStatus;
806 }
807 /****************************************************************************
808 * ...single-file, read the offset of the first VXR.
809 ****************************************************************************/
810 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
811 VDR_VXRHEAD,&VXRoffset,
812 VDR_NULL),&pStatus)) return pStatus;
813 /****************************************************************************
814 * ...and start there.
815 ****************************************************************************/
816 if (!sX(NextRecord_r(CDF->fp,VXRoffset,
817 baseRec,nextRec,found),&pStatus)) return pStatus;
818 return pStatus;
819 }
820
NextRecord_r(fp,vxrOffset,baseRec,nextRec,found)821 static CDFstatus NextRecord_r (fp, vxrOffset, baseRec, nextRec, found)
822 vFILE *fp;
823 Int32 vxrOffset;
824 Int32 baseRec;
825 Int32 *nextRec;
826 Logical *found;
827 {
828 CDFstatus pStatus = CDF_OK;
829 int entryN; struct VXRstruct VXR; Int32 irType;
830 /****************************************************************************
831 * While more VXRs...
832 ****************************************************************************/
833 while (vxrOffset != ZERO_OFFSET) {
834 /**************************************************************************
835 * Read the VXR.
836 **************************************************************************/
837 if (!sX(ReadVXR(fp,vxrOffset,
838 VXR_RECORD,&VXR,
839 VXR_NULL),&pStatus)) return pStatus;
840 /**************************************************************************
841 * Search entries...
842 **************************************************************************/
843 if (baseRec <= VXR.Last[(int)(VXR.NusedEntries-1)]) {
844 for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
845 if (baseRec <= VXR.Last[entryN]) {
846 if (!sX(ReadIrType(fp,
847 VXR.Offset[entryN],
848 &irType),&pStatus)) return pStatus;
849 switch (irType) {
850 case VXR_:
851 return NextRecord_r(fp,VXR.Offset[entryN],
852 baseRec,nextRec,found);
853 case VVR_:
854 case CVVR_:
855 *nextRec = BOO(VXR.First[entryN] <= baseRec,
856 baseRec,VXR.First[entryN]);
857 ASSIGNnotNULL (found, TRUE)
858 return pStatus;
859 default:
860 return CORRUPTED_V2_CDF;
861 }
862 }
863 }
864 }
865 vxrOffset = VXR.VXRnext;
866 }
867 /****************************************************************************
868 * No (more) VXRs. The record number was never found.
869 ****************************************************************************/
870 ASSIGNnotNULL (found, FALSE)
871 return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
872 }
873
874 /******************************************************************************
875 * SearchForRecord.
876 ******************************************************************************/
877
SearchForRecord(CDF,VDRoffset,zVar,recNum,firstRec,lastRec,offset,found)878 STATICforIDL CDFstatus SearchForRecord (CDF, VDRoffset, zVar, recNum,
879 firstRec, lastRec, offset, found)
880 struct CDFstruct *CDF;
881 Int32 VDRoffset;
882 Logical zVar;
883 Int32 recNum;
884 Int32 *firstRec;
885 Int32 *lastRec;
886 Int32 *offset;
887 Logical *found; /* If NULL, return NO_SUCH_RECORD if the record is
888 not found. Otherwise, set according to whether
889 or not the record is found and return the pending
890 status. */
891 {
892 CDFstatus pStatus = CDF_OK; Int32 vxrOffset, maxRec;
893 /****************************************************************************
894 * If multi-file...
895 ****************************************************************************/
896 if (!CDF->singleFile) {
897 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
898 VDR_MAXREC,&maxRec,
899 VDR_NULL),&pStatus)) return pStatus;
900 if (recNum <= maxRec) {
901 ASSIGNnotNULL (firstRec, 0)
902 ASSIGNnotNULL (lastRec, maxRec)
903 ASSIGNnotNULL (offset, ZERO_OFFSET)
904 ASSIGNnotNULL (found, TRUE)
905 }
906 else {
907 ASSIGNnotNULL (found, FALSE)
908 if (found == NULL) pStatus = NO_SUCH_RECORD;
909 }
910 return pStatus;
911 }
912 /****************************************************************************
913 * ...single-file, read the offset of the first VXR.
914 ****************************************************************************/
915 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
916 VDR_VXRHEAD,&vxrOffset,
917 VDR_NULL),&pStatus)) return pStatus;
918 /****************************************************************************
919 * ...and start searching there.
920 ****************************************************************************/
921 if (!sX(SearchForRecord_r(CDF->fp,vxrOffset,recNum,
922 firstRec,lastRec,
923 offset,found),&pStatus)) return pStatus;
924 return pStatus;
925 }
926
SearchForRecord_r(fp,vxrOffset,recNum,firstRec,lastRec,offset,found)927 static CDFstatus SearchForRecord_r (fp, vxrOffset, recNum, firstRec, lastRec,
928 offset, found)
929 vFILE *fp;
930 Int32 vxrOffset;
931 Int32 recNum;
932 Int32 *firstRec;
933 Int32 *lastRec;
934 Int32 *offset;
935 Logical *found;
936 {
937 CDFstatus pStatus = CDF_OK;
938 int entryN; struct VXRstruct VXR; Int32 irType;
939 /****************************************************************************
940 * While more VXRs...
941 ****************************************************************************/
942 while (vxrOffset != ZERO_OFFSET) {
943 /**************************************************************************
944 * Read the VXR.
945 **************************************************************************/
946 if (!sX(ReadVXR(fp,vxrOffset,
947 VXR_RECORD,&VXR,
948 VXR_NULL),&pStatus)) return pStatus;
949 /**************************************************************************
950 * Search entries...
951 **************************************************************************/
952 if (recNum <= VXR.Last[(int)(VXR.NusedEntries-1)]) {
953 for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
954 if (recNum <= VXR.Last[entryN]) {
955 if (VXR.First[entryN] <= recNum) {
956 if (!sX(ReadIrType(fp,
957 VXR.Offset[entryN],
958 &irType),&pStatus)) return pStatus;
959 switch (irType) {
960 case VXR_:
961 return SearchForRecord_r(fp,VXR.Offset[entryN],recNum,
962 firstRec,lastRec,offset,found);
963 case VVR_:
964 case CVVR_:
965 ASSIGNnotNULL (firstRec, VXR.First[entryN])
966 ASSIGNnotNULL (lastRec, VXR.Last[entryN])
967 ASSIGNnotNULL (offset, VXR.Offset[entryN])
968 ASSIGNnotNULL (found, TRUE)
969 return pStatus;
970 default:
971 return CORRUPTED_V2_CDF;
972 }
973 }
974 else {
975 ASSIGNnotNULL (found, FALSE)
976 return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
977 }
978 }
979 }
980 }
981 vxrOffset = VXR.VXRnext;
982 }
983 /****************************************************************************
984 * No (more) VXRs. The record number was never found.
985 ****************************************************************************/
986 ASSIGNnotNULL (found, FALSE)
987 return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
988 }
989
990 /******************************************************************************
991 * IndexingStatistics.
992 ******************************************************************************/
993
IndexingStatistics(CDF,VDRoffset,zVar,nVXRsP,nEntriesP,nAllocP,nRecordsP,nLevelsP)994 STATICforIDL CDFstatus IndexingStatistics (CDF, VDRoffset, zVar, nVXRsP,
995 nEntriesP, nAllocP, nRecordsP,
996 nLevelsP)
997 struct CDFstruct *CDF;
998 Int32 VDRoffset;
999 Logical zVar;
1000 Int32 *nVXRsP;
1001 Int32 *nEntriesP;
1002 Int32 *nAllocP;
1003 Int32 *nRecordsP;
1004 Int32 *nLevelsP;
1005 {
1006 CDFstatus pStatus = CDF_OK; Int32 vxrOffset, maxRec; int level = 1;
1007 Int32 nVXRs = 0, nEntries = 0, nAlloc = 0, nRecords = 0, nLevels = 0;
1008 /****************************************************************************
1009 * Read the maximum record and the offset of the first VXR...
1010 ****************************************************************************/
1011 if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
1012 VDR_VXRHEAD,&vxrOffset,
1013 VDR_MAXREC,&maxRec,
1014 VDR_NULL),&pStatus)) return pStatus;
1015 /****************************************************************************
1016 * ...and start there.
1017 ****************************************************************************/
1018 if (vxrOffset != ZERO_OFFSET) {
1019 if (!sX(IndexingStatistics_r(CDF->fp,vxrOffset,
1020 maxRec,level,&nLevels,
1021 &nVXRs,&nEntries,
1022 &nAlloc,&nRecords),&pStatus)) return pStatus;
1023 }
1024 /****************************************************************************
1025 * Pass back requested statistics.
1026 ****************************************************************************/
1027 ASSIGNnotNULL (nVXRsP, nVXRs)
1028 ASSIGNnotNULL (nEntriesP, nEntries)
1029 ASSIGNnotNULL (nAllocP, nAlloc)
1030 ASSIGNnotNULL (nRecordsP, nRecords)
1031 ASSIGNnotNULL (nLevelsP, nLevels)
1032 return pStatus;
1033 }
1034
IndexingStatistics_r(fp,vxrOffset,maxRec,level,nLevels,nVXRs,nEntries,nAlloc,nRecords)1035 static CDFstatus IndexingStatistics_r (fp, vxrOffset, maxRec, level, nLevels,
1036 nVXRs, nEntries, nAlloc, nRecords)
1037 vFILE *fp;
1038 Int32 vxrOffset;
1039 Int32 maxRec;
1040 int level;
1041 Int32 *nLevels;
1042 Int32 *nVXRs;
1043 Int32 *nEntries;
1044 Int32 *nAlloc;
1045 Int32 *nRecords;
1046 {
1047 CDFstatus pStatus = CDF_OK;
1048 int e; Int32 irType; struct VXRstruct VXR;
1049 /****************************************************************************
1050 * Check if a new level has been reached.
1051 ****************************************************************************/
1052 *nLevels = MAXIMUM(*nLevels,level);
1053 /****************************************************************************
1054 * While more VXRs...
1055 ****************************************************************************/
1056 while (vxrOffset != ZERO_OFFSET) {
1057 /**************************************************************************
1058 * Read/tally the VXR.
1059 **************************************************************************/
1060 if (!sX(ReadVXR(fp,vxrOffset,
1061 VXR_RECORD,&VXR,
1062 VXR_NULL),&pStatus)) return pStatus;
1063 (*nVXRs)++;
1064 /**************************************************************************
1065 * Scan/count entries...
1066 **************************************************************************/
1067 for (e = 0; e < VXR.NusedEntries; e++) {
1068 (*nEntries)++;
1069 if (!sX(ReadIrType(fp,
1070 VXR.Offset[e],
1071 &irType),&pStatus)) return pStatus;
1072 switch (irType) {
1073 case VXR_:
1074 if (!sX(IndexingStatistics_r(fp,VXR.Offset[e],
1075 maxRec,level+1,
1076 nLevels,nVXRs,
1077 nEntries,nAlloc,
1078 nRecords),&pStatus)) return pStatus;
1079 break;
1080 case VVR_:
1081 case CVVR_:
1082 *nAlloc += (VXR.Last[e] - VXR.First[e] + 1);
1083 if (VXR.First[e] <= maxRec) {
1084 *nRecords += MINIMUM(maxRec,VXR.Last[e]) - VXR.First[e] + 1;
1085 }
1086 break;
1087 default:
1088 return CORRUPTED_V2_CDF;
1089 }
1090 }
1091 vxrOffset = VXR.VXRnext;
1092 }
1093 return pStatus;
1094 }
1095
1096 /******************************************************************************
1097 * BuildPadBuffer.
1098 ******************************************************************************/
1099
BuildPadBuffer(CDF,Var,nRecords,how,buffer,encode)1100 STATICforIDL CDFstatus BuildPadBuffer (CDF, Var, nRecords, how, buffer, encode)
1101 struct CDFstruct *CDF;
1102 struct VarStruct *Var;
1103 Int32 nRecords;
1104 int *how;
1105 void **buffer;
1106 Logical encode; /* If TRUE, return values in CDF's encoding. If FALSE,
1107 return values in host computer's encoding. */
1108 {
1109 Byte *ptr; Int32 nBytes, nValues, valueN; void *padValue;
1110 Int32 VDRflags, dataType, numElems; CDFstatus pStatus = CDF_OK;
1111 /****************************************************************************
1112 * Determine pad value.
1113 ****************************************************************************/
1114 if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
1115 VDR_DATATYPE,&dataType,
1116 VDR_NUMELEMS,&numElems,
1117 VDR_FLAGS,&VDRflags,
1118 VDR_NULL),&pStatus)) return pStatus;
1119 padValue = (void *) cdf_AllocateMemory ((size_t) Var->NvalueBytes, NULL);
1120 if (padValue == NULL) return BAD_MALLOC;
1121 if (PADvalueBITset(VDRflags)) {
1122 if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
1123 VDR_PADVALUE,padValue,
1124 VDR_NULL),&pStatus)) {
1125 cdf_FreeMemory (padValue, NULL);
1126 return pStatus;
1127 }
1128 if (!encode) {
1129 if (!sX(ConvertBuffer(CDF->encoding,HostDecoding(),
1130 CDF->negToPosFp0,dataType,
1131 numElems,padValue,padValue),&pStatus)) {
1132 cdf_FreeMemory (padValue, NULL);
1133 return pStatus;
1134 }
1135 }
1136 }
1137 else {
1138 DefaultPadValue (dataType, numElems, padValue);
1139 if (encode) {
1140 if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,
1141 CDF->negToPosFp0,dataType,
1142 numElems,padValue,padValue),&pStatus)) {
1143 cdf_FreeMemory (padValue, NULL);
1144 return pStatus;
1145 }
1146 }
1147 }
1148 /****************************************************************************
1149 * Try to allocate all of the records at once...
1150 ****************************************************************************/
1151 nValues = nRecords * Var->NphyRecValues;
1152 nBytes = nValues * Var->NvalueBytes;
1153 #if LIMITof64K
1154 if (nBytes < 65536L) {
1155 #endif
1156 *buffer = (void *) cdf_AllocateMemory ((size_t) nBytes, NULL);
1157 if (*buffer != NULL) {
1158 for (valueN = 0, ptr = (Byte *) *buffer;
1159 valueN < nValues; valueN++, ptr += (size_t) Var->NvalueBytes) {
1160 memmove (ptr, padValue, (size_t) Var->NvalueBytes);
1161 }
1162 cdf_FreeMemory (padValue, NULL);
1163 *how = ALLrecordsATonce;
1164 return pStatus;
1165 }
1166 #if LIMITof64K
1167 }
1168 #endif
1169 /****************************************************************************
1170 * Not enough memory for that, try allocating one record...
1171 ****************************************************************************/
1172 #if LIMITof64K
1173 if (Var->NphyRecBytes < 65536L) {
1174 #endif
1175 *buffer = (void *) cdf_AllocateMemory ((size_t) Var->NphyRecBytes, NULL);
1176 if (*buffer != NULL) {
1177 for (valueN = 0, ptr = (Byte *) *buffer;
1178 valueN < Var->NphyRecValues;
1179 valueN++, ptr += (size_t) Var->NvalueBytes) {
1180 memmove (ptr, padValue, (size_t) Var->NvalueBytes);
1181 }
1182 cdf_FreeMemory (padValue, NULL);
1183 *how = ONErecordATaTIME;
1184 return pStatus;
1185 }
1186 #if LIMITof64K
1187 }
1188 #endif
1189 /****************************************************************************
1190 * Not enough memory for that either, use the one allocated value...
1191 ****************************************************************************/
1192 *buffer = padValue;
1193 *how = ONEvalueATaTIME;
1194 return pStatus;
1195 }
1196
1197 /******************************************************************************
1198 * ReadVarValues.
1199 * NOTE: If more than one record is being read, full records are assumed
1200 * and the `offset' must be zero.
1201 ******************************************************************************/
1202
ReadVarValues(CDF,Var,startRec,offset,nValues,buffer)1203 STATICforIDL CDFstatus ReadVarValues (CDF, Var, startRec, offset, nValues,
1204 buffer)
1205 struct CDFstruct *CDF;
1206 struct VarStruct *Var;
1207 Int32 startRec; /* Physical record number at which to start reading. */
1208 Int32 offset; /* Byte offset within (first) record at which to
1209 begin reading. */
1210 Int32 nValues; /* Number of values to read. */
1211 void *buffer;
1212 {
1213 CDFstatus pStatus = CDF_OK; Int32 tOffset; Logical fullRecord;
1214 Int32 numElems, firstRec, lastRec, lastRecInVVR, nPadValues;
1215 Int32 readTo, recCount, nBytes;
1216 /****************************************************************************
1217 * Determine first/last record(s) being read and if full physical record(s).
1218 ****************************************************************************/
1219 firstRec = startRec;
1220 if (nValues < Var->NphyRecValues) {
1221 fullRecord = FALSE;
1222 lastRec = startRec;
1223 }
1224 else {
1225 fullRecord = TRUE;
1226 lastRec = startRec + ((nValues - 1) / Var->NphyRecValues);
1227 }
1228 /****************************************************************************
1229 * Read value(s).
1230 ****************************************************************************/
1231 switch (Var->vType) {
1232 /**************************************************************************
1233 * Standard variable in a single-file CDF...
1234 **************************************************************************/
1235 case STANDARD_:
1236 if (fullRecord) {
1237 /**********************************************************************
1238 * Full record(s) - read from contiguous groups...
1239 **********************************************************************/
1240 Byte *tBuffer = buffer; Int32 recNum = firstRec;
1241 while (recNum <= lastRec) {
1242 if (recNum <= Var->maxRec) {
1243 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
1244 Var->zVar,recNum,
1245 NULL,&lastRecInVVR,
1246 NULL,NULL),&pStatus)) return pStatus;
1247 readTo = MINIMUMof3(Var->maxRec,lastRec,lastRecInVVR);
1248 recCount = readTo - recNum + 1;
1249 if (!sX(RecordByteOffset(CDF,Var,
1250 recNum,
1251 &tOffset),&pStatus)) return pStatus;
1252 numElems = recCount * Var->NphyRecElems;
1253 if (!sX(ReadVarElems(Var,CDF->fp,tOffset,
1254 numElems,tBuffer),&pStatus)) return pStatus;
1255 }
1256 else {
1257 recCount = lastRec - recNum + 1;
1258 nPadValues = recCount * Var->NphyRecValues;
1259 if (!sX(PadBuffer(CDF,Var,
1260 nPadValues,
1261 tBuffer),&pStatus)) return pStatus;
1262 sX (VIRTUAL_RECORD_DATA, &pStatus);
1263 }
1264 recNum += recCount;
1265 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
1266 }
1267 }
1268 else {
1269 /**********************************************************************
1270 * Partial record...
1271 **********************************************************************/
1272 if (firstRec <= Var->maxRec) {
1273 if (!sX(RecordByteOffset(CDF,Var,
1274 firstRec,
1275 &tOffset),&pStatus)) return pStatus;
1276 tOffset += (Int32) offset;
1277 numElems = nValues * Var->NvalueElems;
1278 if (!sX(ReadVarElems(Var,CDF->fp,tOffset,
1279 numElems,buffer),&pStatus)) return pStatus;
1280 }
1281 else {
1282 if (!sX(PadBuffer(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
1283 sX (VIRTUAL_RECORD_DATA, &pStatus);
1284 }
1285 }
1286 break;
1287 /**************************************************************************
1288 * Sparse records...
1289 **************************************************************************/
1290 case SPARSE_RECORDS_: {
1291 if (fullRecord) {
1292 if (!sX(ReadSparseFull(CDF,Var,firstRec,
1293 lastRec,buffer),&pStatus)) return pStatus;
1294 }
1295 else {
1296 if (!sX(ReadSparsePartial(CDF,Var,
1297 startRec,offset,
1298 nValues,buffer),&pStatus)) return pStatus;
1299 }
1300 break;
1301 }
1302 /**************************************************************************
1303 * Compressed variable...
1304 **************************************************************************/
1305 case COMPRESSED_:
1306 case SPARSE_COMPRESSED_RECORDS_: {
1307 /************************************************************************
1308 * Initialize staging area. Note that the staging area is only
1309 * initialized if records have been written. This prevents the
1310 * CORRUPTED_V2_CDF error code from being returned if an explicit
1311 * blocking factor has not been specified for the variable.
1312 ************************************************************************/
1313 if (Var->stage.areaOffset == NO_OFFSET && Var->maxRec > NO_RECORD) {
1314 if (Var->blockingFactor == 0) return CORRUPTED_V2_CDF;
1315 nBytes = Var->blockingFactor * Var->NphyRecBytes;
1316 if (!sX(InitVarStage(CDF,Var,nBytes),&pStatus)) return pStatus;
1317 }
1318 /************************************************************************
1319 * If full record(s) or partial record...
1320 ************************************************************************/
1321 if (fullRecord) {
1322 if (!sX(ReadCompressedFull(CDF,Var,firstRec,
1323 lastRec,buffer),&pStatus)) return pStatus;
1324 }
1325 else {
1326 if (!sX(ReadCompressedPartial(CDF,Var,startRec,
1327 offset,nValues,
1328 buffer),&pStatus)) return pStatus;
1329 }
1330 break;
1331 }
1332 /**************************************************************************
1333 * Can't do sparse arrays yet...
1334 **************************************************************************/
1335 case SPARSE_ARRAYS_:
1336 case SPARSE_RECORDS_AND_ARRAYS_:
1337 return UNKNOWN_SPARSENESS;
1338 case IN_MULTI_:
1339 if (fullRecord) {
1340 /********************************************************************
1341 * Full record(s).
1342 ********************************************************************/
1343 Byte *tBuffer = buffer;
1344 if (firstRec <= Var->maxRec) {
1345 if (!sX(RecordByteOffset(CDF,Var,
1346 firstRec,
1347 &tOffset),&pStatus)) return pStatus;
1348 recCount = MINIMUM(lastRec,Var->maxRec) - firstRec + 1;
1349 numElems = recCount * Var->NphyRecElems;
1350 if (!sX(ReadVarElems(Var,Var->fp,tOffset,
1351 numElems,tBuffer),&pStatus)) return pStatus;
1352 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
1353 }
1354 if (lastRec > Var->maxRec) {
1355 recCount = BOO(Var->maxRec < firstRec,
1356 lastRec - firstRec + 1,
1357 lastRec - Var->maxRec);
1358 nPadValues = recCount * Var->NphyRecValues;
1359 if (!sX(PadBuffer(CDF,Var,
1360 nPadValues,
1361 tBuffer),&pStatus)) return pStatus;
1362 sX (VIRTUAL_RECORD_DATA, &pStatus);
1363 }
1364 }
1365 else {
1366 /********************************************************************
1367 * Partial record.
1368 ********************************************************************/
1369 if (firstRec <= Var->maxRec) {
1370 if (!sX(RecordByteOffset(CDF,Var,
1371 firstRec,
1372 &tOffset),&pStatus)) return pStatus;
1373 tOffset += (Int32) offset;
1374 numElems = nValues * Var->NvalueElems;
1375 if (!sX(ReadVarElems(Var,Var->fp,tOffset,
1376 numElems,buffer),&pStatus)) return pStatus;
1377 }
1378 else {
1379 if (!sX(PadBuffer(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
1380 sX (VIRTUAL_RECORD_DATA, &pStatus);
1381 }
1382 }
1383 break;
1384 }
1385 return pStatus;
1386 }
1387
1388 /******************************************************************************
1389 * ReadVarElems.
1390 * NOTE: On IBM PCs, it is assumed that the number of bytes being read
1391 * will not exceed 65535.
1392 ******************************************************************************/
1393
ReadVarElems(Var,fp,offset,numElems,buffer)1394 STATICforIDL CDFstatus ReadVarElems (Var, fp, offset, numElems, buffer)
1395 struct VarStruct *Var;
1396 vFILE *fp;
1397 Int32 offset;
1398 Int32 numElems;
1399 void *buffer;
1400 {
1401 CDFstatus pStatus = CDF_OK; size_t nBytes;
1402 /****************************************************************************
1403 * Seek to the desired offset.
1404 ****************************************************************************/
1405 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return VAR_READ_ERROR;
1406 /****************************************************************************
1407 * Read the value(s).
1408 ****************************************************************************/
1409 nBytes = (size_t) (numElems * Var->NelemBytes);
1410 if (!READv(buffer,nBytes,1,fp)) return VAR_READ_ERROR;
1411 /****************************************************************************
1412 * Decode value(s).
1413 ****************************************************************************/
1414 if (!sX(DECODE(Var->DecodeFunction,buffer,numElems),&pStatus)) {
1415 return pStatus;
1416 }
1417 return pStatus;
1418 }
1419
1420 /******************************************************************************
1421 * ROWtoCOL.
1422 ******************************************************************************/
1423
ROWtoCOL(iBuffer,oBuffer,numDims,dimSizes,nValueBytes)1424 VISIBLE_PREFIX void ROWtoCOL (iBuffer, oBuffer, numDims, dimSizes, nValueBytes)
1425 void *iBuffer;
1426 void *oBuffer;
1427 long numDims;
1428 long dimSizes[];
1429 long nValueBytes;
1430 {
1431 switch (numDims) {
1432 case 0:
1433 case 1: {
1434 long nValues; int dimN;
1435 for (dimN = 0, nValues = 1; dimN < numDims; dimN++) {
1436 nValues *= dimSizes[dimN];
1437 }
1438 memmove (oBuffer, iBuffer, (size_t) (nValues * nValueBytes));
1439 break;
1440 }
1441 default: {
1442 long products[CDF_MAX_DIMS]; /* Products, what each dimension is
1443 `worth'. */
1444 long iBoffset; /* Input buffer, byte offset. */
1445 long oBoffset; /* Output buffer, byte offset. */
1446 long oVoffset; /* Output buffer, value offset. */
1447 int dimN; /* Dimension number. */
1448 for (dimN = 1, products[0] = 1; dimN < numDims; dimN++) {
1449 products[dimN] = products[dimN-1] * dimSizes[dimN-1];
1450 }
1451 switch (numDims) {
1452 case 2: {
1453 int d0, d1; /* Indices... */
1454 for (d0 = 0, iBoffset = 0; d0 < dimSizes[0]; d0++) {
1455 for (d1 = 0; d1 < dimSizes[1]; d1++) {
1456 oVoffset = ((long) d0 * products[0]) + ((long) d1 * products[1]);
1457 oBoffset = oVoffset * nValueBytes;
1458 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1459 (Byte *) iBuffer + (size_t) iBoffset,
1460 (size_t) nValueBytes);
1461 iBoffset += nValueBytes;
1462 }
1463 }
1464 break;
1465 }
1466 case 3: {
1467 int d0, d1, d2; /* Indices... */
1468 for (d0 = 0, iBoffset = 0; d0 < dimSizes[0]; d0++) {
1469 for (d1 = 0; d1 < dimSizes[1]; d1++) {
1470 for (d2 = 0; d2 < dimSizes[2]; d2++) {
1471 oVoffset = ((long) d0 * products[0]) + ((long) d1 * products[1]) +
1472 ((long) d2 * products[2]);
1473 oBoffset = oVoffset * nValueBytes;
1474 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1475 (Byte *) iBuffer + (size_t) iBoffset,
1476 (size_t) nValueBytes);
1477 iBoffset += nValueBytes;
1478 }
1479 }
1480 }
1481 break;
1482 }
1483 default: {
1484 long indices[CDF_MAX_DIMS]; long nValues; int i;
1485 for (dimN = 0; dimN < numDims; dimN++) indices[dimN] = 0;
1486 for (dimN = 0, nValues = 1; dimN < numDims; dimN++) {
1487 nValues *= dimSizes[dimN];
1488 }
1489 for (i = 0, iBoffset = 0; i < (int) nValues; i++) {
1490 for (oVoffset = 0, dimN = 0; dimN < numDims; dimN++) {
1491 oVoffset += indices[dimN] * products[dimN];
1492 }
1493 oBoffset = oVoffset * nValueBytes;
1494 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1495 (Byte *) iBuffer + (size_t) iBoffset,
1496 (size_t) nValueBytes);
1497 iBoffset += nValueBytes;
1498 INCRindicesROW (numDims, dimSizes, indices);
1499 }
1500 break;
1501 }
1502 }
1503 break;
1504 }
1505 }
1506 return;
1507 }
1508
1509 /******************************************************************************
1510 * COLtoROW.
1511 ******************************************************************************/
1512
COLtoROW(iBuffer,oBuffer,numDims,dimSizes,nValueBytes)1513 VISIBLE_PREFIX void COLtoROW (iBuffer, oBuffer, numDims, dimSizes, nValueBytes)
1514 void *iBuffer;
1515 void *oBuffer;
1516 long numDims;
1517 long dimSizes[];
1518 long nValueBytes;
1519 {
1520 switch (numDims) {
1521 case 0:
1522 case 1: {
1523 long nValues; int dimN;
1524 for (dimN = 0, nValues = 1; dimN < numDims; dimN++) {
1525 nValues *= dimSizes[dimN];
1526 }
1527 memmove (oBuffer, iBuffer, (size_t) (nValues * nValueBytes));
1528 break;
1529 }
1530 default: {
1531 long products[CDF_MAX_DIMS]; /* Products, what each dimension is
1532 `worth'. */
1533 long iBoffset; /* Input buffer, byte offset. */
1534 long oBoffset; /* Output buffer, byte offset. */
1535 long oVoffset; /* Output buffer, value offset. */
1536 int dimN; /* Dimension number. */
1537 products[(int)(numDims-1)] = 1;
1538 for (dimN = (int) (numDims - 2); dimN >= 0; dimN--) {
1539 products[dimN] = products[dimN+1] * dimSizes[dimN+1];
1540 }
1541 switch (numDims) {
1542 case 2: {
1543 int d0, d1; /* Indices... */
1544 for (d1 = 0, iBoffset = 0; d1 < dimSizes[1]; d1++) {
1545 for (d0 = 0; d0 < dimSizes[0]; d0++) {
1546 oVoffset = ((long) d0 * products[0]) + ((long) d1 * products[1]);
1547 oBoffset = oVoffset * nValueBytes;
1548 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1549 (Byte *) iBuffer + (size_t) iBoffset,
1550 (size_t) nValueBytes);
1551 iBoffset += nValueBytes;
1552 }
1553 }
1554 break;
1555 }
1556 case 3: {
1557 int d0, d1, d2; /* Indices... */
1558 for (d2 = 0, iBoffset = 0; d2 < dimSizes[2]; d2++) {
1559 for (d1 = 0; d1 < dimSizes[1]; d1++) {
1560 for (d0 = 0; d0 < dimSizes[0]; d0++) {
1561 oVoffset = ((long) d0 * products[0]) + ((long) d1 * products[1]) +
1562 ((long) d2 * products[2]);
1563 oBoffset = oVoffset * nValueBytes;
1564 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1565 (Byte *) iBuffer + (size_t) iBoffset,
1566 (size_t) nValueBytes);
1567 iBoffset += nValueBytes;
1568 }
1569 }
1570 }
1571 break;
1572 }
1573 default: {
1574 long indices[CDF_MAX_DIMS]; long nValues; int i;
1575 for (dimN = 0; dimN < numDims; dimN++) indices[dimN] = 0;
1576 for (dimN = 0, nValues = 1; dimN < numDims; dimN++) {
1577 nValues *= dimSizes[dimN];
1578 }
1579 for (i = 0, iBoffset = 0; i < (int) nValues; i++) {
1580 for (oVoffset = 0, dimN = 0; dimN < numDims; dimN++) {
1581 oVoffset += indices[dimN] * products[dimN];
1582 }
1583 oBoffset = oVoffset * nValueBytes;
1584 memmove ((Byte *) oBuffer + (size_t) oBoffset,
1585 (Byte *) iBuffer + (size_t) iBoffset,
1586 (size_t) nValueBytes);
1587 iBoffset += nValueBytes;
1588 INCRindicesCOL (numDims, dimSizes, indices);
1589 }
1590 break;
1591 }
1592 }
1593 break;
1594 }
1595 }
1596 return;
1597 }
1598
1599 /******************************************************************************
1600 * INCRindicesROW.
1601 * Increment to next set of indices, row majority. When at the last set of
1602 * indices, roll over to 0,0,0,...
1603 ******************************************************************************/
1604
INCRindicesROW(numDims,dimSizes,indices)1605 VISIBLE_PREFIX void INCRindicesROW (numDims, dimSizes, indices)
1606 long numDims;
1607 long dimSizes[];
1608 long indices[];
1609 {
1610 int dimN;
1611 for (dimN = (int) (numDims - 1); dimN >= 0; dimN--)
1612 if (indices[dimN] == dimSizes[dimN] - 1)
1613 indices[dimN] = 0;
1614 else {
1615 indices[dimN]++;
1616 break;
1617 }
1618 return;
1619 }
1620
1621 /******************************************************************************
1622 * INCRindicesCOL.
1623 * Increment to next set of indices, column majority. When at the last set
1624 * of indices, roll over to 0,0,0,...
1625 ******************************************************************************/
1626
INCRindicesCOL(numDims,dimSizes,indices)1627 VISIBLE_PREFIX void INCRindicesCOL (numDims, dimSizes, indices)
1628 long numDims;
1629 long dimSizes[];
1630 long indices[];
1631 {
1632 int dimN;
1633 for (dimN = 0; dimN < numDims; dimN++)
1634 if (indices[dimN] == dimSizes[dimN] - 1)
1635 indices[dimN] = 0;
1636 else {
1637 indices[dimN]++;
1638 break;
1639 }
1640 return;
1641 }
1642
1643 /******************************************************************************
1644 * InitVarStage.
1645 ******************************************************************************/
1646
InitVarStage(CDF,Var,nBytes)1647 STATICforIDL CDFstatus InitVarStage (CDF, Var, nBytes)
1648 struct CDFstruct *CDF;
1649 struct VarStruct *Var;
1650 Int32 nBytes;
1651 {
1652 if (CDF->stage.fp == NULL) {
1653 CDF->stage.fp = V_scratch (ScratchDirectory(CDF), "stg");
1654 if (CDF->stage.fp == NULL) return SCRATCH_CREATE_ERROR;
1655 if (!CACHEv(CDF->stage.fp,CDF->stage.cacheSize)) {
1656 V_delete (CDF->stage.fp, NULL);
1657 CDF->stage.fp = NULL;
1658 return BAD_CACHE_SIZE;
1659 }
1660 CDF->stage.mark = ZERO_OFFSET;
1661 }
1662 Var->stage.areaOffset = CDF->stage.mark;
1663 Var->stage.firstRec = NO_RECORD;
1664 Var->stage.lastRec = NO_RECORD;
1665 Var->stage.dotOffset = NO_OFFSET;
1666 Var->stage.modified = FALSE;
1667 CDF->stage.mark += nBytes;
1668 return CDF_OK;
1669 }
1670
1671 /******************************************************************************
1672 * InitScratch.
1673 ******************************************************************************/
1674
InitScratch(scratchDir,scratchFpH,cacheSize)1675 STATICforIDL CDFstatus InitScratch (scratchDir, scratchFpH, cacheSize)
1676 char *scratchDir; /* Scratch directory to be used. */
1677 vFILE **scratchFpH; /* Scratch file handle (pointer to pointer). */
1678 int cacheSize; /* Number of cache buffers to request. */
1679 {
1680 if (*scratchFpH == NULL) {
1681 *scratchFpH = V_scratch (scratchDir, NULL);
1682 if (*scratchFpH == NULL) return SCRATCH_CREATE_ERROR;
1683 if (!CACHEv(*scratchFpH,cacheSize)) {
1684 V_delete (*scratchFpH, NULL);
1685 *scratchFpH = NULL;
1686 return BAD_CACHE_SIZE;
1687 }
1688 }
1689 else {
1690 if (V_clear(*scratchFpH) != 0) return SCRATCH_READ_ERROR;
1691 if (!SEEKv(*scratchFpH,0L,vSEEK_SET)) return SCRATCH_READ_ERROR;
1692 }
1693 return CDF_OK;
1694 }
1695
1696 /******************************************************************************
1697 * ScratchDirectory.
1698 ******************************************************************************/
1699
ScratchDirectory(CDF)1700 STATICforIDL char *ScratchDirectory (CDF)
1701 struct CDFstruct *CDF; /* Pointer to CDF structure. This might be NULL if a
1702 scratch directory is needed but a CDF has not yet
1703 been opened/created. */
1704 {
1705 char *envTmp = NULL;
1706 if (CDF != NULL) {
1707 if (CDF->scratchDir != NULL) return CDF->scratchDir;
1708 }
1709 #if defined(vms)
1710 envTmp = getenv ("CDF$TMP");
1711 #endif
1712 #if defined(unix) || defined(dos) || defined(posixSHELL) || defined(win32)
1713 envTmp = getenv ("CDF_TMP");
1714 #endif
1715 if (envTmp != NULL) return envTmp;
1716 return NULL;
1717 }
1718
1719 /******************************************************************************
1720 * FlushStage.
1721 ******************************************************************************/
1722
FlushStage(CDF,Var)1723 STATICforIDL CDFstatus FlushStage (CDF, Var)
1724 struct CDFstruct *CDF;
1725 struct VarStruct *Var;
1726 {
1727 CDFstatus pStatus = CDF_OK;
1728 /****************************************************************************
1729 * Based on the variable type...
1730 ****************************************************************************/
1731 switch (Var->vType) {
1732 case SPARSE_RECORDS_: {
1733 Int32 nRecords, nBytes, tOffset; struct AllocStruct alloc;
1734 /************************************************************************
1735 * First check if there are records to be flushed in the staging area.
1736 ************************************************************************/
1737 if (!Var->stage.modified) return pStatus;
1738 /************************************************************************
1739 * Allocate a new VVR.
1740 ************************************************************************/
1741 LoadAllocVVR (alloc, Var->stage.firstRec, Var->stage.lastRec, FALSE)
1742 if (!sX(AllocateRecords(CDF,Var,alloc),&pStatus)) return pStatus;
1743 Var->maxAllocated = MAXIMUM(Var->maxAllocated,Var->stage.lastRec);
1744 /************************************************************************
1745 * Copy the records to the new VVR.
1746 ************************************************************************/
1747 if (!sX(RecordByteOffset(CDF,Var,
1748 Var->stage.firstRec,
1749 &tOffset),&pStatus)) return pStatus;
1750 nRecords = Var->stage.lastRec - Var->stage.firstRec + 1;
1751 nBytes = nRecords * Var->NphyRecBytes;
1752 if (!sX(CopyBytes(CDF->stage.fp,Var->stage.areaOffset,
1753 SCRATCH_READ_ERROR,nBytes,CDF->fp,
1754 tOffset,CDF_WRITE_ERROR),&pStatus)) return pStatus;
1755 Var->maxWritten = MAXIMUM(Var->maxWritten,Var->stage.lastRec);
1756 /************************************************************************
1757 * Clear the staging area control.
1758 ************************************************************************/
1759 Var->stage.firstRec = NO_RECORD;
1760 Var->stage.lastRec = NO_RECORD;
1761 Var->stage.dotOffset = NO_OFFSET;
1762 Var->stage.modified = FALSE;
1763 break;
1764 }
1765 case COMPRESSED_:
1766 case SPARSE_COMPRESSED_RECORDS_: {
1767 Int32 cSize, xSize, irSize, newOffset, nRecords, uSize;
1768 struct CVVRstruct CVVR; struct VVRstruct VVR; struct AllocStruct alloc;
1769 /************************************************************************
1770 * First check if there are records to be flushed in the staging area.
1771 ************************************************************************/
1772 if (!Var->stage.modified) return pStatus;
1773 /************************************************************************
1774 * Check if the scratch file is created/initialized.
1775 ************************************************************************/
1776 if (!sX(InitScratch(ScratchDirectory(CDF),
1777 &(CDF->compressFp),
1778 CDF->compressCacheSize),&pStatus)) return pStatus;
1779 /************************************************************************
1780 * Compress the records in the stage.
1781 ************************************************************************/
1782 nRecords = Var->stage.lastRec - Var->stage.firstRec + 1;
1783 uSize = nRecords * Var->NphyRecBytes;
1784 if (!sX(Compress(CDF->stage.fp,Var->stage.areaOffset,
1785 uSize,SCRATCH_READ_ERROR,Var->cType,
1786 Var->cParms,CDF->compressFp,ZERO_OFFSET,
1787 &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus;
1788 /************************************************************************
1789 * Does a VVR/CVVR for this block of records already exist?
1790 ************************************************************************/
1791 if (Var->stage.dotOffset != NO_OFFSET) {
1792 /**********************************************************************
1793 * Read the size of the existing VVR/CVVR.
1794 **********************************************************************/
1795 if (!sX(ReadIrSize(CDF->fp,
1796 Var->stage.dotOffset,
1797 &irSize),&pStatus)) return pStatus;
1798 /**********************************************************************
1799 * Will a CVVR fit? Note that reserve space is only added to new CVVRs.
1800 **********************************************************************/
1801 if (CVVR_BASE_SIZE + cSize <= irSize) {
1802 LoadCVVRx (CVVR, irSize, cSize)
1803 if (!sX(WriteCVVR(CDF->fp,Var->stage.dotOffset,
1804 CVVR_RECORDx,&CVVR,
1805 CVVR_NULL),&pStatus)) return pStatus;
1806 if (!sX(CopyBytes(CDF->compressFp,ZERO_OFFSET,
1807 SCRATCH_READ_ERROR,cSize,CDF->fp,
1808 Var->stage.dotOffset + CVVR_BASE_SIZE,
1809 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1810 Var->stage.modified = FALSE;
1811 return pStatus;
1812 }
1813 /**********************************************************************
1814 * Will a VVR fit?
1815 **********************************************************************/
1816 if (VVR_BASE_SIZE + uSize <= irSize) {
1817 LoadVVRx (VVR, irSize)
1818 if (!sX(WriteVVR(CDF->fp,Var->stage.dotOffset,
1819 VVR_RECORDx,&VVR,
1820 VVR_NULL),&pStatus)) return pStatus;
1821 if (!sX(CopyBytes(CDF->stage.fp,Var->stage.areaOffset,
1822 SCRATCH_READ_ERROR,uSize,CDF->fp,
1823 Var->stage.dotOffset + VVR_BASE_SIZE,
1824 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1825 Var->stage.modified = FALSE;
1826 sX (DID_NOT_COMPRESS, &pStatus);
1827 return pStatus;
1828 }
1829 /**********************************************************************
1830 * The existing VVR/CVVR will have to be resized. Will a CVVR be
1831 * smaller than a VVR? Note that reserve space is not added to the
1832 * size of the CVVR because a new one isn't being created.
1833 **********************************************************************/
1834 if (CVVR_BASE_SIZE + cSize < VVR_BASE_SIZE + uSize) {
1835 if (!sX(ResizeIR(CDF,Var->stage.dotOffset,
1836 CVVR_BASE_SIZE + cSize,
1837 &newOffset,TRUE,NULL),&pStatus)) return pStatus;
1838 LoadCVVRx (CVVR, CVVR_BASE_SIZE + cSize, cSize)
1839 if (!sX(WriteCVVR(CDF->fp,newOffset,
1840 CVVR_RECORDx,&CVVR,
1841 CVVR_NULL),&pStatus)) return pStatus;
1842 if (!sX(CopyBytes(CDF->compressFp,ZERO_OFFSET,
1843 SCRATCH_READ_ERROR,cSize,
1844 CDF->fp,newOffset + CVVR_BASE_SIZE,
1845 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1846 }
1847 else {
1848 if (!sX(ResizeIR(CDF,Var->stage.dotOffset,
1849 VVR_BASE_SIZE + uSize,
1850 &newOffset,TRUE,NULL),&pStatus)) return pStatus;
1851 LoadVVRx (VVR, VVR_BASE_SIZE + uSize)
1852 if (!sX(WriteVVR(CDF->fp,newOffset,
1853 VVR_RECORDx,&VVR,
1854 VVR_NULL),&pStatus)) return pStatus;
1855 if (!sX(CopyBytes(CDF->stage.fp,Var->stage.areaOffset,
1856 SCRATCH_READ_ERROR,uSize,
1857 CDF->fp,newOffset + VVR_BASE_SIZE,
1858 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1859 sX (DID_NOT_COMPRESS, &pStatus);
1860 }
1861 if (!sX(ModIndexOffset(CDF,Var,
1862 Var->stage.firstRec,
1863 Var->stage.lastRec,
1864 newOffset),&pStatus)) return pStatus;
1865 Var->stage.dotOffset = newOffset;
1866 Var->stage.modified = FALSE;
1867 return pStatus;
1868 }
1869 /************************************************************************
1870 * A new VVR/CVVR will have to be created. First calculate the reserve
1871 * size.
1872 ************************************************************************/
1873 if (Var->reservePct <= 0)
1874 xSize = 0;
1875 else {
1876 if (Var->reservePct <= 100) {
1877 Int32 tSize = (Int32) ((uSize * (Var->reservePct/100.0)) + 0.5);
1878 xSize = MAXIMUM(cSize,tSize) - cSize;
1879 }
1880 else {
1881 Int32 tSize = (Int32) ((cSize * (Var->reservePct/100.0)) + 0.5);
1882 xSize = tSize - cSize;
1883 }
1884 }
1885 /************************************************************************
1886 * Will a CVVR be smaller than a VVR?
1887 ************************************************************************/
1888 if (CVVR_BASE_SIZE + cSize + xSize < VVR_BASE_SIZE + uSize) {
1889 LoadAllocCVVR (alloc, Var->stage.firstRec, Var->stage.lastRec,
1890 cSize, xSize)
1891 if (!sX(AllocateRecords(CDF,Var,alloc),&pStatus)) return pStatus;
1892 if (!sX(SearchForRecord(CDF,Var->VDRoffset,Var->zVar,
1893 Var->stage.firstRec,NULL,NULL,
1894 &newOffset,NULL),&pStatus)) return pStatus;
1895 LoadCVVRx (CVVR, CVVR_BASE_SIZE + cSize + xSize, cSize)
1896 if (!sX(WriteCVVR(CDF->fp,newOffset,
1897 CVVR_RECORDx,&CVVR,
1898 CVVR_NULL),&pStatus)) return pStatus;
1899 if (!sX(CopyBytes(CDF->compressFp,ZERO_OFFSET,
1900 SCRATCH_READ_ERROR,cSize,
1901 CDF->fp,newOffset + CVVR_BASE_SIZE,
1902 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1903 Var->stage.dotOffset = newOffset;
1904 Var->stage.modified = FALSE;
1905 return pStatus;
1906 }
1907 /************************************************************************
1908 * The CVVR will be too big - create a VVR.
1909 ************************************************************************/
1910 LoadAllocVVR (alloc, Var->stage.firstRec, Var->stage.lastRec, TRUE)
1911 if (!sX(AllocateRecords(CDF,Var,alloc),&pStatus)) return pStatus;
1912 if (!sX(SearchForRecord(CDF,Var->VDRoffset,Var->zVar,
1913 Var->stage.firstRec,NULL,NULL,
1914 &newOffset,NULL),&pStatus)) return pStatus;
1915 LoadVVRx (VVR, VVR_BASE_SIZE + uSize)
1916 if (!sX(WriteVVR(CDF->fp,newOffset,
1917 VVR_RECORDx,&VVR,
1918 VVR_NULL),&pStatus)) return pStatus;
1919 if (!sX(CopyBytes(CDF->stage.fp,Var->stage.areaOffset,
1920 SCRATCH_READ_ERROR,uSize,
1921 CDF->fp,newOffset + VVR_BASE_SIZE,
1922 CDF_WRITE_ERROR),&pStatus)) return pStatus;
1923 Var->stage.dotOffset = newOffset;
1924 Var->stage.modified = FALSE;
1925 sX (DID_NOT_COMPRESS, &pStatus);
1926 return pStatus;
1927 }
1928 default:
1929 return CDF_INTERNAL_ERROR;
1930 }
1931 return pStatus;
1932 }
1933
1934 /******************************************************************************
1935 * BringToStage.
1936 ******************************************************************************/
1937
BringToStage(CDF,Var,recNum,found)1938 static CDFstatus BringToStage (CDF, Var, recNum, found)
1939 struct CDFstruct *CDF;
1940 struct VarStruct *Var;
1941 Int32 recNum;
1942 Logical *found;
1943 {
1944 CDFstatus pStatus = CDF_OK;
1945 /****************************************************************************
1946 * First check if record is already in the stage.
1947 ****************************************************************************/
1948 if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
1949 ASSIGNnotNULL (found, TRUE)
1950 return pStatus;
1951 }
1952 /****************************************************************************
1953 * Then, based on variable type...
1954 ****************************************************************************/
1955 switch (Var->vType) {
1956 case COMPRESSED_:
1957 case SPARSE_COMPRESSED_RECORDS_: {
1958 Int32 firstRec, lastRec, offset, nRecords, uSize; Logical foundX;
1959 /************************************************************************
1960 * Determine if the record exists.
1961 ************************************************************************/
1962 if (!sX(SearchForRecord(CDF,Var->VDRoffset,Var->zVar,
1963 recNum,&firstRec,&lastRec,
1964 &offset,&foundX),&pStatus)) return pStatus;
1965 ASSIGNnotNULL (found, foundX)
1966 if (!foundX) return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
1967 /************************************************************************
1968 * Flush the stage before...
1969 ************************************************************************/
1970 if (!sX(FlushStage(CDF,Var),&pStatus)) return pStatus;
1971 /************************************************************************
1972 * ...decompressing the CVVR (or VVR if the records did not compress) to
1973 * the staging area.
1974 ************************************************************************/
1975 nRecords = lastRec - firstRec + 1;
1976 uSize = nRecords * Var->NphyRecBytes;
1977 if (!sX(DecompressToStage(CDF,Var,
1978 offset,uSize),&pStatus)) return pStatus;
1979 /************************************************************************
1980 * Update staging control.
1981 ************************************************************************/
1982 Var->stage.firstRec = firstRec;
1983 Var->stage.lastRec = lastRec;
1984 Var->stage.dotOffset = offset;
1985 Var->stage.modified = FALSE;
1986 break;
1987 }
1988 default:
1989 return CDF_INTERNAL_ERROR;
1990 }
1991 return pStatus;
1992 }
1993
1994 /******************************************************************************
1995 * CopyBytes.
1996 ******************************************************************************/
1997
CopyBytes(iFp,iStart,iError,nBytes,oFp,oStart,oError)1998 STATICforIDL CDFstatus CopyBytes (iFp, iStart, iError, nBytes, oFp, oStart,
1999 oError)
2000 vFILE *iFp;
2001 Int32 iStart;
2002 CDFstatus iError;
2003 Int32 nBytes;
2004 vFILE *oFp;
2005 Int32 oStart;
2006 CDFstatus oError;
2007 {
2008 Int32 nBlocks = nBytes / COPYblockSIZE; /* Number of full blocks that
2009 can be copied. */
2010 Int32 lastCount = nBytes % COPYblockSIZE; /* Number of bytes remaining
2011 to be copied after the full
2012 blocks have been copied. */
2013 Int32 i; Byte buffer[COPYblockSIZE];
2014 /****************************************************************************
2015 * If the copy is within the same file...
2016 ****************************************************************************/
2017 if (iFp == oFp) {
2018 /**************************************************************************
2019 * If the input group (of bytes) is before the output group start at the
2020 * end in case they overlap.
2021 **************************************************************************/
2022 if (iStart < oStart) {
2023 if (nBlocks > 0) {
2024 Int32 iOffset = iStart + nBytes - COPYblockSIZE;
2025 Int32 oOffset = oStart + nBytes - COPYblockSIZE;
2026 for (i = 0; i < nBlocks; i++) {
2027 if (!SEEKv(iFp,(long)iOffset,vSEEK_SET)) return iError;
2028 if (!READv(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return
2029 iError;
2030 if (!SEEKv(oFp,(long)oOffset,vSEEK_SET)) return oError;
2031 if (!WRITEv(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return
2032 oError;
2033 iOffset -= COPYblockSIZE;
2034 oOffset -= COPYblockSIZE;
2035 }
2036 }
2037 if (lastCount > 0) {
2038 if (!SEEKv(iFp,(long)iStart,vSEEK_SET)) return iError;
2039 if (!READv(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
2040 if (!SEEKv(oFp,(long)oStart,vSEEK_SET)) return oError;
2041 if (!WRITEv(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
2042 }
2043 }
2044 /**************************************************************************
2045 * If the input group (of bytes) is after the output group start at the
2046 * beginning in case they overlap.
2047 **************************************************************************/
2048 if (iStart > oStart) {
2049 Int32 iOffset = iStart;
2050 Int32 oOffset = oStart;
2051 if (nBlocks > 0) {
2052 for (i = 0; i < nBlocks; i++) {
2053 if (!SEEKv(iFp,(long)iOffset,vSEEK_SET)) return iError;
2054 if (!READv(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return
2055 iError;
2056 if (!SEEKv(oFp,(long)oOffset,vSEEK_SET)) return oError;
2057 if (!WRITEv(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return
2058 oError;
2059 iOffset += COPYblockSIZE;
2060 oOffset += COPYblockSIZE;
2061 }
2062 }
2063 if (lastCount > 0) {
2064 if (!SEEKv(iFp,(long)iOffset,vSEEK_SET)) return iError;
2065 if (!READv(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
2066 if (!SEEKv(oFp,(long)oOffset,vSEEK_SET)) return oError;
2067 if (!WRITEv(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
2068 }
2069 }
2070 /**************************************************************************
2071 * Offsets are the same - do nothing.
2072 **************************************************************************/
2073 }
2074 else {
2075 /**************************************************************************
2076 * Different files...
2077 **************************************************************************/
2078 if (!SEEKv(iFp,(long)iStart,vSEEK_SET)) return iError;
2079 if (!SEEKv(oFp,(long)oStart,vSEEK_SET)) return oError;
2080 for (i = 0; i < nBlocks; i++) {
2081 if (!READv(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return iError;
2082 if (!WRITEv(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return oError;
2083 }
2084 if (lastCount > 0) {
2085 if (!READv(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
2086 if (!WRITEv(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
2087 }
2088 }
2089 return CDF_OK;
2090 }
2091
2092 /******************************************************************************
2093 * ModIndexOffset.
2094 ******************************************************************************/
2095
ModIndexOffset(CDF,Var,firstRec,lastRec,newOffset)2096 STATICforIDL CDFstatus ModIndexOffset (CDF, Var, firstRec, lastRec, newOffset)
2097 struct CDFstruct *CDF; /* Pointer to CDF. */
2098 struct VarStruct *Var; /* Pointer to variable. */
2099 Int32 firstRec; /* First record of entry. */
2100 Int32 lastRec; /* Last record of entry. */
2101 Int32 newOffset; /* New VVR/CVVR/SVVR offset. */
2102 {
2103 CDFstatus pStatus = CDF_OK; Int32 vxrOffset;
2104 /****************************************************************************
2105 * Read offset of first VXR...
2106 ****************************************************************************/
2107 if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
2108 VDR_VXRHEAD,&vxrOffset,
2109 VDR_NULL),&pStatus)) return pStatus;
2110 /****************************************************************************
2111 * ...and start there.
2112 ****************************************************************************/
2113 if (!sX(ModIndexOffset_r(CDF->fp,vxrOffset,
2114 firstRec,lastRec,
2115 newOffset),&pStatus)) return pStatus;
2116 return pStatus;
2117 }
2118
ModIndexOffset_r(fp,vxrOffset,firstRec,lastRec,newOffset)2119 static CDFstatus ModIndexOffset_r (fp, vxrOffset, firstRec, lastRec, newOffset)
2120 vFILE *fp; /* File pointer to dotCDF file. */
2121 Int32 vxrOffset; /* VXR at which to start. */
2122 Int32 firstRec; /* First record of entry. */
2123 Int32 lastRec; /* Last record of entry. */
2124 Int32 newOffset; /* New VVR/CVVR/SVVR offset. */
2125 {
2126 CDFstatus pStatus = CDF_OK;
2127 struct VXRstruct VXR; int entryN; Int32 irType;
2128 /****************************************************************************
2129 * While more VXRs...
2130 ****************************************************************************/
2131 while (vxrOffset != ZERO_OFFSET) {
2132 /**************************************************************************
2133 * Read the VXR.
2134 **************************************************************************/
2135 if (!sX(ReadVXR(fp,vxrOffset,
2136 VXR_RECORD,&VXR,
2137 VXR_NULL),&pStatus)) return pStatus;
2138 /**************************************************************************
2139 * Search through index entries...
2140 **************************************************************************/
2141 for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
2142 if (VXR.First[entryN] <= firstRec && lastRec <= VXR.Last[entryN]) {
2143 if (!sX(ReadIrType(fp,
2144 VXR.Offset[entryN],
2145 &irType),&pStatus)) return pStatus;
2146 if (irType == VXR_) return ModIndexOffset_r(fp,VXR.Offset[entryN],
2147 firstRec,lastRec,
2148 newOffset);
2149 if (VXR.First[entryN] == firstRec && lastRec == VXR.Last[entryN]) {
2150 VXR.Offset[entryN] = newOffset;
2151 if (!sX(WriteVXR(fp,vxrOffset,
2152 VXR_RECORD,&VXR,
2153 VXR_NULL),&pStatus)) return pStatus;
2154 return pStatus;
2155 }
2156 return CDF_INTERNAL_ERROR; /* or CORRUPTED_V2_CDF? */
2157 }
2158 }
2159 /**************************************************************************
2160 * Go to next VXR.
2161 **************************************************************************/
2162 vxrOffset = VXR.VXRnext;
2163 }
2164 /****************************************************************************
2165 * No more VXRs.
2166 ****************************************************************************/
2167 return CDF_INTERNAL_ERROR;
2168 }
2169
2170 /******************************************************************************
2171 * WriteCompressedRecords.
2172 ******************************************************************************/
2173
WriteCompressedRecords(CDF,Var,firstRec,lastRec,buffer,nValues,offset,fullRecord)2174 static CDFstatus WriteCompressedRecords (CDF, Var, firstRec, lastRec, buffer,
2175 nValues, offset, fullRecord)
2176 struct CDFstruct *CDF; /* Pointer to CDF. */
2177 struct VarStruct *Var; /* Pointer to variable. */
2178 Int32 firstRec; /* First record being written. */
2179 Int32 lastRec; /* Last record being written. */
2180 void *buffer; /* Buffer of values. */
2181 Int32 nValues; /* Number of values being written. */
2182 Int32 offset; /* If not full record(s), byte offset in record at
2183 which to write. */
2184 Logical fullRecord; /* Full record(s) being written? */
2185 {
2186 CDFstatus pStatus = CDF_OK; Logical found;
2187 Int32 recCount, tOffset, recordOffsetInStage, maxRecThisBlock;
2188 Int32 nextRec, writeTo, numElems; void *padBuffer; int how;
2189 Int32 recNum = firstRec; Byte *tBuffer = (Byte *) buffer;
2190 /****************************************************************************
2191 * From first to last record...
2192 ****************************************************************************/
2193 while (recNum <= lastRec) {
2194 /*************************************************************************
2195 * Check if this record is in the staging area.
2196 *************************************************************************/
2197 if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
2198 recordOffsetInStage = recNum - Var->stage.firstRec;
2199 tOffset = Var->stage.areaOffset;
2200 tOffset += (recordOffsetInStage * Var->NphyRecBytes);
2201 if (fullRecord) {
2202 if (Var->stage.dotOffset == NO_OFFSET) {
2203 maxRecThisBlock = Var->stage.firstRec + Var->blockingFactor - 1;
2204 if (!sX(NextRecord(CDF,Var->VDRoffset,
2205 Var->zVar,recNum,
2206 &nextRec,&found),&pStatus)) return pStatus;
2207 if (!found)
2208 writeTo = MINIMUM(maxRecThisBlock,lastRec);
2209 else {
2210 Int32 prevRecN = nextRec - 1;
2211 writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
2212 }
2213 }
2214 else
2215 writeTo = MINIMUM(Var->stage.lastRec,lastRec);
2216 recCount = writeTo - recNum + 1;
2217 numElems = recCount * Var->NphyRecElems;
2218 }
2219 else {
2220 writeTo = recNum;
2221 recCount = 1;
2222 numElems = nValues * Var->NvalueElems;
2223 tOffset += offset;
2224 }
2225 if (!sX(WriteVarElems(Var,CDF->stage.fp,
2226 tOffset,numElems,
2227 tBuffer),&pStatus)) return pStatus;
2228 Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
2229 Var->stage.modified = TRUE;
2230 tBuffer += (size_t) (numElems * Var->NelemBytes);
2231 recNum += recCount;
2232 continue;
2233 }
2234 /*************************************************************************
2235 * Not in the staging area...check if this record is in an existing CVVR.
2236 *************************************************************************/
2237 if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2238 if (found) {
2239 recordOffsetInStage = recNum - Var->stage.firstRec;
2240 tOffset = Var->stage.areaOffset;
2241 tOffset += (recordOffsetInStage * Var->NphyRecBytes);
2242 if (fullRecord) {
2243 writeTo = MINIMUM(Var->stage.lastRec,lastRec);
2244 recCount = writeTo - recNum + 1;
2245 numElems = recCount * Var->NphyRecElems;
2246 }
2247 else {
2248 writeTo = recNum;
2249 recCount = 1;
2250 numElems = nValues * Var->NvalueElems;
2251 tOffset += offset;
2252 }
2253 if (!sX(WriteVarElems(Var,CDF->stage.fp,
2254 tOffset,numElems,
2255 tBuffer),&pStatus)) return pStatus;
2256 Var->stage.modified = TRUE;
2257 tBuffer += (size_t) (numElems * Var->NelemBytes);
2258 recNum += recCount;
2259 continue;
2260 }
2261 /*************************************************************************
2262 * Not in an existing CVVR...this record does not exist. First check
2263 * if the record(s) can be added to the records in the stage.
2264 *************************************************************************/
2265 if (Var->stage.firstRec != NO_RECORD) {
2266 if (Var->stage.dotOffset == NO_OFFSET) {
2267 if (recNum == Var->stage.lastRec + 1) {
2268 maxRecThisBlock = Var->stage.firstRec + Var->blockingFactor - 1;
2269 if (recNum <= maxRecThisBlock) {
2270 recordOffsetInStage = recNum - Var->stage.firstRec;
2271 tOffset = Var->stage.areaOffset;
2272 tOffset += (recordOffsetInStage * Var->NphyRecBytes);
2273 if (fullRecord) {
2274 if (!sX(NextRecord(CDF,Var->VDRoffset,
2275 Var->zVar,recNum,
2276 &nextRec,&found),&pStatus)) return pStatus;
2277 if (!found)
2278 writeTo = MINIMUM(maxRecThisBlock,lastRec);
2279 else {
2280 Int32 prevRecN = nextRec - 1;
2281 writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
2282 }
2283 recCount = writeTo - recNum + 1;
2284 numElems = recCount * Var->NphyRecElems;
2285 }
2286 else {
2287 if (!sX(BuildPadBuffer(CDF,Var,INT32_ONE,
2288 &how,&padBuffer,
2289 TRUE),&pStatus)) return pStatus;
2290 if (!sX(WritePadValues(Var,CDF->stage.fp,
2291 tOffset,INT32_ONE,how,
2292 padBuffer),&pStatus)) return pStatus;
2293 cdf_FreeMemory (padBuffer, NULL);
2294 writeTo = recNum;
2295 recCount = 1;
2296 numElems = nValues * Var->NvalueElems;
2297 tOffset += offset;
2298 }
2299 if (!sX(WriteVarElems(Var,CDF->stage.fp,
2300 tOffset,numElems,
2301 tBuffer),&pStatus)) return pStatus;
2302 Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
2303 Var->stage.modified = TRUE;
2304 tBuffer += (size_t) (numElems * Var->NelemBytes);
2305 recNum += recCount;
2306 continue;
2307 }
2308 }
2309 }
2310 }
2311 /*************************************************************************
2312 * This record cannot be added to the block of records currently in
2313 * the staging area. Start a new block of records.
2314 *************************************************************************/
2315 if (!sX(FlushStage(CDF,Var),&pStatus)) return pStatus;
2316 tOffset = Var->stage.areaOffset;
2317 if (fullRecord) {
2318 maxRecThisBlock = recNum + Var->blockingFactor - 1;
2319 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
2320 recNum,&nextRec,&found),&pStatus)) return pStatus;
2321 if (!found)
2322 writeTo = MINIMUM(maxRecThisBlock,lastRec);
2323 else {
2324 Int32 prevRecN = nextRec - 1;
2325 writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
2326 }
2327 recCount = writeTo - recNum + 1;
2328 numElems = recCount * Var->NphyRecElems;
2329 }
2330 else {
2331 if (!sX(BuildPadBuffer(CDF,Var,INT32_ONE,
2332 &how,&padBuffer,
2333 TRUE),&pStatus)) return pStatus;
2334 if (!sX(WritePadValues(Var,CDF->stage.fp,
2335 tOffset,INT32_ONE,how,
2336 padBuffer),&pStatus)) return pStatus;
2337 cdf_FreeMemory (padBuffer, NULL);
2338 writeTo = recNum;
2339 recCount = 1;
2340 numElems = nValues * Var->NvalueElems;
2341 tOffset += offset;
2342 }
2343 if (!sX(WriteVarElems(Var,CDF->stage.fp,
2344 tOffset,numElems,
2345 tBuffer),&pStatus)) return pStatus;
2346 Var->stage.firstRec = recNum;
2347 Var->stage.lastRec = writeTo;
2348 Var->stage.dotOffset = NO_OFFSET;
2349 Var->stage.modified = TRUE;
2350 tBuffer += (size_t) (numElems * Var->NelemBytes);
2351 recNum += recCount;
2352 }
2353 return pStatus;
2354 }
2355
2356 /******************************************************************************
2357 * CalcCompressionPct.
2358 ******************************************************************************/
2359
CalcCompressionPct(CDF,vdrOffset,zVar,cPct)2360 STATICforIDL CDFstatus CalcCompressionPct (CDF, vdrOffset, zVar, cPct)
2361 struct CDFstruct *CDF;
2362 Int32 vdrOffset;
2363 Logical zVar;
2364 long *cPct;
2365 {
2366 CDFstatus pStatus = CDF_OK; Int32 vxrOffset;
2367 long uTotal = 0, cTotal = 0; Int32 nPhyRecBytes;
2368 /****************************************************************************
2369 * Calculate the number of bytes per physical record.
2370 ****************************************************************************/
2371 if (!sX(CalcPhyRecBytes(CDF,vdrOffset,
2372 zVar,&nPhyRecBytes),&pStatus)) return pStatus;
2373 /****************************************************************************
2374 * Read the offset of the first VXR (return 0% if no VXRs)...
2375 ****************************************************************************/
2376 if (!sX(ReadVDR(CDF,CDF->fp,vdrOffset,zVar,
2377 VDR_VXRHEAD,&vxrOffset,
2378 VDR_NULL),&pStatus)) return pStatus;
2379 if (vxrOffset == ZERO_OFFSET) {
2380 *cPct = 0;
2381 return pStatus;
2382 }
2383 /****************************************************************************
2384 * ...and start there.
2385 ****************************************************************************/
2386 if (!sX(CalcCompressionPct_r(CDF->fp,vxrOffset,
2387 nPhyRecBytes,
2388 &uTotal,&cTotal),&pStatus)) return pStatus;
2389 /****************************************************************************
2390 * Calculate percentage.
2391 ****************************************************************************/
2392 *cPct = (long) (((100.0*cTotal) / uTotal) + 0.5);
2393 return pStatus;
2394 }
2395
CalcCompressionPct_r(fp,vxrOffset,nPhyRecBytes,uTotal,cTotal)2396 static CDFstatus CalcCompressionPct_r (fp, vxrOffset, nPhyRecBytes, uTotal,
2397 cTotal)
2398 vFILE *fp;
2399 Int32 vxrOffset;
2400 Int32 nPhyRecBytes;
2401 long *uTotal;
2402 long *cTotal;
2403 {
2404 CDFstatus pStatus = CDF_OK; struct VXRstruct VXR; int entryN;
2405 Int32 nRecords, uSize, irType, irSize;
2406 /****************************************************************************
2407 * While more VXRs...
2408 ****************************************************************************/
2409 while (vxrOffset != ZERO_OFFSET) {
2410 /**************************************************************************
2411 * Read the VXR.
2412 **************************************************************************/
2413 if (!sX(ReadVXR(fp,vxrOffset,
2414 VXR_RECORD,&VXR,
2415 VXR_NULL),&pStatus)) return pStatus;
2416 /**************************************************************************
2417 * Scan entries...
2418 **************************************************************************/
2419 for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
2420 if (!sX(ReadIrType(fp,VXR.Offset[entryN],&irType),&pStatus)) return
2421 pStatus;
2422 switch (irType) {
2423 case VXR_:
2424 if (!sX(CalcCompressionPct_r(fp,VXR.Offset[entryN],
2425 nPhyRecBytes,uTotal,
2426 cTotal),&pStatus)) return pStatus;
2427 break;
2428 case VVR_:
2429 case CVVR_:
2430 /*******************************************************************
2431 * Accumulate uncompressed size.
2432 *******************************************************************/
2433 nRecords = VXR.Last[entryN] - VXR.First[entryN] + 1;
2434 uSize = nRecords * nPhyRecBytes;
2435 *uTotal += uSize;
2436 /*******************************************************************
2437 * Accumulate compressed size.
2438 *******************************************************************/
2439 if (!sX(ReadIrSize(fp,VXR.Offset[entryN],&irSize),&pStatus)) return
2440 pStatus;
2441 *cTotal += irSize - BOO(irType == CVVR_,
2442 CVVR_BASE_SIZE,
2443 VVR_BASE_SIZE);
2444 break;
2445 default:
2446 return CORRUPTED_V2_CDF;
2447 }
2448 }
2449 vxrOffset = VXR.VXRnext;
2450 }
2451 return pStatus;
2452 }
2453
2454 /******************************************************************************
2455 * CalcPhyRecBytes.
2456 ******************************************************************************/
2457
CalcPhyRecBytes(CDF,vdrOffset,zVar,nPhyRecBytes)2458 STATICforIDL CDFstatus CalcPhyRecBytes (CDF, vdrOffset, zVar, nPhyRecBytes)
2459 struct CDFstruct *CDF;
2460 Int32 vdrOffset;
2461 Logical zVar;
2462 Int32 *nPhyRecBytes;
2463 {
2464 CDFstatus pStatus = CDF_OK; int dimN; Int32 dataType, numElems;
2465 Int32 numDims, dimSizes[CDF_MAX_DIMS], dimVarys[CDF_MAX_DIMS];
2466 if (!sX(CalcDimParms(CDF,vdrOffset,zVar,
2467 &numDims,dimSizes,dimVarys),&pStatus)) return pStatus;
2468 if (!sX(ReadVDR(CDF,CDF->fp,vdrOffset,zVar,
2469 VDR_DATATYPE,&dataType,
2470 VDR_NUMELEMS,&numElems,
2471 VDR_NULL),&pStatus)) return pStatus;
2472 *nPhyRecBytes = CDFelemSize((long)dataType) * numElems;
2473 for (dimN = 0; dimN < numDims; dimN++) {
2474 if (dimVarys[dimN]) *nPhyRecBytes *= dimSizes[dimN];
2475 }
2476 return pStatus;
2477 }
2478
2479 /******************************************************************************
2480 * ReadSparseFull.
2481 ******************************************************************************/
2482
ReadSparseFull(CDF,Var,firstRec,lastRec,buffer)2483 static CDFstatus ReadSparseFull (CDF, Var, firstRec, lastRec, buffer)
2484 struct CDFstruct *CDF;
2485 struct VarStruct *Var;
2486 Int32 firstRec;
2487 Int32 lastRec;
2488 void *buffer;
2489 {
2490 CDFstatus pStatus = CDF_OK; Logical found;
2491 Int32 readTo, recCount, numElems, recX, prevRecN;
2492 Int32 nextRec, padTo, tOffset, nPadValues;
2493 Int32 recNum = firstRec;
2494 Byte *tBuffer = (Byte *) buffer;
2495 /****************************************************************************
2496 * While there are more records to be read/generated...
2497 ****************************************************************************/
2498 while (recNum <= lastRec) {
2499 /**************************************************************************
2500 * Is the record in the staging area?
2501 **************************************************************************/
2502 if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
2503 readTo = MINIMUM(Var->stage.lastRec,lastRec);
2504 recCount = readTo - recNum + 1;
2505 numElems = recCount * Var->NphyRecElems;
2506 recX = recNum - Var->stage.firstRec;
2507 tOffset = Var->stage.areaOffset + (recX * Var->NphyRecBytes);
2508 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2509 tOffset,numElems,tBuffer),&pStatus)) return pStatus;
2510 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2511 recNum += recCount;
2512 continue;
2513 }
2514 /**************************************************************************
2515 * Does the record exist and has been written to (not just allocated)?
2516 **************************************************************************/
2517 if (recNum <= Var->maxRec) {
2518 Int32 firstRecInVVR, lastRecInVVR;
2519 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
2520 Var->zVar,recNum,
2521 &firstRecInVVR,
2522 &lastRecInVVR,
2523 &tOffset,&found),&pStatus)) return pStatus;
2524 if (found) {
2525 readTo = MINIMUMof3(Var->maxRec,lastRec,lastRecInVVR);
2526 recCount = readTo - recNum + 1;
2527 numElems = recCount * Var->NphyRecElems;
2528 recX = recNum - firstRecInVVR;
2529 tOffset += VVR_BASE_SIZE + (recX * Var->NphyRecBytes);
2530 if (!sX(ReadVarElems(Var,CDF->fp,tOffset,
2531 numElems,tBuffer),&pStatus)) return pStatus;
2532 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2533 recNum += recCount;
2534 continue;
2535 }
2536 }
2537 /**************************************************************************
2538 * Determine which records need to be padded.
2539 **************************************************************************/
2540 if (recNum <= Var->maxRec) {
2541 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
2542 recNum,&nextRec,&found),&pStatus)) return pStatus;
2543 if (found) {
2544 if (EXCLUSIVE(recNum,
2545 Var->stage.firstRec,
2546 nextRec)) nextRec = Var->stage.firstRec;
2547 prevRecN = nextRec - 1;
2548 padTo = MINIMUM(prevRecN,lastRec);
2549 }
2550 else {
2551 prevRecN = Var->stage.firstRec - 1;
2552 padTo = MINIMUM(prevRecN,lastRec);
2553 }
2554 }
2555 else
2556 padTo = lastRec;
2557 recCount = padTo - recNum + 1;
2558 /**************************************************************************
2559 * If sRecords.PREV...
2560 **************************************************************************/
2561 if (Var->prevIfMissing) {
2562 Int32 prevRec; Byte *destBuffer;
2563 if (!sX(PrevRecord(CDF,Var->VDRoffset,Var->zVar,
2564 MINIMUM(recNum,Var->maxRec),
2565 &prevRec,&found),&pStatus)) return pStatus;
2566 if (found) {
2567 if (EXCLUSIVE(prevRec,Var->stage.lastRec,recNum)) {
2568 recX = Var->stage.lastRec - Var->stage.firstRec;
2569 tOffset = Var->stage.areaOffset + (recX * Var->NphyRecBytes);
2570 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2571 tOffset,Var->NphyRecElems,
2572 tBuffer),&pStatus)) return pStatus;
2573 }
2574 else {
2575 if (!sX(RecordByteOffset(CDF,Var,
2576 prevRec,
2577 &tOffset),&pStatus)) return pStatus;
2578 if (!sX(ReadVarElems(Var,CDF->fp,tOffset,
2579 Var->NphyRecElems,
2580 tBuffer),&pStatus)) return pStatus;
2581 }
2582 destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2583 for (recX = 1; recX < recCount; recX++) {
2584 memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2585 destBuffer += (size_t) Var->NphyRecBytes;
2586 }
2587 sX (VIRTUAL_RECORD_DATA, &pStatus);
2588 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2589 recNum += recCount;
2590 continue;
2591 }
2592 if (EXCLUSIVE(NO_RECORD,Var->stage.lastRec,recNum)) {
2593 recX = Var->stage.lastRec - Var->stage.firstRec;
2594 tOffset = Var->stage.areaOffset + (recX * Var->NphyRecBytes);
2595 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2596 tOffset,Var->NphyRecElems,
2597 tBuffer),&pStatus)) return pStatus;
2598 destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2599 for (recX = 1; recX < recCount; recX++) {
2600 memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2601 destBuffer += (size_t) Var->NphyRecBytes;
2602 }
2603 sX (VIRTUAL_RECORD_DATA, &pStatus);
2604 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2605 recNum += recCount;
2606 continue;
2607 }
2608 }
2609 /**************************************************************************
2610 * Pad with the variable's pad value. This occurs if the variable is
2611 * sRecords.NO, sRecords.PAD, or if sRecords.PREV but a previous record
2612 * does not exist (in a VVR or the staging area).
2613 **************************************************************************/
2614 nPadValues = recCount * Var->NphyRecValues;
2615 if (!sX(PadBuffer(CDF,Var,nPadValues,tBuffer),&pStatus)) return pStatus;
2616 sX (VIRTUAL_RECORD_DATA, &pStatus);
2617 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2618 recNum += recCount;
2619 }
2620 return pStatus;
2621 }
2622
2623 /******************************************************************************
2624 * ReadSparsePartial.
2625 ******************************************************************************/
2626
ReadSparsePartial(CDF,Var,recNum,offset,nValues,buffer)2627 static CDFstatus ReadSparsePartial (CDF, Var, recNum, offset, nValues, buffer)
2628 struct CDFstruct *CDF;
2629 struct VarStruct *Var;
2630 Int32 recNum;
2631 Int32 offset;
2632 Int32 nValues;
2633 void *buffer;
2634 {
2635 CDFstatus pStatus = CDF_OK; Logical found;
2636 Int32 tOffset, firstRec, prevRec;
2637 Int32 numElems = nValues * Var->NvalueElems;
2638 /****************************************************************************
2639 * If the record is in the staging area...
2640 ****************************************************************************/
2641 if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
2642 tOffset = Var->stage.areaOffset;
2643 tOffset += Var->NphyRecBytes * (recNum - Var->stage.firstRec);
2644 tOffset += offset;
2645 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2646 tOffset,numElems,buffer),&pStatus)) return pStatus;
2647 return pStatus;
2648 }
2649 /****************************************************************************
2650 * If the record exists and has been written (ie. not just allocated)...
2651 ****************************************************************************/
2652 if (recNum <= Var->maxRec) {
2653 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
2654 Var->zVar,recNum,&firstRec,
2655 NULL,&tOffset,&found),&pStatus)) return pStatus;
2656 if (found) {
2657 tOffset += VVR_BASE_SIZE;
2658 tOffset += Var->NphyRecBytes * (recNum - firstRec);
2659 tOffset += offset;
2660 if (!sX(ReadVarElems(Var,CDF->fp,
2661 tOffset,numElems,buffer),&pStatus)) return pStatus;
2662 return pStatus;
2663 }
2664 }
2665 /****************************************************************************
2666 * If missing records are to be read from the previous record...
2667 ****************************************************************************/
2668 if (Var->prevIfMissing) {
2669 /**************************************************************************
2670 * Check if a previous record exists in a VVR.
2671 **************************************************************************/
2672 if (!sX(PrevRecord(CDF,Var->VDRoffset,Var->zVar,
2673 MINIMUM(recNum,Var->maxRec),
2674 &prevRec,&found),&pStatus)) return pStatus;
2675 /**************************************************************************
2676 * If so, also make sure that the last record in the staging area isn't
2677 * really the previous record to use.
2678 **************************************************************************/
2679 if (found) {
2680 if (EXCLUSIVE(prevRec,Var->stage.lastRec,recNum)) {
2681 Int32 recNumInStage = Var->stage.lastRec - Var->stage.firstRec;
2682 tOffset = Var->stage.areaOffset;
2683 tOffset += Var->NphyRecBytes * recNumInStage;
2684 tOffset += offset;
2685 if (!sX(ReadVarElems(Var,CDF->stage.fp,tOffset,
2686 numElems,buffer),&pStatus)) return pStatus;
2687 }
2688 else {
2689 if (!sX(RecordByteOffset(CDF,Var,
2690 prevRec,
2691 &tOffset),&pStatus)) return pStatus;
2692 tOffset += offset;
2693 if (!sX(ReadVarElems(Var,CDF->fp,tOffset,
2694 numElems,buffer),&pStatus)) return pStatus;
2695 }
2696 sX (VIRTUAL_RECORD_DATA, &pStatus);
2697 return pStatus;
2698 }
2699 /**************************************************************************
2700 * A previous record does not exist in a VVR...check if the last record in
2701 * the staging area is the previous record.
2702 **************************************************************************/
2703 if (EXCLUSIVE(NO_RECORD,Var->stage.lastRec,recNum)) {
2704 Int32 recNumInStage = Var->stage.lastRec - Var->stage.firstRec;
2705 tOffset = Var->stage.areaOffset;
2706 tOffset += Var->NphyRecBytes * recNumInStage;
2707 tOffset += offset;
2708 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2709 tOffset,numElems,buffer),&pStatus)) return pStatus;
2710 sX (VIRTUAL_RECORD_DATA, &pStatus);
2711 return pStatus;
2712 }
2713 }
2714 /****************************************************************************
2715 * Pad the buffer with the variable's pad value. Note that this is also done
2716 * if the variable is sRecords.PREV but a previous record does not exist.
2717 ****************************************************************************/
2718 if (!sX(PadBuffer(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
2719 sX (VIRTUAL_RECORD_DATA, &pStatus);
2720 return pStatus;
2721 }
2722
2723 /******************************************************************************
2724 * ReadCompressedFull.
2725 ******************************************************************************/
2726
ReadCompressedFull(CDF,Var,firstRec,lastRec,buffer)2727 static CDFstatus ReadCompressedFull (CDF, Var, firstRec, lastRec, buffer)
2728 struct CDFstruct *CDF;
2729 struct VarStruct *Var;
2730 Int32 firstRec;
2731 Int32 lastRec;
2732 void *buffer;
2733 {
2734 CDFstatus pStatus = CDF_OK; Logical found;
2735 Int32 readTo, recCount, numElems, recX, tOffset, nextRec;
2736 Int32 recNum = firstRec, nPadValues, prevRec, padTo;
2737 Byte *tBuffer = (Byte *) buffer, *destBuffer;
2738 /****************************************************************************
2739 * While there are more records to be read/generated...
2740 ****************************************************************************/
2741 while (recNum <= lastRec) {
2742 /**************************************************************************
2743 * Try to bring the record to the staging area.
2744 **************************************************************************/
2745 if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2746 if (found) {
2747 readTo = MINIMUM(Var->stage.lastRec,lastRec);
2748 recCount = readTo - recNum + 1;
2749 numElems = recCount * Var->NphyRecElems;
2750 recX = recNum - Var->stage.firstRec;
2751 tOffset = Var->stage.areaOffset + (recX * Var->NphyRecBytes);
2752 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2753 tOffset,numElems,tBuffer),&pStatus)) return pStatus;
2754 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2755 recNum += recCount;
2756 continue;
2757 }
2758 /**************************************************************************
2759 * Determine which records need to be padded.
2760 **************************************************************************/
2761 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
2762 recNum,&nextRec,&found),&pStatus)) return pStatus;
2763 if (found) {
2764 if (EXCLUSIVE(recNum,
2765 Var->stage.firstRec,
2766 nextRec)) nextRec = Var->stage.firstRec;
2767 prevRec = nextRec - 1;
2768 padTo = MINIMUM(prevRec,lastRec);
2769 }
2770 else
2771 padTo = BOO(Var->stage.firstRec > recNum,
2772 Var->stage.firstRec - 1,lastRec);
2773 recCount = padTo - recNum + 1;
2774 /**************************************************************************
2775 * If sRecords.PREV...
2776 **************************************************************************/
2777 if (Var->prevIfMissing) {
2778 if (!sX(PrevRecord(CDF,Var->VDRoffset,Var->zVar,
2779 recNum,&prevRec,&found),&pStatus)) return pStatus;
2780 if (!found) prevRec = NO_RECORD;
2781 if (EXCLUSIVE(prevRec,
2782 Var->stage.lastRec,
2783 recNum)) prevRec = Var->stage.lastRec;
2784 if (prevRec > NO_RECORD) {
2785 if (!sX(BringToStage(CDF,Var,prevRec,NULL),&pStatus)) return pStatus;
2786 recX = prevRec - Var->stage.firstRec;
2787 tOffset = Var->stage.areaOffset + (recX * Var->NphyRecBytes);
2788 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2789 tOffset,Var->NphyRecElems,
2790 tBuffer),&pStatus)) return pStatus;
2791 destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2792 for (recX = 1; recX < recCount; recX++) {
2793 memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2794 destBuffer += (size_t) Var->NphyRecBytes;
2795 }
2796 sX (VIRTUAL_RECORD_DATA, &pStatus);
2797 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2798 recNum += recCount;
2799 continue;
2800 }
2801 }
2802 /**************************************************************************
2803 * Pad with the variable's pad value. This occurs if the variable is
2804 * sRecords.NO, sRecords.PAD, or if sRecords.PREV but a previous record
2805 * does not exist (in a CVVR/VVR or the staging area).
2806 **************************************************************************/
2807 nPadValues = recCount * Var->NphyRecValues;
2808 if (!sX(PadBuffer(CDF,Var,nPadValues,tBuffer),&pStatus)) return pStatus;
2809 sX (VIRTUAL_RECORD_DATA, &pStatus);
2810 tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2811 recNum += recCount;
2812 }
2813 return pStatus;
2814 }
2815
2816 /******************************************************************************
2817 * ReadCompressedPartial.
2818 ******************************************************************************/
2819
ReadCompressedPartial(CDF,Var,recNum,offset,nValues,buffer)2820 static CDFstatus ReadCompressedPartial (CDF, Var, recNum, offset, nValues,
2821 buffer)
2822 struct CDFstruct *CDF;
2823 struct VarStruct *Var;
2824 Int32 recNum;
2825 Int32 offset;
2826 Int32 nValues;
2827 void *buffer;
2828 {
2829 CDFstatus pStatus = CDF_OK;
2830 Int32 numElems = nValues * Var->NvalueElems;
2831 Int32 tOffset, prevRec, recX; Logical found;
2832 /****************************************************************************
2833 * Try to bring the record to the staging area.
2834 ****************************************************************************/
2835 if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2836 if (found) {
2837 tOffset = Var->stage.areaOffset;
2838 tOffset += Var->NphyRecBytes * (recNum - Var->stage.firstRec);
2839 tOffset += offset;
2840 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2841 tOffset,numElems,buffer),&pStatus)) return pStatus;
2842 return pStatus;
2843 }
2844 /****************************************************************************
2845 * If sRecords.PREV...
2846 ****************************************************************************/
2847 if (Var->prevIfMissing) {
2848 if (!sX(PrevRecord(CDF,Var->VDRoffset,
2849 Var->zVar,recNum,
2850 &prevRec,&found),&pStatus)) return pStatus;
2851 if (!found) prevRec = NO_RECORD;
2852 if (EXCLUSIVE(prevRec,
2853 Var->stage.lastRec,
2854 recNum)) prevRec = Var->stage.lastRec;
2855 if (prevRec > NO_RECORD) {
2856 if (!sX(BringToStage(CDF,Var,prevRec,NULL),&pStatus)) return pStatus;
2857 recX = Var->stage.lastRec - Var->stage.firstRec;
2858 tOffset = Var->stage.areaOffset + (Var->NphyRecBytes * recX) + offset;
2859 if (!sX(ReadVarElems(Var,CDF->stage.fp,
2860 tOffset,numElems,buffer),&pStatus)) return pStatus;
2861 sX (VIRTUAL_RECORD_DATA, &pStatus);
2862 return pStatus;
2863 }
2864 }
2865 /****************************************************************************
2866 * Pad the buffer with the variable's pad value. Note that this is also done
2867 * if the variable is sRecords.PREV but a previous record does not exist.
2868 ****************************************************************************/
2869 if (!sX(PadBuffer(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
2870 sX (VIRTUAL_RECORD_DATA, &pStatus);
2871 return pStatus;
2872 }
2873
2874 #if defined(MSVC67)
2875 /******************************************************************************
2876 * Replace _ftol2 with _ftol on Windows as VC 6.0 doesn't have a such function.
2877 ******************************************************************************/
2878
_ftol2(dblSource)2879 VISIBLE_PREFIX long _ftol2(dblSource)
2880 double dblSource;
2881 {
2882 return (long) _ftol( dblSource );
2883 }
2884 #endif
2885