1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF. The full HDF copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* $Id$ */
15
16 /*-----------------------------------------------------------------------------
17 File: dfsd.c
18
19 Purpose:
20 Routines for input and output of numeric data group
21
22 Invokes:
23 df.c dfgroup.c dfkit.c dfi.h df.h dfsd.h
24
25 Public functions:
26 DFSDgetdims - get rank and dim sizes
27 DFSDgetdatastrs - get label, unit, format and coord system of data
28 DFSDgetdimstrs - get label, unit and format for a dimension
29 DFSDgetdatalen -
30 DFSDgetdimlen -
31 DFSDgetdimscale - get scale for a dimension
32 DFSDgetrange - get max and min of data
33 DFSDgetdata - get data values
34 DFSDgetNT - get file number type for reading
35 DFSDpre32sdg - tests, without calling DFSDsdginfo, whether or
36 not the SDG/ref written with 3.1
37 DFSDsetlengths - set lengths of label, unit, format strings on gets
38 DFSDsetdims - set rank and dim sizes
39 DFSDsetdatastrs - set data label, unit, format and coord system
40 DFSDsetdimstrs - set dim labels, units and formats
41 DFSDsetdimscale - set scale for a dimension
42 DFSDsetrange - set max and min of data
43 DFSDsetorder - set array order to C or FORTRAN order
44 DFSDsetNT - set number type to be written out
45 DFSDputdata - output data, data info, and display info
46 DFSDrestart - forget info about last file accessed - restart from
47 beginning
48 DFSDndatasets - return number of SDGs in file
49 DFSDclear - forget all info set by DFSDset* routines
50 DFSDlastref - get reference number of last SDG read or written
51 DFSDgetslice - get part of the data, specified as a slice
52 DFSDstartslice - set up to write SD
53 DFSDputslice - write specified number of data items to file
54 DFSDendslice - end of series of writes, write out SDG
55 DFSDwriteref - set reference number to be used in next SDS write slab
56 DFSDsetfillvalue - set fill value to be used in next SDS written
57 DFSDgetfillvalue - return fill value from SDS that is about to be read
58 DFSDstartslab - set up to write slabs
59 DFSDwriteslab - write hyperslab of values
60 DFSDendslab - end of series of hyperslab writes
61 DFSDreadslab - get part of the data, specified as a slab
62
63 Lower level functions:
64 DFSDgetsdg - read SDG into struct
65 DFSDputsdg - write SDG to file
66
67 Private functions:
68 DFSDIopen - open or reopen file
69 DFSDIsdginfo - find next sdg in file
70 DFSDIisndg - was currently read sdg written by HDF3.2
71 DFSDIrefresh - get info of next sdg if necessary
72 DFSDIgetrrank - get rank of the currently read sdg
73 DFSDIgetwrank - get rank of the sdg to be written
74 DFSDIclear - clear sdg data structure of all info
75 DFSDIgetdata - read data from file
76 DFSDIputdata - write data to file
77 DFSDIgetslice - get slice
78 DFSDIputslice - put slice
79 DFSDIendslice -
80 DFSDIsetnsdg_t - set up nsdg table
81 DFSDInextnsdg - get next nsdg from nsdg table
82 DFSDIgetndg - read NDG into struct
83 DFSDIputndg - write NDG to file
84
85 Fortran stub functions:
86 dsisdas - set data label, unit, format and coord system
87 dsisdis - set dim labels, units and formats
88
89 Remarks:
90 These functions will be copied into dfsd.c after debugging.
91 This version assumes that all the values are floating point.
92 *---------------------------------------------------------------------------*/
93
94 #include "hdf.h"
95 #include "dfsd.h"
96
97 /* MMM: make this definition correct and move to hfile.h, or wherever. */
98 #define DF_NOFILE 0
99
100 #define LABEL 0
101 #define UNIT 1
102 #define FORMAT 2
103 #define COORDSYS 3
104
105 #define NFGSDG_TYPE_SDG 0 /* a pure SDG */
106 #define NFGSDG_TYPE_NFG 1 /* a pure NDG */
107 #define NFGSDG_TYPE_SDGNDG 2 /* an SDG in NDG */
108
109 /* Init NSDG table header */
110 PRIVATE DFnsdg_t_hdr *nsdghdr = NULL;
111
112 /* initialize aid to -1 and numbertype to DFNT_NONE. S. Xu */
113 PRIVATE DFSsdg Readsdg = /* struct for reading */
114 {
115 {(uint16) 0, (uint16) 0}, (intn) 0, NULL, NULL,
116 {NULL, NULL, NULL},
117 {NULL, NULL, NULL}, NULL,
118 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
119 (int32) DFNT_NONE, DFNTF_NONE, (int32) -1, (int32) 0, (int32) 0,
120 (float64) 1.0, (float64) 0.0, (float64) 0.0, (float64) 0.0,
121 (int32) -1,
122 {0}, 0
123 };
124
125 PRIVATE DFSsdg Writesdg = /* struct for writing */
126 {
127 {(uint16) 0, (uint16) 0}, (intn) 0, NULL, NULL,
128 {NULL, NULL, NULL},
129 {NULL, NULL, NULL}, NULL,
130 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
131 (int32) DFNT_NONE, DFNTF_NONE, (int32) -1, (int32) 0, (int32) 0,
132 (float64) 1.0, (float64) 0.0, (float64) 0.0, (float64) 0.0,
133 (int32) -1,
134 {0}, 0
135 };
136
137 PRIVATE uint16 Writeref = 0; /* ref of next SDG/NDG to write to file */
138 PRIVATE intn Newdata = (-1); /* Values in Readsdg fresh? */
139 /* -1 : no descriptor read */
140 /* 1 : descriptor read */
141 PRIVATE intn Nextsdg = 1; /* Signal if DFSDgetdata should get the */
142 /* next SDG/NDG */
143 PRIVATE int32 Sfile_id = DF_NOFILE; /* pointer to file for slice writes */
144 PRIVATE int32 *Sddims; /*dims written so far in slice write */
145
146 PRIVATE struct
147 { /* Indicators of status (s) of info: */
148 intn dims; /* s = -1: there is no info in this category */
149 intn nt; /* s = 0: info was set, but not yet written */
150 intn coordsys; /* s > 0: info was set and written with ref no.s */
151 intn luf[3];
152 intn scales;
153 intn maxmin;
154 intn transpose; /* It should be taken out!!! !!! */
155 intn cal;
156 intn fill_value;
157 intn new_ndg;
158 }
159 Ref =
160 {
161 -1, -1, -1,
162 {
163 -1, -1, -1
164 }
165 ,-1, -1, -1, -1, -1, -1
166 };
167
168 PRIVATE intn Maxstrlen[4] =
169 {DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN, DFS_MAXLEN};
170 PRIVATE intn Ismaxmin = 0; /* is there a max/min value on read? */
171 PRIVATE intn FileTranspose = 0; /* is the data in column major order? */
172 PRIVATE intn Fortorder = 0; /* should data be written col major? */
173 PRIVATE intn IsCal = 0; /* has calibration info been set? */
174
175 /* In ver. 3.2 numbertype and file number format (subclass) are included */
176 /* in DFSsdg, and fileNTsize is local to functions . */
177 /* static int fileNT=DFNTF_IEEE, default: all IEEE */
178 /* fileNTsize=4, */
179 /* outNT=DFNTF_IEEE, default output: IEEE */
180 /* outNTsize=4, */
181 /* userNT=DFNTF_IEEE ; default */
182
183 PRIVATE uint16 Readref = 0; /* ref of next SDG/NDG to be read? */
184 #if 0
185 PRIVATE char Lastfile[DF_MAXFNLEN] = ""; /* last file opened */
186 #endif
187 PRIVATE char *Lastfile = NULL;
188 PRIVATE uint16 Lastref = 0; /* Last ref to be read/written? */
189 PRIVATE DFdi lastnsdg; /* last read nsdg in nsdg_t */
190
191 /* Whether we've installed the library termination function yet for this interface */
192 PRIVATE intn library_terminate = FALSE;
193
194 /* Private buffer */
195 PRIVATE uint8 *ptbuf = NULL;
196
197 /* Prototypes */
198 static intn DFSDIsetnsdg_t(int32 file_id, DFnsdg_t_hdr * l_nsdghdr);
199 static intn DFSDInextnsdg(DFnsdg_t_hdr * l_nsdghdr, DFdi * nsdg);
200 static intn DFSDIgetndg(int32 file_id, uint16 tag, uint16 ref, DFSsdg * sdg);
201 static intn DFSDIputndg(int32 file_id, uint16 ref, DFSsdg * sdg);
202 static intn DFSDIstart(void);
203
204 /*--------------------------------------------------------------------------
205 NAME
206 DFSDgetdims
207 USAGE
208 int DFSDgetdims(filename, prank, sizes, maxrank)
209 char *filename; IN: Name of file with scientific data set
210 int prank; OUT: Number of dimensions
211 int32 sizes: OUT: array for holding dimensions of data set in file.
212 int maxrank: IN: size of array "dimsizes"
213
214 RETURNS
215 Returns SUCCED(0) if successful and FAIL(-1) otherwise.
216 DESCRIPTION
217 Gets the number of dimensions(rank) and the sizes of the dimensions
218 (dimsizes) for the next data set in the file. The input argument
219 "maxrank" tells the size of the array that is allocated for storing
220 the "dimsizses" array. The value of rank cannot exceed the value of
221 "maxrank". The allocation of space for reading in the scientific
222 data set should correspond to the values read in by "DFSDgetdims".
223 The first value in the array "dimsizes" should equal the first
224 dimension of the array that is allocated to hold the data set; the
225 second value in "dimsizes" should equal the second dimension of the
226 data set, and so forth. "DFSDgetdims" opens and closes the file.
227
228 --------------------------------------------------------------------------*/
229 intn
DFSDgetdims(const char * filename,intn * prank,int32 sizes[],intn maxrank)230 DFSDgetdims(const char *filename, intn *prank, int32 sizes[], intn maxrank)
231 {
232 intn i;
233 int32 file_id;
234 CONSTR(FUNC, "DFSDgetdims");
235 intn ret_value = SUCCEED;
236
237 HEclear(); /* Clear error stack */
238
239 /* Perform global, one-time initialization */
240 if (library_terminate == FALSE)
241 if(DFSDIstart()==FAIL)
242 HGOTO_ERROR(DFE_CANTINIT, FAIL);
243
244 if (!prank) /* check if ptr is valid */
245 HGOTO_ERROR(DFE_BADPTR, FAIL);
246
247 file_id = DFSDIopen(filename, DFACC_READ); /* open/reopen file */
248 if (file_id == FAIL)
249 {
250 ret_value = FAIL;
251 goto done;
252 }
253
254 if (DFSDIsdginfo(file_id) < 0)
255 { /* reads next SDG from file */
256 Hclose(file_id);
257 ret_value = FAIL; /* on error, close file and return */
258 goto done;
259 }
260
261 *prank = Readsdg.rank; /* copy rank, dimensions */
262 if (maxrank < *prank) /* if not all dimensions copied */
263 HGOTO_ERROR(DFE_NOTENOUGH, FAIL);
264
265 for (i = 0; i < *prank; i++) /* copy dimensions */
266 sizes[i] = Readsdg.dimsizes[i];
267 Nextsdg = 0;
268
269 ret_value = Hclose(file_id);
270
271 done:
272 if(ret_value == FAIL)
273 { /* Error condition cleanup */
274
275 } /* end if */
276
277 /* Normal function cleanup */
278 return ret_value;
279 }
280
281 /*---------------------------------------------------------------------------
282 NAME
283 DFSDgetdatastrs
284 USAGE
285 int DFSDgetdatastrs(label, unit, format, coordsys)
286 char *label; OUT: label string that describes the data
287 char *unit; OUT: unit string that describes the unit used
288 char *format; OUT: format string that describes the format for
289 displaying the data
290 char *coordsys; OUT: string describing coordinate system
291 RETURN
292 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
293 DESCRIPTION
294 Retrieves information about the data from its associated attribute
295 strings. Particularly, it reads the label, unit and format strings
296 for the data. The parameter "coordsys" gives the coordinate system
297 that is to be used for interpreting the dimension information.
298
299 ----------------------------------------------------------------------------*/
300 intn
DFSDgetdatastrs(char * label,char * unit,char * format,char * coordsys)301 DFSDgetdatastrs(char *label, char *unit, char *format, char *coordsys)
302 {
303 int32 luf;
304 char *lufp;
305 CONSTR(FUNC, "DFSDgetdatastrs");
306 intn ret_value = SUCCEED;
307
308 HEclear(); /* Clear error stack */
309
310 /* Perform global, one-time initialization */
311 if (library_terminate == FALSE)
312 if(DFSDIstart()==FAIL)
313 HGOTO_ERROR(DFE_CANTINIT, FAIL);
314
315 if (Newdata < 0)
316 HGOTO_ERROR(DFE_BADCALL, FAIL);
317 /* NOTE: Once DFSDsetdatastrs is changed to always write all three (label,
318 unit and format) whenever it is called, this routine should be
319 changed so that it returns all three, if any exist. This means
320 that it also should be changed to return -1 if none exist.
321 (Currently it returns FAIL only if the SDS doesn't exist.)
322 */
323
324 /* copy label, unit, format */
325 for (luf = LABEL; luf <= FORMAT; luf++)
326 {
327 lufp = (luf == LABEL) ? label : (luf == UNIT) ? unit : format;
328 if (lufp)
329 {
330 if (Readsdg.dataluf[luf])
331 HIstrncpy(lufp, Readsdg.dataluf[luf], Maxstrlen[luf]);
332 }
333 } /* end for 'luf' */
334 /* copy coordsys */
335 if (coordsys)
336 {
337 if (Readsdg.coordsys)
338 HIstrncpy(coordsys, Readsdg.coordsys, Maxstrlen[COORDSYS]);
339 else
340 coordsys[0] = '\0';
341 }
342
343 done:
344 if(ret_value == FAIL)
345 { /* Error condition cleanup */
346
347 } /* end if */
348
349 /* Normal function cleanup */
350 return ret_value;
351 }
352
353 /*----------------------------------------------------------------------------
354 NAME
355 DFSDgetdimstrs
356 USAGE
357 int DFSDgetdimstrs(dim, label, unit, format)
358 int dim; OUT: Dimension this label, unit and format refer to
359 char *label; OUT: Label that describes this dimension
360 char *unit; OUT: Unit to be used with this dimension
361 char *format; OUT: Format to be used in displaying scale for this
362 dimension
363 RETURNS
364 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
365 DESCRIPTION
366 Gets the labe, unit and format strings corresponding to the specified
367 dimension. The space allocated for the label, unit and format string
368 must be at least 1 byte larger than the length of the string. If the
369 length is unknown when the program is written, declare the array size
370 as 1+maxlen_label, _unit or _format after they are set by "DFSDsetlengths".
371 The maximum default string length is 255.
372 ----------------------------------------------------------------------------*/
373 intn
DFSDgetdimstrs(int dim,char * label,char * unit,char * format)374 DFSDgetdimstrs(int dim, char *label, char *unit, char *format)
375 {
376 intn luf;
377 intn rdim;
378 char *lufp;
379 CONSTR(FUNC, "DFSDgetdimstrs");
380 intn ret_value = SUCCEED;
381
382 HEclear(); /* Clear error stack */
383
384 /* Perform global, one-time initialization */
385 if (library_terminate == FALSE)
386 if(DFSDIstart()==FAIL)
387 HGOTO_ERROR(DFE_CANTINIT, FAIL);
388
389 if (Newdata < 0)
390 HGOTO_ERROR(DFE_BADCALL, FAIL);
391 /* NOTE: Once DFSDsetdimstrs is changed to always write all three (label,
392 unit and format) whenever it is called, this routine should be
393 changed so that it returns all three, if any exist. This means
394 that it also should be changed to return -1 if none exist.
395 (Currently it returns FAIL only if the SDS doesn't exist.)
396 */
397
398 rdim = dim - 1; /* translate dim to zero origin */
399 if ((rdim >= Readsdg.rank) || (rdim < 0))
400 HGOTO_ERROR(DFE_BADDIM, FAIL);
401
402 /* copy labels etc */
403 for (luf = LABEL; luf <= FORMAT; luf++)
404 {
405 lufp = (luf == LABEL) ? label : (luf == UNIT) ? unit : format;
406 if (lufp)
407 {
408 if (!Readsdg.dimluf)
409 { /* no labels etc */
410 *lufp = '\0';
411 continue;
412 }
413 if (Readsdg.dimluf[luf])
414 HIstrncpy(lufp, Readsdg.dimluf[luf][rdim], Maxstrlen[luf]);
415 } /* end if 'lufp' */
416 } /* end for 'luf' */
417
418 done:
419 if(ret_value == FAIL)
420 { /* Error condition cleanup */
421
422 } /* end if */
423
424 /* Normal function cleanup */
425 return ret_value;
426 }
427
428 /*---------------------------------------------------------------------------
429 NAME
430 DFSDgetdatalen
431 USAGE
432 int DFSDgetdatalen(llabel, lunit, lformat, lcoordsys)
433 int *llabel; OUT: length of label string
434 int *lunit; OUT: length of unit string
435 int *lformat; OUT: length of format string
436 int *lcoordsys; OUT: length of coordsys string
437
438 RETURN
439 Returns SUCCED(0) if succesful and FAIL(-1) otherwise
440 DESCRIPTION
441 Gets actual length of label, unit, format and coordinate system
442 strings. The space allocated for the label, unit, format and
443 coordinate system strings must be at least 1 byte larger than the
444 actual length of the string.
445
446 ----------------------------------------------------------------------------*/
447 intn
DFSDgetdatalen(intn * llabel,intn * lunit,intn * lformat,intn * lcoordsys)448 DFSDgetdatalen(intn *llabel, intn *lunit, intn *lformat, intn *lcoordsys)
449 {
450 CONSTR(FUNC, "DFSDgetdatalen");
451 intn ret_value = SUCCEED;
452
453 HEclear(); /* Clear error stack */
454
455 /* Perform global, one-time initialization */
456 if (library_terminate == FALSE)
457 if(DFSDIstart()==FAIL)
458 HGOTO_ERROR(DFE_CANTINIT, FAIL);
459
460 if (Newdata < 0)
461 HGOTO_ERROR(DFE_BADCALL, FAIL);
462
463 *llabel = (intn)(Readsdg.dataluf[LABEL] ? HDstrlen(Readsdg.dataluf[LABEL]) : 0);
464 *lunit = (intn)(Readsdg.dataluf[UNIT] ? HDstrlen(Readsdg.dataluf[UNIT]) : 0);
465 *lformat = (intn)(Readsdg.dataluf[FORMAT] ? HDstrlen(Readsdg.dataluf[FORMAT]) : 0);
466 *lcoordsys = (intn)(Readsdg.coordsys ? HDstrlen(Readsdg.coordsys) : 0);
467
468 done:
469 if(ret_value == FAIL)
470 { /* Error condition cleanup */
471
472 } /* end if */
473
474 /* Normal function cleanup */
475 return ret_value;
476 }
477
478 /*---------------------------------------------------------------------------
479 NAME
480 DFSDgetdimlen
481 USAGE
482 int DFSDgetdimlen(dim, llabel, lunit, lformat)
483 int dim; OUT: number of dimensions to get info about
484 int *llabel; OUT: length of label string
485 int *lunit; OUT: length of unit string
486 int *lformat; OUT: length of format string
487 RETURN
488 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
489 DESCRIPTION
490 Get the length of label, unit, and format for the specified
491 dimension. The space allocated to hold the label, unit, and format
492 strings must be at least 1 byte larger than the actual length of the
493 string.
494 ----------------------------------------------------------------------------*/
495 intn
DFSDgetdimlen(intn dim,intn * llabel,intn * lunit,intn * lformat)496 DFSDgetdimlen(intn dim, intn *llabel, intn *lunit, intn *lformat)
497 {
498 CONSTR(FUNC, "DFSDgetdimlen");
499 intn ret_value = SUCCEED;
500
501 HEclear(); /* Clear error stack */
502
503 /* Perform global, one-time initialization */
504 if (library_terminate == FALSE)
505 if(DFSDIstart()==FAIL)
506 HGOTO_ERROR(DFE_CANTINIT, FAIL);
507
508 if (Newdata < 0)
509 HGOTO_ERROR(DFE_BADCALL, FAIL);
510
511 if (dim > Readsdg.rank)
512 HGOTO_ERROR(DFE_BADDIM, FAIL);
513
514 *llabel = (intn)(Readsdg.dimluf[LABEL][dim - 1] ? HDstrlen(Readsdg.dimluf[LABEL][dim - 1]) : 0);
515 *lunit = (intn)(Readsdg.dimluf[UNIT][dim - 1] ? HDstrlen(Readsdg.dimluf[UNIT][dim - 1]) : 0);
516 *lformat = (intn)(Readsdg.dimluf[FORMAT][dim - 1] ? HDstrlen(Readsdg.dimluf[FORMAT][dim - 1]) : 0);
517
518 done:
519 if(ret_value == FAIL)
520 { /* Error condition cleanup */
521
522 } /* end if */
523
524 /* Normal function cleanup */
525 return ret_value;
526 }
527
528 /*----------------------------------------------------------------------------
529 NAME
530 DFSDgetdimscale
531 USAGE
532 int DFSDgetdimscale(dim, maxsize, scale)
533 int dim; IN: Dimension this scale corresponds to
534 int32 size; IN: size of scale
535 VOIDP scale; OUT: the scale
536 RETURN
537 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
538 DESCRIPTION
539 Gets the scale corresponding to the specified demension. The DFSD
540 interface in HDFv3.3 requires that the dimension scales are of the
541 same number type as the corresponding data. To store dimension scales
542 of a different number type than the corresponding data see the
543 multi-file SD interface.
544 ---------------------------------------------------------------------------*/
545 intn
DFSDgetdimscale(intn dim,int32 maxsize,VOIDP scale)546 DFSDgetdimscale(intn dim, int32 maxsize, VOIDP scale)
547 {
548 uint32 dimsize;
549 int32 numtype;
550 int32 localNTsize;
551 intn rdim;
552 uint8 *p1, *p2;
553 CONSTR(FUNC, "DFSDgetdimscale");
554 intn ret_value = SUCCEED;
555
556 HEclear(); /* Clear error stack */
557
558 /* Perform global, one-time initialization */
559 if (library_terminate == FALSE)
560 if(DFSDIstart()==FAIL)
561 HGOTO_ERROR(DFE_CANTINIT, FAIL);
562
563 if (Newdata < 0)
564 HGOTO_ERROR(DFE_BADCALL, FAIL);
565
566 rdim = dim - 1; /* translate dim to zero origin */
567 if ((rdim >= Readsdg.rank) || (rdim < 0))
568 HGOTO_ERROR(DFE_BADDIM, FAIL);
569
570 if (maxsize < Readsdg.dimsizes[rdim])
571 HGOTO_ERROR(DFE_NOSPACE, FAIL);
572
573 if (!scale)
574 HGOTO_ERROR(DFE_BADPTR, FAIL);
575
576 if (!Readsdg.dimscales || !Readsdg.dimscales[rdim]) /* no scale */
577 HGOTO_ERROR(DFE_NOVALS, FAIL);
578
579 /* get number type and copy data from Readsdg to scale */
580 if (Readsdg.numbertype == DFNT_NONE)
581 Readsdg.numbertype = DFNT_FLOAT32;
582
583 numtype = Readsdg.numbertype;
584 localNTsize = DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
585 dimsize = (uint32)localNTsize * (uint32)Readsdg.dimsizes[rdim]; /* in bytes */
586
587 p1 = (uint8 *) scale;
588 p2 = (uint8 *) (Readsdg.dimscales[rdim]);
589 HDmemcpy(p1, p2, dimsize);
590
591 done:
592 if(ret_value == FAIL)
593 { /* Error condition cleanup */
594
595 } /* end if */
596
597 /* Normal function cleanup */
598 return ret_value;
599 }
600
601 /*---------------------------------------------------------------------------
602 NAME
603 DFSDgetrange
604 USAGE
605 int DFSDgetrange(max, min)
606 VOIDP max; OUT: High value stored with the scientific data set
607 VOIDP min; OUT: Low value stored with the scientific data set
608 RETURNS
609 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
610 DESCRIPTION
611 Gets the maximum and minimum values stored with the scientific data
612 set. The "max" and "min" values are set by "DFSDsetrange". They are
613 not automatically stored when a data set is written to a file.
614 Since these values are supposed to relate to the data itself, it is
615 assumed that they are of the same number type as the data itself.
616 One implication of this is that in the C version of "DFSDgetrange"
617 the arguments are pointers, rather than simple variables, whereas in
618 the FORTRAN version they are simple variables of the same type as the
619 data array. Neither "DFSDgetrange" or "DFSDgetdata" compare the "max"
620 and "min" values stored with the data set to the actual values in
621 the data set; they merely retrieve the data. As a result, the
622 maximum and minimum values may not always reflect the actual maximum
623 and minimum vlaues in the data set. In some cases the "max" and "min"
624 values may actually lie outside the range of values in the data set.
625 ---------------------------------------------------------------------------*/
626 int
DFSDgetrange(VOIDP pmax,VOIDP pmin)627 DFSDgetrange(VOIDP pmax, VOIDP pmin)
628 {
629 int32 numtype;
630 uint32 localNTsize;
631 uint8 *p1, *p2;
632 CONSTR(FUNC, "DFSDgetrange");
633 int ret_value = SUCCEED;
634
635 HEclear(); /* Clear error stack */
636
637 /* Perform global, one-time initialization */
638 if (library_terminate == FALSE)
639 if(DFSDIstart()==FAIL)
640 HGOTO_ERROR(DFE_CANTINIT, FAIL);
641
642 if (Newdata < 0)
643 HGOTO_ERROR(DFE_BADCALL, FAIL);
644
645 /* get number type and copy data */
646 if (Readsdg.numbertype == DFNT_NONE)
647 Readsdg.numbertype = DFNT_FLOAT32;
648 numtype = Readsdg.numbertype;
649 localNTsize = (uint32)DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
650
651 if (Ismaxmin) /* Ismaxmin is a global */
652 {
653 p1 = (uint8 *) pmax;
654 p2 = (uint8 *) &(Readsdg.max_min[0]);
655 HDmemcpy(p1, p2, localNTsize);
656 p1 = (uint8 *) pmin;
657 p2 = &(Readsdg.max_min[localNTsize]);
658 HDmemcpy(p1, p2, localNTsize);
659 ret_value = SUCCEED;
660 goto done;
661 }
662 else
663 HGOTO_ERROR(DFE_NOVALS, FAIL);
664
665 done:
666 if(ret_value == FAIL)
667 { /* Error condition cleanup */
668
669 } /* end if */
670
671 /* Normal function cleanup */
672 return ret_value;
673 }
674
675 /*---------------------------------------------------------------------------
676 NAME
677 DFSDgetdata
678 USAGE
679 intn DFSDgetdata(filename, rank, maxsizes, data)
680 char filename; IN: name of HDF file containing scientific data set
681 intn rank; IN: number of dimensions of array "data"
682 int32 maxsizes; IN: Array that holds dimensions of buffer that will
683 hold the data
684 VOIDP data; OUT: Array for holding the data
685
686 RETURN
687 Returns SUCCEED(0) if succesful and FAIL(-1) otherwise.
688 DESCRIPTION
689 Reads the next data set in the file. If you do no know the values of
690 "rank" or "dimsizes", you must call "DFSDgetdims" to get them and
691 then use them to provide the right amount of space for the array
692 "data". If you do not know the number type of the data in the
693 scientific dat set, you can call "DFSDgetNT" to find out.
694 Subsequent calls to "DFSDgetdata"(or to "DFSDgetdims" and "DFSDgetdata")
695 will sequentially read scientific data sets from the file. For example,
696 if "DFSDgetdata" is called three times in succession, the third call
697 reads data from the third scientific data set in the file. Note that
698 if you do no know the values of "rank" or "dimsizes" you must call
699 "DFSDgetdims" to get them each time and then provide the necessary
700 space to hold the data. If "DFSDgetdims" or "DFSDgetdata" is called
701 and there are no more scientific data sets left in the file, an
702 error code is returned and nothing is read. "DFSDrestart" can be
703 used to override this convention.
704
705 ---------------------------------------------------------------------------*/
706 intn
DFSDgetdata(const char * filename,intn rank,int32 maxsizes[],VOIDP data)707 DFSDgetdata(const char *filename, intn rank, int32 maxsizes[], VOIDP data)
708 {
709 intn ret_value;
710
711 ret_value = (DFSDIgetdata(filename, rank, maxsizes, data, 0)); /* 0 == C */
712
713 return ret_value;
714 }
715
716 /*-----------------------------------------------------------------------------
717 NAME
718 DFSDsetlengths
719 USAGE
720 int DFSDsetlengths(maxlen_label, maxlen_unit, maxlen_format, maxlen_coordsys)
721 int maxlen_label; IN: maximum length of any label
722 int maxlen_unit; IN: maximum length of any unit
723 int maxlen_format; IN: maximum length of any format
724 int maxlen_coordsys; IN: maximum length of any coordsys
725 RETURNS
726 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
727 DESCRIPTION
728 Sets the maximum lengths for the strings that will hold labels, units
729 formats and the name of the coordinate system. These lengths are used
730 by the routines "DFSDgetdimstrs" and "DFSDgetdatastrs" to determine
731 the maximum lengths of strings that they get from the HDF file.
732 Normally, "DFSDsetlengths" is not needed. If it is not called,
733 default maximum lengths of 255 are used for all strings.
734 -----------------------------------------------------------------------------*/
735 intn
DFSDsetlengths(intn maxlen_label,intn maxlen_unit,intn maxlen_format,intn maxlen_coordsys)736 DFSDsetlengths(intn maxlen_label, intn maxlen_unit, intn maxlen_format,
737 intn maxlen_coordsys)
738 {
739 CONSTR(FUNC, "DFSDsetlengths");
740 intn ret_value = SUCCEED;
741
742 /* Perform global, one-time initialization */
743 if (library_terminate == FALSE)
744 if(DFSDIstart()==FAIL)
745 HGOTO_ERROR(DFE_CANTINIT, FAIL);
746
747 if (maxlen_label > 0)
748 Maxstrlen[LABEL] = maxlen_label;
749 if (maxlen_unit > 0)
750 Maxstrlen[UNIT] = maxlen_unit;
751 if (maxlen_format > 0)
752 Maxstrlen[FORMAT] = maxlen_format;
753 if (maxlen_coordsys > 0)
754 Maxstrlen[COORDSYS] = maxlen_coordsys;
755
756 done:
757 if(ret_value == FAIL)
758 { /* Error condition cleanup */
759
760 } /* end if */
761
762 /* Normal function cleanup */
763 return ret_value;
764 }
765
766 /*-----------------------------------------------------------------------------
767 NAME
768 DFSDsetdims
769 USAGE
770 int DFSDsetdims(rank, dimsizes)
771 int rank; IN: number of dimensions
772 int32 dimsizes[]; IN: array containing dimensions of scientific data sett
773 RETURNS
774 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
775 DESCRIPTION
776 Sets the rank and dimension sizes for all subsequent scientific data
777 sets written to the file. This routine must be called before calling
778 either "DFSDgetdimstrs" or "DFSDsetdimscale". "DFSDsetdims" need not
779 be called if other set routines are not called and the correct
780 dimensions are supplied in "DFSDputdata" or "DFSDadddata". If the
781 rank or dimension sizes change, all previous set calls are cleared,
782 except for the number type which is set by calling "DFSDsetNT".
783 -----------------------------------------------------------------------------*/
784 intn
DFSDsetdims(intn rank,int32 dimsizes[])785 DFSDsetdims(intn rank, int32 dimsizes[])
786 {
787 intn i;
788 CONSTR(FUNC, "DFSDsetdims");
789 intn ret_value = SUCCEED;
790
791 HEclear();
792
793 /* Perform global, one-time initialization */
794 if (library_terminate == FALSE)
795 if(DFSDIstart()==FAIL)
796 HGOTO_ERROR(DFE_CANTINIT, FAIL);
797
798 if (Sfile_id != DF_NOFILE)
799 HGOTO_ERROR(DFE_BADCALL, FAIL);
800
801 if (Writesdg.rank == rank) /* check if dimensions same */
802 {
803 if (Writesdg.dimsizes)
804 {
805 for (i = 0; i < rank; i++)
806 {
807 if (Writesdg.dimsizes[i] != dimsizes[i])
808 break;
809 }
810 if (i == rank)
811 {
812 ret_value= SUCCEED; /* Dimensions same as before */
813 goto done;
814 }
815 }
816 }
817
818 /* forget all attributes set previously */
819 if (DFSDIclear((DFSsdg *) & Writesdg) < 0)
820 {
821 ret_value = FAIL;
822 goto done;
823 }
824
825 /* allocate dimensions */
826 Writesdg.dimsizes = (int32 *) HDmalloc((size_t)rank * sizeof(int32));
827 if (Writesdg.dimsizes == NULL)
828 {
829 ret_value = FAIL;
830 goto done;
831 }
832
833 /* copy dimensions */
834 Writesdg.rank = rank;
835 for (i = 0; i < rank; i++)
836 Writesdg.dimsizes[i] = dimsizes[i];
837
838 /* Note dimensions modified */
839 Ref.dims = 0;
840
841 /*
842 * Added side effect, allows creation of new "ref" whenever called
843 * before DFSDwriteslab().
844 */
845 Ref.new_ndg = 0;
846 Writeref = 0;
847
848 done:
849 if(ret_value == FAIL)
850 { /* Error condition cleanup */
851
852 } /* end if */
853
854 /* Normal function cleanup */
855 return ret_value;
856 }
857
858 /*-----------------------------------------------------------------------------
859 NAME
860 DFSDsetdatastrs
861 USAGE
862 int DFSDsetdatastrs(label, unit, format, coordsys)
863 char *label; IN: label that describes the data
864 char *unit; IN: unit to be used with the data
865 char *format; IN: format to be used in displaying the data
866 char *coordsys; IN: coordinate system
867 RETURNS
868 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
869 DESCRIPTION
870 Sets the label, unit, format and coordsys(coordinate system) strings
871 to be assigned to the next data set written to the file.
872 -----------------------------------------------------------------------------*/
873 intn
DFSDsetdatastrs(const char * label,const char * unit,const char * format,const char * coordsys)874 DFSDsetdatastrs(const char *label, const char *unit, const char *format, const char *coordsys)
875 {
876 intn ret_value;
877
878 ret_value = (DFSDIsetdatastrs(label, unit, format, coordsys));
879
880 return ret_value;
881 }
882
883 /*-----------------------------------------------------------------------------
884 * Name: DFSDIsetdatastrs()
885 * Purpose: Set label, unit and format for displaying subsequent SDGs
886 * Inputs: label: label to be used to describe data
887 * unit: unit corresponding to data values
888 * format: format to be used in displaying data values
889 * coordsys: type of coordinate system
890 * Globals: Writesdg, Ref
891 * Returns: 0 on success, FAIL on failure with error set
892 * Users: HDF users, utilities, other routines
893 * Invokes: none
894 * Method: Stores values in global structure Writesdg
895 * Remarks: should we validate coordsys? proposed strings: "cartesian",
896 * "polar" (="spherical") and "cylindrical". Do "spherical" and
897 * "cylindrical" make sense for 2D?
898 *---------------------------------------------------------------------------*/
899 intn
DFSDIsetdatastrs(const char * label,const char * unit,const char * format,const char * coordsys)900 DFSDIsetdatastrs(const char *label, const char *unit, const char *format, const char *coordsys)
901 {
902 intn luf; /* takes values LABEL, UNIT, FORMAT */
903 /* in succession */
904 const char *lufp; /* points to label, unit, format */
905 /* in succession */
906 CONSTR(FUNC, "DFSDIsetdatastrs"); /* for HERROR */
907 intn ret_value = SUCCEED;
908
909 /* Perform global, one-time initialization */
910 if (library_terminate == FALSE)
911 if(DFSDIstart()==FAIL)
912 HGOTO_ERROR(DFE_CANTINIT, FAIL);
913
914 /* NOTE: The following code should be changed to write all three, even if
915 one or more is an empty string. Then, when DFSDgetdatastrs is called
916 values will be returned for all three also, even though some might
917 be empty strings.
918 */
919 for (luf = LABEL; luf <= FORMAT; luf++)
920 {
921 /* set lufp to point to label etc. as apppropriate */
922 lufp = (luf == LABEL) ? label : (luf == UNIT) ? unit : format;
923
924 /* free space if allocated */
925 HDfreenclear(Writesdg.dataluf[luf]);
926
927 /* copy string */
928 if (lufp)
929 {
930 Writesdg.dataluf[luf] = (char *) HDstrdup(lufp);
931 if (Writesdg.dataluf[luf] == NULL)
932 {
933 ret_value= FAIL;
934 goto done;
935 }
936 }
937 }
938
939 HDfreenclear(Writesdg.coordsys);
940
941 if (coordsys)
942 {
943 Writesdg.coordsys = (char *) HDstrdup(coordsys);
944 if (Writesdg.coordsys == NULL)
945 {
946 ret_value = FAIL;
947 goto done;
948 }
949 }
950
951 /* indicate that label, unit, format and coordsys info modified */
952 Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = Ref.coordsys = 0;
953
954 done:
955 if(ret_value == FAIL)
956 { /* Error condition cleanup */
957
958 } /* end if */
959
960 /* Normal function cleanup */
961
962 return ret_value;
963 }
964
965 /*-----------------------------------------------------------------------------
966 NAME
967 DFSDsetdimstrs()
968 USAGE
969 int DFSDsetdimstrs(dim, label, unit, format)
970 int dim; IN: dimension this label, unit and format refer to
971 char *label; IN: label that describes this dimension
972 char *unit; IN: unit to be used with this dimension
973 char *format; IN: format to be used to display scale
974 RETURNS
975 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
976 DESCRIPTION
977 Sets the label, unit, and format strings corresponding to the specified
978 dimension. In both FORTRAN and C programs, dim=1 for the first
979 dimension, and dim=2 for the second and so on. If the user is not
980 interested in one or more strings, empty strings can be used as
981 parameters for the "DFSDsetdimstrs" call. For example,
982 "DFSDsetdimstrs(1, "vertical", "", "") " will set the label for the
983 first dimension to "vertical" and set the unit and format strings to
984 empty strings.
985 -----------------------------------------------------------------------------*/
986 intn
DFSDsetdimstrs(intn dim,const char * label,const char * unit,const char * format)987 DFSDsetdimstrs(intn dim, const char *label, const char *unit, const char *format)
988 {
989 intn ret_value;
990
991 ret_value = (DFSDIsetdimstrs(dim, label, unit, format));
992
993 return ret_value;
994 } /* DFSDsetdimstrs */
995
996 /*-----------------------------------------------------------------------------
997 * Name: DFSDIsetdimstrs()
998 * Purpose: For the given dimension, set label, unit, format
999 * This routine needs to be called once for each dimension whose
1000 * values the user wants to set.
1001 * Inputs: dim: the dimension that this info applies to
1002 * label: label to be used to describe this dimension
1003 * unit: units for dimension
1004 * format: format to be used in displaying
1005 * Globals: Writesdg, Ref
1006 * Returns: 0 on success, FAIL on failure with error set
1007 * Users: HDF users, utilities, other routines
1008 * Invokes: none
1009 * Method: Stores values in global structure Writesdg
1010 *---------------------------------------------------------------------------*/
1011 intn
DFSDIsetdimstrs(intn dim,const char * label,const char * unit,const char * format)1012 DFSDIsetdimstrs(intn dim, const char *label, const char *unit, const char *format)
1013 {
1014 intn i;
1015 intn rdim;
1016 intn luf; /* takes values LABEL, UNIT, FORMAT */
1017 /* in succession */
1018 const char *lufp; /* points to label, unit, format */
1019 /* in succession */
1020 CONSTR(FUNC, "DFSDsetdimstrs");
1021 intn ret_value = SUCCEED;
1022
1023 HEclear();
1024
1025 /* Perform global, one-time initialization */
1026 if (library_terminate == FALSE)
1027 if(DFSDIstart()==FAIL)
1028 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1029
1030 /* translate from 1 to 0 origin */
1031 rdim = dim - 1;
1032
1033 if ((rdim >= Writesdg.rank) || (rdim < 0))
1034 HGOTO_ERROR(DFE_BADDIM, FAIL);
1035
1036 for (luf = LABEL; luf <= FORMAT; luf++)
1037 {
1038 /* set lufp to point to label etc. as apppropriate */
1039 lufp = (luf == LABEL) ? label : (luf == UNIT) ? unit : format;
1040
1041 /* allocate space if necessary */
1042 if (!Writesdg.dimluf[luf])
1043 {
1044 Writesdg.dimluf[luf] =
1045 (char **) HDmalloc((uint32) Writesdg.rank * sizeof(char *));
1046 if (Writesdg.dimluf[luf] == NULL)
1047 {
1048 ret_value = FAIL;
1049 goto done;
1050 }
1051 for (i = 0; i < Writesdg.rank; i++) /* set allocated pointers to NULL */
1052 Writesdg.dimluf[luf][i] = NULL;
1053 }
1054
1055 /* free string space if allocated */
1056 HDfreenclear(Writesdg.dimluf[luf][rdim]);
1057
1058 /* NOTE: The following code should be changed to write all three, even if
1059 one or more is an empty string. Then, when DFSDgetdimstrs is called
1060 values will be returned for all three also, even though some might
1061 be empty strings.
1062 */
1063 /* copy string */
1064 if (lufp)
1065 {
1066 Writesdg.dimluf[luf][rdim] = (char *) HDstrdup(lufp);
1067 if (Writesdg.dimluf[luf][rdim] == NULL)
1068 {
1069 ret_value = FAIL;
1070 goto done;
1071 }
1072 }
1073 }
1074 /* Indicate that this info has not been written to file */
1075 Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = 0;
1076
1077 done:
1078 if(ret_value == FAIL)
1079 { /* Error condition cleanup */
1080
1081 } /* end if */
1082
1083 /* Normal function cleanup */
1084
1085 return ret_value;
1086 }
1087
1088 /*-----------------------------------------------------------------------------
1089 NAME
1090 DFSDsetdimscale
1091 USAGE
1092 int DFSDsetdimscale(dim, dimsize, scale)
1093 int dim; IN: dimension the is scale corresponds to
1094 int32 dimsize; IN: size of scale in the dimension
1095 VOID *scale; IN: the scale
1096 RETURNS
1097 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1098 DESCRIPTION
1099 Sets the scale for a dimension. A scale is a 1D array whose value
1100 describes reference points along one of the dimensions of the
1101 scientific data set. For example, a 2D scientific data set representing
1102 points on a mpa could have two scales, one representing points of
1103 latitude, and the other points of longitude.
1104 -----------------------------------------------------------------------------*/
1105 intn
DFSDsetdimscale(intn dim,int32 dimsize,VOIDP scale)1106 DFSDsetdimscale(intn dim, int32 dimsize, VOIDP scale)
1107 {
1108 int32 i;
1109 intn rdim;
1110 int32 numtype;
1111 uint32 bytesize;
1112 int32 localNTsize;
1113 uint8 *p1, *p2;
1114 intn ret_value = SUCCEED;
1115 CONSTR(FUNC, "DFSDsetdimscale");
1116
1117 HEclear();
1118
1119 /* Perform global, one-time initialization */
1120 if (library_terminate == FALSE)
1121 if(DFSDIstart()==FAIL)
1122 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1123
1124 rdim = dim - 1; /* translate from 1 to 0 origin */
1125
1126 if (!Writesdg.dimsizes)
1127 HGOTO_ERROR(DFE_BADCALL, FAIL);
1128
1129 if (Writesdg.numbertype == DFNT_NONE)
1130 {
1131 if (DFSDsetNT(DFNT_FLOAT32) < 0)
1132 {
1133 ret_value = FAIL;
1134 goto done;
1135 }
1136 }
1137 numtype = Writesdg.numbertype;
1138 localNTsize = DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
1139
1140 if ((rdim >= Writesdg.rank) || (rdim < 0) /* check dimensions */
1141 || (dimsize != Writesdg.dimsizes[rdim]))
1142 {
1143 HGOTO_ERROR(DFE_BADDIM, FAIL);
1144 }
1145
1146 if (!scale)
1147 { /* No scale for this dimension */
1148 if (Writesdg.dimscales)
1149 HDfreenclear(Writesdg.dimscales[rdim]);
1150 Ref.scales = 0;
1151 ret_value = SUCCEED;
1152 goto done;
1153 }
1154
1155 /* get number type and size of this type in this machine */
1156 if (Writesdg.numbertype == DFNT_NONE)
1157 {
1158 if (DFSDsetNT(DFNT_FLOAT32) < 0)
1159 {
1160 ret_value = FAIL;
1161 goto done;
1162 }
1163 }
1164 numtype = Writesdg.numbertype;
1165 localNTsize = DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
1166 bytesize = (uint32)(dimsize * localNTsize);
1167
1168 /* allocate space for dimscales if necessary */
1169 if (!Writesdg.dimscales)
1170 {
1171 Writesdg.dimscales =
1172 (uint8 **) HDmalloc((uint32) Writesdg.rank * sizeof(int8 *));
1173 if (Writesdg.dimscales == NULL)
1174 {
1175 ret_value = FAIL;
1176 goto done;
1177 }
1178 for (i = 0; i < Writesdg.rank; i++) /* set allocated pointers to NULL */
1179 Writesdg.dimscales[i] = NULL;
1180 }
1181
1182 if (!Writesdg.dimscales[rdim])
1183 {
1184 /* allocate dimension scale space if necessary */
1185 Writesdg.dimscales[rdim] =
1186 (uint8 *) HDmalloc((uint32) bytesize);
1187 if (Writesdg.dimscales[rdim] == NULL)
1188 {
1189 ret_value = FAIL;
1190 goto done;
1191 }
1192 }
1193
1194 /* copy scale */
1195 p1 = (uint8 *) scale;
1196 p2 = (uint8 *) Writesdg.dimscales[rdim];
1197 HDmemcpy(p2, p1, bytesize);
1198
1199 /* Indicate scales modified */
1200 Ref.scales = 0;
1201
1202 done:
1203 if(ret_value == FAIL)
1204 { /* Error condition cleanup */
1205
1206 } /* end if */
1207
1208 /* Normal function cleanup */
1209 return ret_value;
1210 }
1211
1212 /*-----------------------------------------------------------------------------
1213 NAME
1214 DFSDsetrange
1215 USAGE
1216 int DFSDsetrange(max, min)
1217 VOIDP max; IN: High value in the scientific data set
1218 VOIDP min; IN: Low value in the scientific data set
1219 RETURNS
1220 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1221 DESCRIPTION
1222 Sets the maximum and minimum values to be stored with the scientific
1223 data set. Since these values are supposed to relate to the data itself,
1224 it is assumed that they are of the same number type as the data itself.
1225 One implication of this is that in the C version of "DFSDgetrange"
1226 the arguments are pointers, rather than simple variables, whereas in
1227 the FORTRAN version they are simple variables of the same type as the
1228 data array. This routine does not compute the maximum and minimum values;
1229 it merely stores the values it is given. As a result, the
1230 maximum and minimum values may not always reflect the actual maximum
1231 and minimum vlaues in the data set. When the maximum and minimum
1232 values are written to a file, the HDF elemement that hold these value
1233 is cleared, because it is assumed that subsequent data sets will have
1234 different values for "max" and "min". These values are automatically
1235 cleared aftera a call to either "DFSDputdata" or "DFSDaddadata".
1236 -----------------------------------------------------------------------------*/
1237 intn
DFSDsetrange(VOIDP maxi,VOIDP mini)1238 DFSDsetrange(VOIDP maxi, VOIDP mini)
1239 {
1240 int32 numtype;
1241 uint32 localNTsize;
1242 intn i;
1243 uint8 *p1, *p2;
1244 intn ret_value = SUCCEED;
1245 CONSTR(FUNC, "DFSDsetrange"); /* for HERROR */
1246
1247 HEclear();
1248
1249 /* Perform global, one-time initialization */
1250 if (library_terminate == FALSE)
1251 if(DFSDIstart()==FAIL)
1252 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1253
1254 p1 = &(Writesdg.max_min[0]);
1255 for (i = 0; i < 16; i++)
1256 *p1++ = 0; /* clear max_min */
1257
1258 /* get number type and copy the values to Writesdg */
1259 if (Writesdg.numbertype == DFNT_NONE)
1260 DFSDsetNT(DFNT_FLOAT32);
1261
1262 numtype = Writesdg.numbertype;
1263 localNTsize = (uint32)DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
1264 p1 = (uint8 *) maxi;
1265 p2 = (uint8 *) mini;
1266
1267 HDmemcpy((uint8 *) &(Writesdg.max_min[0]), p1, localNTsize);
1268 HDmemcpy((uint8 *) &(Writesdg.max_min[localNTsize]), p2, localNTsize);
1269
1270 Ref.maxmin = 0;
1271
1272 done:
1273 if(ret_value == FAIL)
1274 { /* Error condition cleanup */
1275
1276 } /* end if */
1277
1278 /* Normal function cleanup */
1279 return ret_value;
1280 }
1281
1282 /*-----------------------------------------------------------------------------
1283 NAME
1284 DFSDputdata
1285 USAGE
1286 intn DFSDputdata(filename, rank, dimsizes, data)
1287 char *filename; IN: name of file to store scientific data set in
1288 int rank; IN: number of dimensions of data array to be stored
1289 int32 dimsizes[]; IN: array that holds sizes of dimensions
1290 VOID *data; IN: array holding data to be stored
1291 RETURNS
1292 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1293 DESCRIPTION
1294 Writes scientific data and related information to an HDF file.
1295 If a new filename is used, "DFSDputdata" functions exactly like
1296 "DFSDadddata".
1297 WARNING
1298 "DFSDputdata" will write data to an existing file by destroying the
1299 contents of the original file. Use with caution.
1300 -----------------------------------------------------------------------------*/
1301
1302 intn
DFSDputdata(const char * filename,intn rank,int32 dimsizes[],VOIDP data)1303 DFSDputdata(const char *filename, intn rank, int32 dimsizes[], VOIDP data)
1304 {
1305 intn ret_value;
1306
1307 /* 0, 0 specify create mode, C style array (row major) */
1308 ret_value = (DFSDIputdata(filename, rank, dimsizes, data, 0, 0));
1309
1310 return ret_value;
1311 }
1312
1313 /*-----------------------------------------------------------------------------
1314 NAME
1315 DFSDadddata
1316 USAGE
1317 intn DFSDadddata(filename, rank, dimsizes, data)
1318 char *filename; IN: Name of HDF file to store the data set
1319 intn rank; IN: Number of dimensions in the data array to be written
1320 int32 dimsizes[]; IN: Array holding the size of each dimension
1321 VOIDP data; IN: Array holding the data to be stored
1322
1323 RETURNS
1324 SUCCEED(0) if successful and FAIL(-1) otherwise.
1325
1326 DESCRIPTION
1327 In addition to appending any multidemensional array of data to an HDF
1328 file, "DFSDaddata" automatically stores any information pertinent to the
1329 data set. It will not overwrite existing data in the file. The array
1330 "data" can be of any valid type. However if no number type has been set
1331 by "DFSDsetNT", it is assumed that the data type is of type "float32".
1332 The invocation of "DFSDadddata" triggers the writing of the entire
1333 scientific data set. That is, when "DFSDadddat" is called, all
1334 information that has been set by "DFSDset* " calls is written to the
1335 file, along with the data array itself.
1336 -----------------------------------------------------------------------------*/
1337 intn
DFSDadddata(const char * filename,intn rank,int32 dimsizes[],VOIDP data)1338 DFSDadddata(const char *filename, intn rank, int32 dimsizes[], VOIDP data)
1339 {
1340 intn ret_value;
1341
1342 /* 1, 0 specifies append mode, C style array (row major) */
1343 ret_value = (DFSDIputdata(filename, rank, dimsizes, data, 1, 0));
1344
1345 return ret_value;
1346 }
1347
1348 /*-----------------------------------------------------------------------------
1349 NAME
1350 DFSDrestart
1351 USAGE
1352 int DFSDrestart()
1353 RETURNS
1354 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1355 DESCRIPTION
1356 Forces the next read operation to read the first scientific data set
1357 in the file.
1358 -----------------------------------------------------------------------------*/
1359 intn
DFSDrestart(void)1360 DFSDrestart(void)
1361 {
1362 intn ret_value = SUCCEED;
1363 CONSTR(FUNC, "DFSDndatasets");
1364
1365 /* Perform global, one-time initialization */
1366 if (library_terminate == FALSE)
1367 if(DFSDIstart()==FAIL)
1368 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1369
1370 if (Lastfile != NULL)
1371 *Lastfile = '\0'; /* set to 0-length string instead of NULLing ptr */
1372 Readref = 0;
1373
1374 done:
1375 if(ret_value == FAIL)
1376 { /* Error condition cleanup */
1377
1378 } /* end if */
1379
1380 /* Normal function cleanup */
1381 return ret_value;
1382 }
1383
1384 /*-----------------------------------------------------------------------------
1385 NAME
1386 DFSDndatasets
1387 USAGE
1388 int32 DFSDndatasets(filename)
1389 char *filename; IN: filename of HDF file
1390 RETURNS
1391 Returns the number of data sets if successful and FAIL(-1) otherwise.
1392 DESCRIPTION
1393 Returns the number of scientific datasets in the file. In HDFv3.3
1394 "DFSDndatasets" replaces "DFSDnumber". In order to maintain backward
1395 compatibility with existing HDF applications, HDF will continue to
1396 support "DFSDnumber". However, it is recommended that all new applications
1397 use "DFSDndatasets" instead of "DFSDnumber".
1398 -----------------------------------------------------------------------------*/
1399 int32
DFSDndatasets(char * filename)1400 DFSDndatasets(char *filename)
1401 {
1402 int32 file_id;
1403 int32 nsdgs = 0;
1404 int32 ret_value = SUCCEED;
1405 CONSTR(FUNC, "DFSDndatasets");
1406
1407 HEclear();
1408
1409 /* Perform global, one-time initialization */
1410 if (library_terminate == FALSE)
1411 if(DFSDIstart()==FAIL)
1412 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1413
1414 /* should use reopen if same file as last time - more efficient */
1415 file_id = DFSDIopen(filename, DFACC_READ);
1416 if (file_id == FAIL)
1417 HGOTO_ERROR(DFE_BADOPEN, FAIL);
1418
1419 nsdgs = (int32)nsdghdr->size;
1420 if (Hclose(file_id) == FAIL)
1421 HGOTO_ERROR(DFE_CANTCLOSE,FAIL);
1422
1423 ret_value = nsdgs;
1424
1425 done:
1426 if(ret_value == FAIL)
1427 { /* Error condition cleanup */
1428
1429 } /* end if */
1430
1431 /* Normal function cleanup */
1432 return ret_value;
1433 }
1434
1435 /*-----------------------------------------------------------------------------
1436 NAME
1437 DFSDclear
1438 USAGE
1439 int DFSDclear()
1440 RETURNS
1441 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1442 DESCRIPTION
1443 Clears all possible set values. After a call to "DFSDclear", all
1444 values set by an "DFSDset*" calls will not be written unless they
1445 are set again.
1446 ----------------------------------------------------------------------------*/
1447 intn
DFSDclear(void)1448 DFSDclear(void)
1449 {
1450 CONSTR(FUNC, "DFSDclear");
1451 intn ret_value = SUCCEED;
1452
1453 /* Perform global, one-time initialization */
1454 if (library_terminate == FALSE)
1455 if(DFSDIstart()==FAIL)
1456 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1457
1458 lastnsdg.tag = DFTAG_NULL;
1459 lastnsdg.ref = 0;
1460 if (DFSDIclearNT(&Writesdg) < 0)
1461 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1462
1463 ret_value = DFSDIclear(&Writesdg);
1464
1465 done:
1466 if(ret_value == FAIL)
1467 { /* Error condition cleanup */
1468
1469 } /* end if */
1470
1471 /* Normal function cleanup */
1472 return ret_value;
1473 }
1474
1475 /*-----------------------------------------------------------------------------
1476 NAME
1477 DFSDlastref
1478 USAGE
1479 uint16 DFSDlastref()
1480 RETURNS
1481 Returns the reference number of the last accessed scientific data set
1482 if successful and FAIL(-1) otherwise.
1483 DESCRIPTION
1484 Get the most recent reference number used in writing or reading a
1485 scientific data set.
1486 -----------------------------------------------------------------------------*/
1487 uint16
DFSDlastref(void)1488 DFSDlastref(void)
1489 {
1490 CONSTR(FUNC, "DFSDlastref");
1491 uint16 ret_value;
1492
1493 /* Perform global, one-time initialization */
1494 if (library_terminate == FALSE)
1495 if(DFSDIstart()==FAIL)
1496 HGOTO_ERROR(DFE_CANTINIT, 0);
1497
1498 ret_value = (uint16) Lastref;
1499
1500 done:
1501 if(ret_value == 0) /* 0 is invalid ref */
1502 { /* Error condition cleanup */
1503
1504 } /* end if */
1505
1506 /* Normal function cleanup */
1507 return ret_value;
1508 }
1509
1510 /*-----------------------------------------------------------------------------
1511 NAME
1512 DFSDreadref
1513 USAGE
1514 int DFSDreadref(filename, ref)
1515 char *filename; IN: name of HDF file containing scientific data set
1516 uint16 ref; IN: reference number for next "DFSDgetdata" call
1517 RETURNS
1518 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1519 DESCRIPTION
1520 Specifies teh reference number for the data set to be read during
1521 the next read operation. This routine is most likely to be used in
1522 conjunction with "DFANgetlablist" which returns a list of labels for
1523 a given tag together with their reference numbers. It provides a sort
1524 of random access to scientific data sets. There is no guarantee that
1525 reference numbers appear in sequence in an HDF file, so ti is not
1526 generally safe to assume that a reference number is a sequence number
1527 for a scientific data set.
1528 -----------------------------------------------------------------------------*/
1529
1530 intn
DFSDreadref(char * filename,uint16 ref)1531 DFSDreadref(char *filename, uint16 ref)
1532 {
1533 int32 file_id;
1534 int32 aid;
1535 intn ret_value = SUCCEED;
1536 CONSTR(FUNC, "DFSDreadref");
1537
1538 HEclear();
1539
1540 /* Perform global, one-time initialization */
1541 if (library_terminate == FALSE)
1542 if(DFSDIstart()==FAIL)
1543 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1544
1545 file_id = DFSDIopen(filename, DFACC_READ);
1546 if (file_id == DF_NOFILE)
1547 HGOTO_ERROR(DFE_BADOPEN, FAIL);
1548
1549 if ((aid = Hstartread(file_id, DFTAG_SDG, ref)) == FAIL
1550 && (aid = Hstartread(file_id, DFTAG_NDG, ref)) == FAIL)
1551 HCLOSE_GOTO_ERROR(file_id, DFE_NOMATCH, FAIL);
1552
1553 Hendaccess(aid);
1554 Readref = ref;
1555 Newdata = -1;
1556
1557 ret_value = Hclose(file_id);
1558
1559 done:
1560 if(ret_value == FAIL)
1561 { /* Error condition cleanup */
1562
1563 } /* end if */
1564
1565 /* Normal function cleanup */
1566 return ret_value;
1567 }
1568
1569 /*-----------------------------------------------------------------------------
1570 NAME
1571 DFSDgetslice
1572 USAGE
1573 intn DFSDgetslice(filename, winst, windims, data, dims)
1574 char *filename; IN: name of HDF file
1575 int32 winst[]; IN: array containing the coordinates for the start
1576 of the slice
1577 int32 windims[]; IN: array containing the dimensions of the slice
1578 VOID *data; OUT: array for returning the slice
1579 int32 dims[]; OUT: dimensions of array data
1580 RETURNS
1581 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1582 DESCRIPTION
1583 Gets a part of a scientific data set from a file. "DFSDgetslice"
1584 accesses the data set last accessed by "DFSDgetdims". If "DFSDgetdims"
1585 has not been called for the named file, "DFSDgetslice" gets a slice
1586 from the next data set in the file. The array "winst" specifies the
1587 coordinates for the beginning of the slice. Array "windims" gives the
1588 size of the slice. The number of elements in both "winst" and "windims"
1589 must be equal to the rank of the data set. For example, if the file
1590 contains a 3D data set, "winst" may contain the values {2,4,3}, while
1591 "windims" contains the values {3,1,4} and the dims shuld be at least
1592 {3,1,4}, the same size as the slice. This will extract a 3x4,
1593 two-dimensional slice, containing the elements between(2,4.3) and
1594 (4,4,6) from the original data set. The array "data" is the array
1595 into which the slice is read. It must be at least as big as the desired
1596 slice. The array "dims" is the array containing the actual dimensions
1597 of the array "data". The user assigns values to "dims" before calling
1598 "DFSDgetslice". All parameters assume FORTRAN-style 1-based arrays.
1599 "DFSDgetslice" is obsoleted by "DFSDreadslab". "DFSDreadslab" is the
1600 recommended fucntion call to use when reading hyperslabs(previously
1601 known as data slices). HDFv3.3 will continue to support "DFSDgetslice"
1602 only to maintain backward compatibility with HDF applications built
1603 on earlier versions of the library.
1604 ----------------------------------------------------------------------------*/
1605 intn
DFSDgetslice(const char * filename,int32 winst[],int32 windims[],VOIDP data,int32 dims[])1606 DFSDgetslice(const char *filename, int32 winst[], int32 windims[], VOIDP data,
1607 int32 dims[])
1608 {
1609 intn ret_value;
1610
1611 ret_value = (DFSDIgetslice(filename, winst, windims, data, dims, 0));
1612
1613 return ret_value;
1614 }
1615
1616 /*-----------------------------------------------------------------------------
1617 NAME
1618 DFSDstartslice
1619 USAGE
1620 int DFSDstartslice(filename)
1621 char *filename; IN: name of HDF file to write to
1622 RETURNS
1623 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1624 DESCRIPTION
1625 Prepares the DFSD interface to write a slice to a scientific data set.
1626 Before calling "DFSDstartslice", you must call "DFSDsetdims" to
1627 specify the dimensions of the data set to be written to the file.
1628 "DFSDstartslice" always appends a new data set to an existing file.
1629 Remember, you must call "DFSDstartslice" before calling "DFSDputslice"
1630 or "DFSDendslice". "DFSDstarslice" is obsolete in favor of "DFSDstartslab"
1631 "DFSDstartslab" is the recommended function to call to use when
1632 beginning hyperslab(i.e. data slabs) opertaions. HDFv3.3 will continue
1633 to support "DFSDstartslice" only to maintain backward compatibility
1634 with HDF applications built on earlier version of the library.
1635 -----------------------------------------------------------------------------*/
1636 intn
DFSDstartslice(const char * filename)1637 DFSDstartslice(const char *filename)
1638 {
1639 intn i;
1640 int32 size;
1641 intn ret_value = SUCCEED;
1642 CONSTR(FUNC, "DFSDstartslice");
1643
1644 HEclear();
1645
1646 /* Perform global, one-time initialization */
1647 if (library_terminate == FALSE)
1648 if(DFSDIstart()==FAIL)
1649 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1650
1651 if (!Writesdg.rank) /* dimensions not set */
1652 HGOTO_ERROR(DFE_BADDIM, FAIL);
1653
1654 Sfile_id = DFSDIopen(filename, DFACC_WRITE);
1655 if (Sfile_id == DF_NOFILE)
1656 HGOTO_ERROR(DFE_BADOPEN, FAIL);
1657
1658 Writesdg.data.tag = DFTAG_SD;
1659
1660 if (!Writeref)
1661 Writeref = Hnewref(Sfile_id);
1662 if (!Writeref)
1663 HGOTO_ERROR(DFE_BADREF, FAIL);
1664 Writesdg.data.ref = Writeref;
1665
1666 if (Writesdg.numbertype == DFNT_NONE) /* if NT not set,default to float32 */
1667 DFSDsetNT(DFNT_FLOAT32);
1668
1669 /* set up to write data */
1670 size = DFKNTsize(Writesdg.numbertype);
1671 for (i = 0; i < Writesdg.rank; i++)
1672 size *= Writesdg.dimsizes[i];
1673
1674 Writesdg.aid = Hstartwrite(Sfile_id, DFTAG_SD, Writeref, size);
1675 if (Writesdg.aid == FAIL)
1676 HCLOSE_GOTO_ERROR(Sfile_id,DFE_BADAID, FAIL);
1677
1678 /* allocate array for keeping track of dims written */
1679 Sddims = (int32 *) HDmalloc((uint32) Writesdg.rank * sizeof(int32));
1680 if (Sddims == NULL)
1681 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
1682
1683 for (i = 0; i < Writesdg.rank; i++)
1684 Sddims[i] = 0; /* nothing written so far */
1685
1686 done:
1687 if(ret_value == FAIL)
1688 { /* Error condition cleanup */
1689
1690 } /* end if */
1691
1692 /* Normal function cleanup */
1693 return ret_value;
1694 }
1695
1696 /*-----------------------------------------------------------------------------
1697 NAME
1698 DFSDputslice
1699 USAGE
1700 int DFSDputslice(winend, data, dims)
1701 int32 winend[]; IN: dimensions that specify the size of slice to be
1702 written
1703 VOID *data; IN: array containing slice to be written
1704 int32 dims[]; IN: dimensions of array data
1705 RETURNS
1706 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1707 DESCRIPTION
1708 Writes part of a scientific data set to a file. "DFSDputslice" takes
1709 some contiguous part of an array in memory and stores it as part of
1710 the scientific data set array specified by "DFSDgetdims". Slices must
1711 be stored contiguously. Array "windims" specifies the size of the
1712 slice to be written. The number of elements in "windims" is equal to
1713 the number of dimensions in the scientific data set array. The array
1714 "data" is the array in memory containg the slice. The array "dims"
1715 contains the dimensions of the array "data". Note that the two arrays
1716 "windim" and "dims" need not be the same since the "windims" arguement
1717 could refer to a sub-array of "data". In this case only a portion
1718 of the array "data" is written to the scientific data set. All
1719 parameters assume FORTRAN-style 1-based arrays. "DFSDputslice" is
1720 obsoleted by "DFSDwriteslab". DFSDwriteslab is the recommended function
1721 call to use when writing hyperslabs(previously known as data slices).
1722 HDFv3.3 will continue to support "DFSDputslice" only to maintain
1723 backward compatibility with HDF applications built on earlier versions
1724 of the library.
1725 -----------------------------------------------------------------------------*/
1726 intn
DFSDputslice(int32 winend[],VOIDP data,int32 dims[])1727 DFSDputslice(int32 winend[], VOIDP data, int32 dims[])
1728 {
1729 intn ret_value;
1730
1731 ret_value = (DFSDIputslice(winend, data, dims, 0));
1732
1733 return ret_value;
1734 }
1735
1736 /*-----------------------------------------------------------------------------
1737 NAME
1738 DFSDendslice
1739 USAGE
1740 int DFSDendslice()
1741 RETURNS
1742 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1743 DESCRIPTION
1744 Terminates the write operation after storing a slice of data in a
1745 scientific data set. "DFSDendslice" must be called after all the
1746 slices are written. It checks to insure that the entire data set
1747 has been written, and returns an error code if not. "DFSDendslice"
1748 is obsolete in favor of "DFSDendslab". "DFSDendslab" is the
1749 recommended function call to use when terminating hyperslab(previously
1750 known as data slices) operations. HDFv3.3 will continue to support
1751 "DFSDendslice" only to maintain backward compatability with HDF
1752 applications build on earlier versions of the library.
1753
1754 ----------------------------------------------------------------------------*/
1755 intn
DFSDendslice(void)1756 DFSDendslice(void)
1757 {
1758 intn ret_value;
1759
1760 ret_value = (DFSDIendslice(0));
1761
1762 return ret_value;
1763 }
1764
1765 /*---------------------------------------------------------------------------
1766 NAME
1767 DFSDsetNT
1768 USAGE
1769 int DFSDsetNT(numbertype)
1770 int32 *numbertype; IN: Number type of the data to be written
1771 RETURNS
1772 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1773 DESCRIPTION
1774 Sets the number type for the data to be written in the next write
1775 operation. "DFSDsetNT" must be called if a number type other than
1776 "float32" is to be stored. "DFSDsetNT" and "DFSDsetdims" can be called
1777 in any order, but they should be called before any other "DFSDset*"
1778 functions and before "DFSDputdata" or "DFSDadddata". Valid values for
1779 "DFSDgetNT" are of the general form "DFNT_<numbertype>". If you include
1780 the headier file "hdf.h" in your program, you can use the following
1781 symbolic names for the number types:
1782 32-bit float DFNT_FLOAT32 5
1783 64-bit float DFNT_FLOAT64 6
1784 8-bit signed int DFNT_INT8 20
1785 8-bit unsigned int DFNT_UINT8 21
1786 16-bit signed int DFNT_INT16 22
1787 16-bit unsigned int DFNT_UINT16 23
1788 32-bit signed int DFNT_INT32 24
1789 32-bit unsigned int DFNT_UINT32 25
1790 ---------------------------------------------------------------------------*/
1791 intn
DFSDsetNT(int32 numbertype)1792 DFSDsetNT(int32 numbertype)
1793 {
1794 uint8 outNT;
1795 intn ret_value = SUCCEED;
1796 CONSTR(FUNC, "DFSDsetNT");
1797
1798 HEclear();
1799
1800 /* Perform global, one-time initialization */
1801 if (library_terminate == FALSE)
1802 if(DFSDIstart()==FAIL)
1803 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1804
1805 outNT = (uint8) (DFKisnativeNT(numbertype) ? DFKgetPNSC(numbertype, DF_MT) :
1806 (DFKislitendNT(numbertype) ? DFNTF_PC : DFNTF_HDFDEFAULT));
1807 if ((numbertype == Writesdg.numbertype)
1808 && (outNT == Writesdg.filenumsubclass))
1809 HGOTO_DONE(SUCCEED);
1810
1811 /* Forget previous numbertype */
1812 if (DFSDIclearNT((DFSsdg *) & Writesdg) < 0)
1813 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1814
1815 Writesdg.numbertype = numbertype;
1816 Writesdg.filenumsubclass = outNT;
1817 Ref.nt = 0;
1818 Ref.dims = (Ref.dims >= 0 ? 0 : Ref.dims);
1819 Ref.new_ndg = 0;
1820
1821 ret_value = (DFKsetNT(numbertype));
1822
1823 done:
1824 if(ret_value == FAIL)
1825 { /* Error condition cleanup */
1826
1827 } /* end if */
1828
1829 /* Normal function cleanup */
1830 return ret_value;
1831 }
1832
1833 /*-------------------------------------------------------------------
1834 * Name: DFSDIclearNT
1835 * Purpose: Reset all "set" values related to number types
1836 * Inputs: sdg: pointer to sdg struct to clear
1837 * Globals: Ref
1838 * Returns: 0 on success, FAIL on error with error set
1839 * Users: DFSDsetNT, HDF users
1840 * Invokes: none
1841 * Remarks:
1842 *--------------------------------------------------------------------*/
1843 intn
DFSDIclearNT(DFSsdg * sdg)1844 DFSDIclearNT(DFSsdg * sdg)
1845 {
1846 intn i;
1847 intn ret_value = SUCCEED;
1848 CONSTR(FUNC, "DFSDIclearNT");
1849
1850 HEclear();
1851
1852 /* Perform global, one-time initialization */
1853 if (library_terminate == FALSE)
1854 if(DFSDIstart()==FAIL)
1855 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1856
1857 sdg->numbertype = DFNT_NONE;
1858 sdg->filenumsubclass = DFNTF_NONE;
1859
1860 /* free scale pointers. Note: scale pointer array is not freed */
1861 /* sdg->dimscales will be freed only when rank is changed */
1862 if (sdg->dimscales)
1863 {
1864 for (i = 0; i < sdg->rank; i++)
1865 HDfreenclear(sdg->dimscales[i]);
1866 }
1867
1868 Ref.nt = -1;
1869 Ref.maxmin = -1; /* maxmin and scales should be changed to */
1870 Ref.scales = -1; /* new number type */
1871 Ref.new_ndg = -1;
1872
1873 done:
1874 if(ret_value == FAIL)
1875 { /* Error condition cleanup */
1876
1877 } /* end if */
1878
1879 /* Normal function cleanup */
1880
1881 return ret_value;
1882 }
1883
1884 /*---------------------------------------------------------------------------
1885 NAME
1886 DFSDgetNT
1887 USAGE
1888 int DFSDgetNT(numbertype)
1889 int32 *numbertype; OUT: Number type of the data in the scientific
1890 data set.
1891 RETURNS
1892 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1893 DESCRIPTION
1894 Gets the number type of the current scientific data set. This
1895 information is then used by calls such as "DFSDgetdata" and
1896 "DFSDgetslice". Since "DFSDgetNT" gets the number type of the
1897 current data set, "DFSDgetdims" must be called before calling
1898 "DFSDgetNT". Valid values for "DFSDgetNT" are of the general form
1899 "DFNT_<numbertype>". The following are valid symbolic names and
1900 their number types:
1901
1902 32-bit float DFNT_FLOAT32 5
1903 64-bit float DFNT_FLOAT64 6
1904 8-bit signed int DFNT_INT8 20
1905 8-bit unsigned int DFNT_UINT8 21
1906 16-bit signed int DFNT_INT16 22
1907 16-bit unsigned int DFNT_UINT16 23
1908 32-bit signed int DFNT_INT32 24
1909 32-bit unsigned int DFNT_UINT32 25
1910 --------------------------------------------------------------------------- */
1911 intn
DFSDgetNT(int32 * pnumbertype)1912 DFSDgetNT(int32 *pnumbertype)
1913 {
1914 intn ret_value = SUCCEED;
1915 CONSTR(FUNC, "DFSDgetNT");
1916
1917 HEclear();
1918
1919 /* Perform global, one-time initialization */
1920 if (library_terminate == FALSE)
1921 if(DFSDIstart()==FAIL)
1922 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1923
1924 *(pnumbertype) = Readsdg.numbertype;
1925 if (*(pnumbertype) == DFNT_NONE)
1926 HGOTO_ERROR(DFE_BADNUMTYPE, FAIL);
1927
1928 done:
1929 if(ret_value == FAIL)
1930 { /* Error condition cleanup */
1931
1932 } /* end if */
1933
1934 /* Normal function cleanup */
1935 return ret_value;
1936 }
1937
1938 /*---------------------------------------------------------------------------
1939 NAME
1940 DFSDpre32sdg
1941 USAGE
1942 int DFSDpre32sdg(filename, ref, ispre32)
1943 char *filename; IN: The name of the HDF file containing the
1944 scientific data set
1945 uint16 ref; IN: Reference number of scientific data set
1946 int ispre32; OUT: Pointer to the results of the inquiry
1947 RETURNS
1948 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
1949 DESCRIPTION
1950 Tests if the scientific data set with the specified reference number
1951 was created by a HDF library that precedes HDF3.2. This routine is
1952 for programmers who need to know whether a scientific data set was
1953 written by a version of the HDF library earlier than HDF3.2. If the
1954 scientific data set was created with a version of HDF prior to v3.2,
1955 "ispre32" will be set to 1, otherwise it will be set to 0. Based on
1956 this information, programmers can decide whether or not to transpose
1957 the corresponding array.
1958 ----------------------------------------------------------------------------*/
1959 intn
DFSDpre32sdg(char * filename,uint16 ref,intn * ispre32)1960 DFSDpre32sdg(char *filename, uint16 ref, intn *ispre32)
1961 {
1962 uint32 num;
1963 int32 file_id;
1964 intn found = 0;
1965 DFnsdgle *ptr;
1966 intn ret_value = SUCCEED;
1967 CONSTR(FUNC, "DFSDpre32sdg");
1968
1969 HEclear();
1970
1971 /* Perform global, one-time initialization */
1972 if (library_terminate == FALSE)
1973 if(DFSDIstart()==FAIL)
1974 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1975
1976 file_id = DFSDIopen(filename, DFACC_READ);
1977 if (file_id == FAIL)
1978 HGOTO_ERROR(DFE_BADOPEN, FAIL);
1979 ptr = nsdghdr->nsdg_t;
1980 num = nsdghdr->size;
1981
1982 while ((num > 0) && (ptr != NULL) && !found)
1983 {
1984 if ((ptr->nsdg.tag == DFTAG_SDG)
1985 && (ptr->nsdg.ref == ref))
1986 { /* pure SDG */
1987 found = 1;
1988 *ispre32 = TRUE;
1989 }
1990 else if ((ptr->sdg.tag == DFTAG_SDG)
1991 && (ptr->sdg.ref == ref))
1992 { /* NDGSDG */
1993 found = 1;
1994 *ispre32 = FALSE;
1995 }
1996 else
1997 {
1998 ptr = ptr->next;
1999 num--;
2000 }
2001 } /* while */
2002
2003 if (((num == 0) && (ptr != NULL)) || ((num != 0) && (ptr == NULL)) || !found)
2004 HCLOSE_GOTO_ERROR(file_id, DFE_BADTABLE, FAIL);
2005
2006 if (Hclose(file_id) < 0)
2007 ret_value = FAIL;
2008
2009 done:
2010 if(ret_value == FAIL)
2011 { /* Error condition cleanup */
2012
2013 } /* end if */
2014
2015 /* Normal function cleanup */
2016 return ret_value;
2017 } /* end of DFSDpre32sdg */
2018
2019 /******************************************************************************/
2020 /*--------------------- Lower level routines --------------------------------*/
2021 /******************************************************************************/
2022
2023 /* Functions for NDG and SDG stuff */
2024
2025 /*--------------------------------------------------------------------------
2026 * Name: DFSDIsetnsdg_t
2027 * Purpose: Set up the NDG/SDG table. Each node has two
2028 fields: the 1st field is NDG or SDG, the 2nd
2029 field has value only when it is a special
2030 NDG, i.e. the data set is float32 and not
2031 compressed.
2032 * Inputs: file_id: pointer to HDF file containing SDG
2033 * Returns: 0 on success, FAIL on failure with error set
2034 * Users: DFSDIopen for READ
2035 *--------------------------------------------------------------------------*/
2036 static intn
DFSDIsetnsdg_t(int32 file_id,DFnsdg_t_hdr * l_nsdghdr)2037 DFSDIsetnsdg_t(int32 file_id, DFnsdg_t_hdr * l_nsdghdr)
2038 {
2039 uint32 sz_DFnsdgle = (uint32) sizeof(struct DFnsdgle);
2040 int32 aid; /* access id */
2041 int32 ndgs; /* number of ndg's */
2042 int32 sdgs; /* number of sdg's */
2043 int32 GroupID;
2044 uint16 intag=DFTAG_NULL;
2045 uint16 inref=DFTAG_NULL;
2046 intn moretags;
2047 intn found;
2048 DFnsdgle *ntb = NULL;
2049 DFnsdgle *stb = NULL;
2050 DFnsdgle *new;
2051 DFnsdgle *nf;
2052 DFnsdgle *nr;
2053 DFnsdgle *sf;
2054 DFnsdgle *sr;
2055 DFdi di;
2056 DFdi lnkdd[2];
2057 uint8 *bufp;
2058 intn ret_value = SUCCEED;
2059 CONSTR(FUNC, "DFSDsetnsdg_t");
2060
2061 HEclear();
2062
2063 /* Perform global, one-time initialization */
2064 if (library_terminate == FALSE)
2065 if(DFSDIstart()==FAIL)
2066 HGOTO_ERROR(DFE_CANTINIT, FAIL);
2067
2068 if (!HDvalidfid(file_id))
2069 HGOTO_ERROR(DFE_BADCALL, FAIL);
2070
2071 /* Check if temproray buffer has been allocated */
2072 if (ptbuf == NULL)
2073 {
2074 ptbuf = (uint8 *) HDmalloc(TBUF_SZ * sizeof(uint8));
2075 if (ptbuf == NULL)
2076 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2077 }
2078
2079 /* MMM: Talk to Shiming and make sure the change made to the way ndgs
2080 and sdgs are handled is ok.
2081 */
2082 ndgs = Hnumber(file_id, DFTAG_NDG);
2083 sdgs = Hnumber(file_id, DFTAG_SDG);
2084 if ((ndgs == FAIL) || (sdgs == FAIL))
2085 HGOTO_ERROR(DFE_INTERNAL, FAIL);
2086
2087 if ((ndgs + sdgs) == 0)
2088 { /* no sdgs or ndgs in file */
2089 l_nsdghdr->size = 0;
2090 l_nsdghdr->nsdg_t = NULL;
2091 HGOTO_DONE(SUCCEED);
2092 }
2093 if ((ntb = (DFnsdgle *) HDmalloc(sz_DFnsdgle)) == NULL)
2094 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2095
2096 /* the first node in each table is a dummy node */
2097 ntb->nsdg.tag = DFTAG_NULL; /* set up and init an ndg table */
2098 ntb->nsdg.ref = 0;
2099 ntb->sdg.tag = DFTAG_NULL;
2100 ntb->sdg.ref = 0;
2101 ntb->next = NULL;
2102
2103 if ((stb = (DFnsdgle *) HDmalloc(sz_DFnsdgle)) == NULL)
2104 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2105
2106 stb->nsdg.tag = DFTAG_NULL; /* set up and init an sdg table */
2107 stb->nsdg.ref = 0;
2108 stb->sdg.tag = DFTAG_NULL; /* this field should be named as */
2109 stb->sdg.ref = 0; /* stb->ndg.tag, the ndg to which this */
2110 stb->next = NULL; /* sdg belongs. */
2111
2112 aid = Hstartread(file_id, DFTAG_WILDCARD, DFREF_WILDCARD);
2113 moretags = (aid != FAIL);
2114 while (moretags)
2115 { /* read dd's and put each dd in ntb or stb */
2116 HQuerytagref(aid, &intag, &inref);
2117 /* put NDG or SDG on ntb or stb */
2118 if (intag == DFTAG_NDG)
2119 {
2120 nr = ntb;
2121 nf = ntb;
2122 while ((inref > nf->nsdg.ref) && (nf->next != NULL))
2123 {
2124 nr = nf;
2125 nf = nf->next;
2126 }
2127 /* MMM: Tlk to Shiming and make sure the way this part was
2128 rearranged is ok.
2129 */
2130 /* check for duplicate nsdg */
2131 if (inref == nf->nsdg.ref)
2132 HGOTO_ERROR(DFE_BADNDG, FAIL);
2133
2134 /* add a node to the table */
2135 if ((new = (DFnsdgle *) HDmalloc(sz_DFnsdgle)) == NULL)
2136 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2137
2138 new->nsdg.tag = DFTAG_NDG;
2139 new->nsdg.ref = inref;
2140 new->sdg.tag = DFTAG_NULL;
2141 new->sdg.ref = 0;
2142
2143 if (inref < nf->nsdg.ref)
2144 { /* does it go before current node? */
2145 new->next = nf;
2146 nr->next = new;
2147 }
2148 else
2149 { /* or at the end? */
2150 new->next = nf->next;
2151 nf->next = new;
2152 }
2153
2154 /* Does this NDG have an SDG? */
2155 if ((GroupID = DFdiread(file_id, DFTAG_NDG, inref)) < 0)
2156 HGOTO_ERROR(DFE_BADGROUP, FAIL);
2157
2158 found = FALSE;
2159 di.tag = DFTAG_NULL;
2160 di.ref = 0;
2161 while ((found == 0) && (DFdiget(GroupID, &di.tag, &di.ref) == 0))
2162 {
2163 if (di.tag == DFTAG_SDLNK)
2164 found = TRUE;
2165 }
2166
2167 if (found)
2168 { /* read in the tag/refs in the link element */
2169 if (Hgetelement(file_id, di.tag, di.ref, ptbuf) == (int32) FAIL)
2170 {
2171 DFdifree(GroupID);
2172 HGOTO_ERROR(DFE_GETELEM, FAIL);
2173 }
2174 bufp = ptbuf;
2175 UINT16DECODE(bufp, lnkdd[0].tag);
2176 UINT16DECODE(bufp, lnkdd[0].ref);
2177 UINT16DECODE(bufp, lnkdd[1].tag);
2178 UINT16DECODE(bufp, lnkdd[1].ref);
2179 new->sdg.tag = lnkdd[1].tag;
2180 new->sdg.ref = lnkdd[1].ref;
2181 DFdifree(GroupID);
2182 }
2183 } /* end of NDG */
2184
2185 if (intag == DFTAG_SDG)
2186 {
2187 sr = stb;
2188 sf = stb;
2189 while ((inref > sf->nsdg.ref) && (sf->next != NULL))
2190 {
2191 sr = sf;
2192 sf = sf->next;
2193 }
2194 if (inref == sf->nsdg.ref)
2195 HGOTO_ERROR(DFE_BADNDG, FAIL);
2196
2197 /* insert a new node */
2198 if ((new = (DFnsdgle *) HDmalloc(sz_DFnsdgle)) == NULL)
2199 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2200
2201 new->nsdg.tag = DFTAG_SDG;
2202 new->nsdg.ref = inref;
2203 new->sdg.tag = DFTAG_NULL;
2204 new->sdg.ref = 0;
2205
2206 if (inref < sf->nsdg.ref)
2207 { /* does it go before current node? */
2208 new->next = sf;
2209 sr->next = new;
2210 }
2211 else
2212 { /* or at the end? */
2213 new->next = sf->next;
2214 sf->next = new;
2215 }
2216 /* Does it belong to an NDG? */
2217 if ((GroupID = DFdiread(file_id, DFTAG_SDG, inref)) < 0)
2218 HGOTO_ERROR(DFE_BADGROUP, FAIL);
2219 found = FALSE;
2220 di.tag = DFTAG_NULL;
2221 di.ref = 0;
2222 while ((found == 0) && (DFdiget(GroupID, &di.tag, &di.ref) == 0))
2223 {
2224 if (di.tag == DFTAG_SDLNK)
2225 found = TRUE;
2226 }
2227 if (found)
2228 { /* read in the tag/refs in the link element */
2229 if (Hgetelement(file_id, di.tag, di.ref, ptbuf) == (int32) FAIL)
2230 {
2231 DFdifree(GroupID);
2232 HGOTO_ERROR(DFE_GETELEM, FAIL);
2233 }
2234 bufp = ptbuf;
2235 UINT16DECODE(bufp, lnkdd[0].tag);
2236 UINT16DECODE(bufp, lnkdd[0].ref);
2237 UINT16DECODE(bufp, lnkdd[1].tag);
2238 UINT16DECODE(bufp, lnkdd[1].ref);
2239 new->sdg.tag = lnkdd[0].tag;
2240 new->sdg.ref = lnkdd[0].ref;
2241 DFdifree(GroupID);
2242 }
2243 } /* end of SDG */
2244
2245 /* get next dd */
2246 moretags = (SUCCEED == Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT));
2247 } /* gone through the dd blocks */
2248 Hendaccess(aid);
2249
2250 /* merge stb and ntb */
2251 /* remove SDGNDG from stb */
2252 nf = ntb->next;
2253 while (nf != NULL)
2254 {
2255 inref = nf->sdg.ref;
2256 if (inref != 0)
2257 { /* it has an SDG */
2258 sr = stb;
2259 sf = stb;
2260 while ((sf->nsdg.ref < inref) && (sf->next != NULL))
2261 {
2262 sr = sf;
2263 sf = sf->next;
2264 }
2265 if (sf->nsdg.ref == inref)
2266 {
2267 if (sf->sdg.ref != nf->nsdg.ref)
2268 {
2269 HGOTO_ERROR(DFE_BADNDG, FAIL);
2270 }
2271 else
2272 {
2273 sr->next = sf->next;
2274 HDfreenclear(sf);
2275 sdgs--;
2276 }
2277 }
2278 }
2279 nf = nf->next;
2280 }
2281
2282 /* check all SDGNDGs were removed */
2283 sf = stb->next;
2284 while (sf != NULL)
2285 {
2286 if (sf->sdg.ref != 0)
2287 HGOTO_ERROR(DFE_BADSDG, FAIL);
2288 sf = sf->next;
2289 }
2290
2291 /* merge the two tables into one */
2292 nf = ntb; /* looking for the end of ntb */
2293 while (nf->next != NULL)
2294 nf = nf->next;
2295 nf->next = stb->next; /* the first node in stb is a dummy */
2296 l_nsdghdr->size = (uint32)(ndgs + sdgs);
2297 l_nsdghdr->nsdg_t = ntb->next;
2298
2299 done:
2300 if(ret_value == FAIL)
2301 { /* Error condition cleanup */
2302
2303 } /* end if */
2304
2305 /* Normal function cleanup */
2306 /* Release the first nodes in stb and ntb */
2307 if (stb != NULL)
2308 HDfree((VOIDP) stb);
2309 if (ntb != NULL)
2310 HDfree((VOIDP) ntb);
2311
2312 return ret_value;
2313 } /* end of DFSDsdtnsdg_t */
2314
2315 /*-----------------------------------------------------------------------
2316 * Name DFSDInextnsdg
2317 * Purpose: Returns next ndg or sdg in the file
2318 * Inputs: nsdghdr: point to the nsdg table
2319 * nsdg: the structure holds the di of next sdg or ndg
2320 * Returns: 0 on succeeds, FAIL on failure
2321 * -------------------------------------------------------------------*/
2322 static intn
DFSDInextnsdg(DFnsdg_t_hdr * l_nsdghdr,DFdi * nsdg)2323 DFSDInextnsdg(DFnsdg_t_hdr * l_nsdghdr, DFdi * nsdg)
2324 {
2325 uint32 num;
2326 intn found = FALSE;
2327 DFnsdgle *ptr;
2328 intn ret_value = SUCCEED;
2329 CONSTR(FUNC, "DFSDInextnsdg");
2330
2331 HEclear();
2332
2333 /* Perform global, one-time initialization */
2334 if (library_terminate == FALSE)
2335 if(DFSDIstart()==FAIL)
2336 HGOTO_ERROR(DFE_CANTINIT, FAIL);
2337
2338 nsdg->tag = DFTAG_NULL;
2339 nsdg->ref = 0;
2340 ptr = l_nsdghdr->nsdg_t;
2341 num = l_nsdghdr->size;
2342
2343 if ((ptr == NULL) || (num == 0))
2344 HGOTO_DONE(SUCCEED);
2345
2346 if ((lastnsdg.tag == DFTAG_NULL) && (lastnsdg.ref == 0))
2347 {
2348 found = TRUE;
2349 }
2350 else
2351 {
2352 while ((num > 0) && (ptr != NULL) && !found)
2353 {
2354 if ((ptr->nsdg.tag == lastnsdg.tag)
2355 && (ptr->nsdg.ref == lastnsdg.ref))
2356 {
2357 if ((ptr = ptr->next) != NULL)
2358 found = TRUE;
2359 }
2360 else
2361 {
2362 ptr = ptr->next;
2363 num--;
2364 }
2365 } /* while */
2366
2367 if (((num == 0) && (ptr != NULL))
2368 || ((num != 0) && (ptr == NULL)) || !found)
2369 {
2370 HGOTO_ERROR(DFE_BADTABLE, FAIL);
2371 }
2372 } /* else */
2373
2374 if (found)
2375 {
2376 nsdg->tag = ptr->nsdg.tag;
2377 nsdg->ref = ptr->nsdg.ref;
2378 }
2379
2380 done:
2381 if(ret_value == FAIL)
2382 { /* Error condition cleanup */
2383
2384 } /* end if */
2385
2386 /* Normal function cleanup */
2387
2388 return ret_value;
2389 } /* end of DFSDInextnsdg */
2390
2391 /*-----------------------------------------------------------------------------
2392 * Name: DFSDIgetndg
2393 * Purpose: Reads in NDG
2394 * Inputs: file_id: pointer to HDF file containing NDG
2395 * ref: ref of NDG to read
2396 * sdg: pointer to DFSsdg struct to read NDG into
2397 * Returns: 0 on success, FAIL on failure with error set
2398 * Users: HDF programmers, DFSDIsdginfo
2399 * Invokes: DFgetelement, DFdiread, DFdiget, DFaccess, DFread
2400 DFSDgetsdg
2401 * Method: Reads in NDG using DFdiread. Gets each tag/ref using DFdiget.
2402 * Reads in dimensions using DFgetelement.
2403 * Call DFSDgetsdg to read in the rest info.
2404 * Mallocs space for these, freeing
2405 * previously allocated space.
2406 * Remarks: This accepts non-float32 data
2407 *---------------------------------------------------------------------------*/
2408 static intn
DFSDIgetndg(int32 file_id,uint16 tag,uint16 ref,DFSsdg * sdg)2409 DFSDIgetndg(int32 file_id, uint16 tag, uint16 ref, DFSsdg * sdg)
2410 {
2411 int16 int16var;
2412 int32 i;
2413 intn luf;
2414 DFdi elmt;
2415 DFdi nt;
2416 int32 length;
2417 int32 numtype = 0; /* current number type */
2418 int32 fileNTsize = 0; /* size of this NT as it is in the file */
2419 int32 localNTsize = 0; /* size of this NT as it is in this machine */
2420 int32 ret;
2421 int32 aid;
2422 int32 GroupID;
2423 int8 fileNT = 0; /* file number subclass */
2424 int8 platnumsubclass = 0; /* platform number subclass */
2425 uint8 ntstring[4];
2426 uint8 *isscales;
2427 uint8 *buf;
2428 uint8 *p; /* temporary pointer for moving things to buffer */
2429 intn ret_value = SUCCEED;
2430 CONSTR(FUNC, "DFSDIgetndg");
2431
2432 HEclear();
2433
2434 /* Perform global, one-time initialization */
2435 if (library_terminate == FALSE)
2436 if(DFSDIstart()==FAIL)
2437 HGOTO_ERROR(DFE_CANTINIT, FAIL);
2438
2439 if (!HDvalidfid(file_id))
2440 HGOTO_ERROR(DFE_BADCALL, FAIL);
2441
2442 if (!ref)
2443 HGOTO_ERROR(DFE_BADREF, FAIL);
2444
2445 /* Check if temproray buffer has been allocated */
2446 if (ptbuf == NULL)
2447 {
2448 ptbuf = (uint8 *) HDmalloc(TBUF_SZ * sizeof(uint8));
2449 if (ptbuf == NULL)
2450 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2451 }
2452
2453 /* read NDG into memory */
2454 if ((GroupID = DFdiread(file_id, tag, ref)) < 0)
2455 HGOTO_ERROR(DFE_BADGROUP, FAIL);
2456
2457 DFSDIclear(sdg);
2458 if (tag == DFTAG_NDG)
2459 DFSDIclearNT(sdg);
2460 Ismaxmin = 0;
2461 IsCal = FALSE;
2462
2463 /*
2464 * Loop through all members of the group
2465 */
2466 while (!DFdiget(GroupID, &elmt.tag, &elmt.ref))
2467 {
2468 luf = -1; /* flag value for label/unit/ */
2469 /* format gets process tag/ref */
2470 switch (elmt.tag)
2471 {
2472
2473 case DFTAG_SD: /* data tag/ref */
2474 sdg->data.tag = elmt.tag; /* put tag/ref in struct */
2475 sdg->data.ref = elmt.ref;
2476 break;
2477
2478 case DFTAG_SDD: /* dimension */
2479 aid = Hstartread(file_id, elmt.tag, elmt.ref);
2480 if (aid == FAIL)
2481 {
2482 DFdifree(GroupID);
2483 HGOTO_ERROR(DFE_BADAID, FAIL);
2484 }
2485
2486 /* read rank */
2487 if (Hread(aid, (int32) 2, ptbuf) == FAIL)
2488 {
2489 DFdifree(GroupID);
2490 Hendaccess(aid);
2491 HGOTO_ERROR(DFE_READERROR, FAIL);
2492 }
2493 p = ptbuf;
2494 INT16DECODE(p, int16var);
2495 sdg->rank=(intn)int16var;
2496
2497 /* get space for dimensions */
2498 sdg->dimsizes = (int32 *) HDmalloc((uint32) sdg->rank *
2499 sizeof(int32));
2500 if (sdg->dimsizes == NULL)
2501 {
2502 DFdifree(GroupID);
2503 Hendaccess(aid);
2504 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2505 }
2506
2507 /* read dimension record */
2508 if (Hread(aid, (int32) 4 * sdg->rank, ptbuf) == FAIL)
2509 {
2510 DFdifree(GroupID);
2511 Hendaccess(aid);
2512 HGOTO_ERROR(DFE_READERROR, FAIL);
2513 }
2514 p = ptbuf;
2515 for (i = 0; i < sdg->rank; i++)
2516 INT32DECODE(p, sdg->dimsizes[i]);
2517
2518 /* read tag/ref of NT */
2519 if (Hread(aid, (int32) 4, ptbuf) == FAIL)
2520 {
2521 DFdifree(GroupID);
2522 Hendaccess(aid);
2523 HGOTO_ERROR(DFE_READERROR, FAIL);
2524 }
2525 p = ptbuf;
2526 UINT16DECODE(p, nt.tag);
2527 UINT16DECODE(p, nt.ref);
2528
2529 /* read actual NT */
2530 if (Hgetelement(file_id, nt.tag, nt.ref, ntstring) == FAIL)
2531 {
2532 DFdifree(GroupID);
2533 Hendaccess(aid);
2534 HGOTO_ERROR(DFE_GETELEM, FAIL);
2535 }
2536
2537 /* check for any valid NT */
2538 if (ntstring[1] == DFNT_NONE)
2539 {
2540 DFdifree(GroupID);
2541 Hendaccess(aid);
2542 HGOTO_ERROR(DFE_BADCALL, FAIL);
2543 }
2544
2545 /* if looking for an SDG type must be FLOAT32 */
2546 if (tag == DFTAG_SDG && ntstring[1] != DFNT_FLOAT32)
2547 {
2548 DFdifree(GroupID);
2549 Hendaccess(aid);
2550 HGOTO_ERROR(DFE_BADCALL, FAIL);
2551 }
2552
2553 /* set NT info */
2554 numtype = (int32)ntstring[1];
2555 fileNT = (int8)ntstring[3];
2556 platnumsubclass = DFKgetPNSC(numtype, DF_MT);
2557 if ((fileNT != DFNTF_HDFDEFAULT)
2558 && (fileNT != DFNTF_PC)
2559 && (fileNT != platnumsubclass))
2560 {
2561 DFdifree(GroupID);
2562 Hendaccess(aid);
2563 HGOTO_ERROR(DFE_BADCALL, FAIL);
2564 }
2565 if (fileNT != DFNTF_HDFDEFAULT)
2566 { /* if native or little endian */
2567 if (fileNT != DFNTF_PC) /* native */
2568 numtype |= DFNT_NATIVE;
2569 else /* little endian */
2570 numtype |= DFNT_LITEND;
2571 } /* end if */
2572
2573 sdg->filenumsubclass = ntstring[3];
2574 sdg->numbertype = numtype;
2575
2576 /* set size of NT */
2577 fileNTsize = DFKNTsize(numtype);
2578 localNTsize = DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
2579
2580 /* read and check all scale NTs */
2581 for (i = 0; i < sdg->rank; i++)
2582 {
2583 if (Hread(aid, (int32) 4, ptbuf) == FAIL)
2584 {
2585 DFdifree(GroupID);
2586 Hendaccess(aid);
2587 HGOTO_ERROR(DFE_READERROR, FAIL);
2588 }
2589 p = ptbuf;
2590 UINT16DECODE(p, nt.tag);
2591 UINT16DECODE(p, nt.ref);
2592
2593 /* read NT itself */
2594 if (Hgetelement(file_id, nt.tag, nt.ref, ntstring) == FAIL)
2595 {
2596 DFdifree(GroupID);
2597 Hendaccess(aid);
2598 HGOTO_ERROR(DFE_GETELEM, FAIL);
2599 }
2600
2601 /* check for any valid NT */
2602 if (ntstring[1] == DFNT_NONE)
2603 {
2604 DFdifree(GroupID);
2605 Hendaccess(aid);
2606 HGOTO_ERROR(DFE_BADCALL, FAIL);
2607 }
2608
2609 /* if looking for an SDG type must be FLOAT32 */
2610 if (tag == DFTAG_SDG && ntstring[1] != DFNT_FLOAT32)
2611 {
2612 DFdifree(GroupID);
2613 Hendaccess(aid);
2614 HGOTO_ERROR(DFE_BADCALL, FAIL);
2615 }
2616
2617 } /* end for loop */
2618 Hendaccess(aid);
2619 break;
2620
2621 case DFTAG_SDLNK: /* SDG NDG link */
2622 break; /* do nothing in 3.2 */
2623
2624 case DFTAG_SDL: /* labels */
2625 if (luf == (-1))
2626 luf = LABEL;
2627
2628 case DFTAG_SDU: /* units */
2629 if (luf == (-1))
2630 luf = UNIT;
2631
2632 case DFTAG_SDF: /* formats */
2633 if (luf == (-1))
2634 luf = FORMAT;
2635
2636 if (!sdg->dimsizes)
2637 {
2638 DFdifree(GroupID);
2639 HGOTO_ERROR(DFE_CORRUPT, FAIL);
2640 }
2641
2642 /* get needed size of buffer, allocate */
2643 length = Hlength(file_id, elmt.tag, elmt.ref);
2644 if (length == FAIL)
2645 {
2646 DFdifree(GroupID);
2647 HGOTO_ERROR(DFE_BADLEN, FAIL);
2648 }
2649 buf = (uint8 *) HDmalloc((uint32) length);
2650 if (buf == NULL)
2651 {
2652 DFdifree(GroupID);
2653 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2654 }
2655
2656 /* read in luf */
2657 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
2658 {
2659 DFdifree(GroupID);
2660 HDfree((VOIDP) buf);
2661 HGOTO_ERROR(DFE_GETELEM, FAIL);
2662 }
2663 p = buf;
2664
2665 /* allocate data luf space */
2666 sdg->dataluf[luf] = (char *) HDmalloc((uint32) HDstrlen((char *) p) + 1);
2667
2668 if (sdg->dataluf[luf] == NULL)
2669 {
2670 DFdifree(GroupID);
2671 HDfree((VOIDP) buf);
2672 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2673 }
2674
2675 /* extract data luf */
2676 HDstrcpy(sdg->dataluf[luf], (char *) p);
2677 p += HDstrlen(sdg->dataluf[luf]) + 1;
2678
2679 /* get space for dimluf array */
2680 sdg->dimluf[luf] =
2681 (char **) HDmalloc((uint32) sdg->rank * sizeof(char *));
2682 if (sdg->dimluf[luf] == NULL)
2683 {
2684 DFdifree(GroupID);
2685 HDfree((VOIDP) buf);
2686 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2687 }
2688
2689 /* extract dimension lufs */
2690 for (i = 0; i < sdg->rank; i++)
2691 {
2692 sdg->dimluf[luf][i] = (char *)
2693 HDmalloc((uint32) HDstrlen((char *) p) + 1);
2694 if (sdg->dimluf[luf][i] == NULL)
2695 {
2696 DFdifree(GroupID);
2697 HDfree((VOIDP) buf);
2698 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2699 }
2700 HDstrcpy(sdg->dimluf[luf][i], (char *) p);
2701 p += HDstrlen(sdg->dimluf[luf][i]) + 1;
2702 }
2703 HDfree((VOIDP) buf);
2704 break;
2705
2706 case DFTAG_SDS: /* scales */
2707 if (!sdg->dimsizes)
2708 {
2709 DFdifree(GroupID);
2710 HGOTO_ERROR(DFE_CORRUPT, FAIL);
2711 }
2712
2713 /* set up to read scale */
2714 aid = Hstartread(file_id, elmt.tag, elmt.ref);
2715 if (aid == FAIL)
2716 {
2717 DFdifree(GroupID);
2718 HGOTO_ERROR(DFE_BADAID, FAIL);
2719 }
2720
2721 /* read isscales */
2722 isscales = (uint8 *) HDmalloc((uint32) sdg->rank);
2723 if (isscales == NULL)
2724 {
2725 DFdifree(GroupID);
2726 Hendaccess(aid);
2727 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2728 }
2729 if (Hread(aid, (int32) sdg->rank, isscales) == FAIL)
2730 {
2731 DFdifree(GroupID);
2732 Hendaccess(aid);
2733 HGOTO_ERROR(DFE_READERROR, FAIL);
2734 }
2735
2736 /* allocate scale pointers */
2737 sdg->dimscales =
2738 (uint8 **) HDmalloc((uint32) sdg->rank * sizeof(int8 *));
2739 if (sdg->dimscales == NULL)
2740 {
2741 DFdifree(GroupID);
2742 HDfree((VOIDP) isscales);
2743 Hendaccess(aid);
2744 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2745 }
2746
2747 /* read scales */
2748 for (i = 0; i < sdg->rank; i++)
2749 {
2750 sdg->dimscales[i] = NULL; /* default */
2751 if (!isscales[i])
2752 continue;
2753
2754 /* space for scale */
2755 sdg->dimscales[i] = (uint8 *)
2756 HDmalloc((size_t) (sdg->dimsizes[i] * localNTsize));
2757 if (sdg->dimscales[i] == NULL)
2758 {
2759 DFdifree(GroupID);
2760 HDfree((VOIDP) isscales);
2761 Hendaccess(aid);
2762 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2763 }
2764
2765 if (platnumsubclass == fileNT)
2766 { /* no conversion needed */
2767 ret = Hread(aid, (int32) sdg->dimsizes[i] * fileNTsize,
2768 (uint8 *) sdg->dimscales[i]);
2769 if (ret == FAIL)
2770 {
2771 DFdifree(GroupID);
2772 HDfree((VOIDP) isscales);
2773 Hendaccess(aid);
2774 HGOTO_ERROR(DFE_READERROR, FAIL);
2775 }
2776 }
2777 else
2778 { /* conversion necessary */
2779 /* allocate conversion buffer */
2780 buf = (uint8 *) HDmalloc((size_t) (sdg->dimsizes[i] * fileNTsize));
2781 if (buf == NULL)
2782 {
2783 DFdifree(GroupID);
2784 HDfree((VOIDP) isscales);
2785 Hendaccess(aid);
2786 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2787 }
2788
2789 /* read scale from file */
2790 ret = Hread(aid,(int32) (sdg->dimsizes[i] * fileNTsize), buf);
2791 if (ret == FAIL)
2792 {
2793 DFdifree(GroupID);
2794 HDfree((VOIDP) buf);
2795 HDfree((VOIDP) isscales);
2796 Hendaccess(aid);
2797 HGOTO_ERROR(DFE_READERROR, FAIL);
2798 }
2799
2800 p = buf;
2801
2802 /* convert, all at once */
2803 DFKconvert((VOIDP) p, (VOIDP) sdg->dimscales[i], numtype,
2804 sdg->dimsizes[i], DFACC_READ, 0, 0);
2805
2806 HDfree((VOIDP) buf);
2807 }
2808 }
2809 HDfree((VOIDP) isscales);
2810 Hendaccess(aid);
2811 break;
2812
2813 case DFTAG_SDC: /* coordsys */
2814 /* find and allocate necessary space */
2815 length = Hlength(file_id, elmt.tag, elmt.ref);
2816 if (length == FAIL)
2817 {
2818 DFdifree(GroupID);
2819 HGOTO_ERROR(DFE_BADLEN, FAIL);
2820 }
2821
2822 sdg->coordsys = (char *) HDmalloc((uint32) length);
2823 if (sdg->coordsys == NULL)
2824 {
2825 DFdifree(GroupID);
2826 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2827 }
2828
2829 /* read coordsys */
2830 if (Hgetelement(file_id, elmt.tag, elmt.ref,
2831 (uint8 *) sdg->coordsys) == FAIL)
2832 {
2833 DFdifree(GroupID);
2834 HGOTO_ERROR(DFE_GETELEM, FAIL);
2835 }
2836 break;
2837
2838 case DFTAG_SDM: /* max/min */
2839 if (fileNT == platnumsubclass)
2840 { /* no conversion */
2841 if (Hgetelement(file_id, elmt.tag, elmt.ref,
2842 (uint8 *) &(sdg->max_min[0])) == FAIL)
2843 {
2844 DFdifree(GroupID);
2845 HGOTO_ERROR(DFE_GETELEM, FAIL);
2846 }
2847 }
2848 else
2849 {
2850 /* conversion needed */
2851 /* allocate buffer */
2852 buf = (uint8 *) HDmalloc((size_t) (2 * fileNTsize));
2853 if (buf == NULL)
2854 {
2855 DFdifree(GroupID);
2856 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2857 }
2858
2859 /* read and convert max/min */
2860 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
2861 {
2862 DFdifree(GroupID);
2863 HGOTO_ERROR(DFE_GETELEM, FAIL);
2864 }
2865
2866 DFKconvert((VOIDP) buf, (VOIDP) &(sdg->max_min[0]), numtype, 2,
2867 DFACC_READ, 0, 0);
2868
2869 HDfree((VOIDP) buf);
2870 }
2871 Ismaxmin = 1;
2872 break;
2873
2874 case DFTAG_CAL:
2875 if (fileNT == platnumsubclass)
2876 { /* no conversion */
2877 /* get size of element */
2878 intn eltSize = (intn) Hlength(file_id, elmt.tag, elmt.ref);
2879 if (eltSize == FAIL)
2880 {
2881 DFdifree(GroupID);
2882 HGOTO_ERROR(DFE_BADLEN, FAIL);
2883 }
2884
2885 if (eltSize == 36)
2886 {
2887 /* element is new, double based type */
2888 if (Hgetelement(file_id, elmt.tag, elmt.ref,
2889 (unsigned char *) &sdg->cal) < 0)
2890 {
2891 DFdifree(GroupID);
2892 HGOTO_ERROR(DFE_GETELEM, FAIL);
2893 }
2894 }
2895 else
2896 {
2897 /* element is old float based type */
2898 float32 buf2[4];
2899
2900 /* allocate input buffer */
2901 if (Hgetelement(file_id, elmt.tag, elmt.ref,
2902 (unsigned char *) buf2) < 0)
2903 {
2904 DFdifree(GroupID);
2905 HGOTO_ERROR(DFE_GETELEM, FAIL);
2906 }
2907
2908 /* move 'em over */
2909 sdg->ioff = (float64) buf2[0];
2910 sdg->ioff_err = (float64) buf2[1];
2911 sdg->cal = (float64) buf2[2];
2912 sdg->cal_err = (float64) buf2[3];
2913 sdg->cal_type = DFNT_INT16;
2914
2915 }
2916 }
2917 else
2918 {
2919 intn eltSize;
2920
2921 /* get size of element */
2922 eltSize = (intn) Hlength(file_id, elmt.tag, elmt.ref);
2923 if (eltSize == FAIL)
2924 {
2925 DFdifree(GroupID);
2926 HGOTO_ERROR(DFE_BADLEN, FAIL);
2927 }
2928
2929 /* allocate buffer */
2930 buf = (uint8 *) HDmalloc((uint32) eltSize);
2931 if (buf == NULL)
2932 {
2933 DFdifree(GroupID);
2934 HGOTO_ERROR(DFE_NOSPACE, FAIL);
2935 }
2936
2937 /* read and convert calibration */
2938 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
2939 {
2940 DFdifree(GroupID);
2941 HGOTO_ERROR(DFE_GETELEM, FAIL);
2942 }
2943
2944 if (eltSize == 36)
2945 {
2946 /* element is new, double based type */
2947 /* read in the 64bit float factors */
2948 DFKconvert((VOIDP) buf,
2949 (VOIDP) &sdg->cal,
2950 DFNT_FLOAT64, 4, DFACC_READ, 0, 0);
2951
2952 /* read in the 32bit integer number type */
2953 DFKconvert((VOIDP) (buf + 32),
2954 (VOIDP) &sdg->cal_type,
2955 DFNT_INT32, 1, DFACC_READ, 0, 0);
2956 }
2957 else
2958 {
2959 /* element is old float based type */
2960 float32 buf2[4];
2961
2962 /* convert calibration factors */
2963 DFKconvert((VOIDP) buf, (VOIDP) buf2, DFNT_FLOAT32, 4,
2964 DFACC_READ, 0, 0);
2965
2966 /* move 'em over */
2967 sdg->ioff = (float64) buf2[0];
2968 sdg->ioff_err = (float64) buf2[1];
2969 sdg->cal = (float64) buf2[2];
2970 sdg->cal_err = (float64) buf2[3];
2971 sdg->cal_type = DFNT_INT16;
2972
2973 }
2974 HDfree((VOIDP) buf);
2975 }
2976 IsCal = TRUE;
2977 break;
2978
2979 case DFTAG_FV:
2980 if (fileNT == platnumsubclass)
2981 { /* no conversion */
2982 /* get size of element */
2983 intn eltSize = (intn) Hlength(file_id, elmt.tag, elmt.ref);
2984 if (eltSize == FAIL)
2985 {
2986 DFdifree(GroupID);
2987 HGOTO_ERROR(DFE_BADLEN, FAIL);
2988 }
2989
2990 /* get element */
2991 if (Hgetelement(file_id, elmt.tag, elmt.ref,
2992 (unsigned char *) sdg->fill_value) == FAIL)
2993 {
2994 DFdifree(GroupID);
2995 HGOTO_ERROR(DFE_GETELEM, FAIL);
2996 }
2997 }
2998 else
2999 {
3000 intn eltSize;
3001
3002 /* get size of element */
3003 eltSize = (intn) Hlength(file_id, elmt.tag, elmt.ref);
3004 if (eltSize == FAIL)
3005 {
3006 DFdifree(GroupID);
3007 HGOTO_ERROR(DFE_BADLEN, FAIL);
3008 }
3009
3010 /* allocate buffer for conversion */
3011 buf = (uint8 *) HDmalloc((uint32) eltSize);
3012 if (buf == NULL)
3013 {
3014 DFdifree(GroupID);
3015 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3016 }
3017
3018 /* read fill value into buffer */
3019 if (Hgetelement(file_id, elmt.tag, elmt.ref, buf) == FAIL)
3020 {
3021 DFdifree(GroupID);
3022 HGOTO_ERROR(DFE_GETELEM, FAIL);
3023 }
3024
3025 /* convert the fill value */
3026 DFKconvert((VOIDP) buf, (VOIDP) sdg->fill_value,
3027 numtype, 1, DFACC_READ, 0, 0);
3028
3029 HDfree((VOIDP) buf);
3030 }
3031 break;
3032
3033 case DFTAG_SDT:
3034 FileTranspose = 1;
3035 break;
3036 default:
3037 if ((elmt.tag <= DFTAG_BREQ) && (elmt.tag >= DFTAG_EREQ))
3038 {
3039 DFdifree(GroupID);
3040 HGOTO_ERROR(DFE_BADNDG, FAIL);
3041 }
3042 break;
3043 }
3044 }
3045
3046 /* since the dataset exists, the fill value cannot be changed */
3047 sdg->fill_fixed = TRUE;
3048
3049 done:
3050 if(ret_value == FAIL)
3051 { /* Error condition cleanup */
3052
3053 } /* end if */
3054
3055 /* Normal function cleanup */
3056
3057 return ret_value;
3058 }
3059
3060 /*---------------------------------------------------------------------------*
3061 * Name: DFSDIputndg
3062 * Purpose: Write NDG out to HDF file
3063 * Inputs: file_id: HDF file pointer
3064 * ref: ref to put NDG with
3065 * sdg: struct containing NDG info to put
3066 * Returns: 0 on success, FAIL on failure with error set
3067 * Users: HDF programmers, utilities, DFSDputdata, other routines
3068 * Invokes: DFIcheck, DFdistart, DFdiadd, DFdiend, DFputelement, DFaccess,
3069 * DFwrite
3070 * Remarks: Writes out NTs
3071 *---------------------------------------------------------------------------*/
3072 static intn
DFSDIputndg(int32 file_id,uint16 ref,DFSsdg * sdg)3073 DFSDIputndg(int32 file_id, uint16 ref, DFSsdg * sdg)
3074 {
3075 int32 i;
3076 intn j;
3077 intn luf;
3078 intn issdg = 0; /* issdg=1 if it is NDG SDG */
3079 intn len;
3080 uint16 luftag;
3081 uint8 *buf;
3082 uint8 *Isscales = NULL;
3083 uint8 *bufp;
3084 uint8 ntstring[4];
3085 uint8 platnumsubclass;
3086 uint8 outNT; /* file number type subclass */
3087 int32 GroupID;
3088 int32 numtype; /* current number type */
3089 int32 fileNTsize; /* size of this NT as it will be in the file */
3090 int32 scaleNTsize; /* size of scale NT as it will be in the file */
3091 int32 aid;
3092 DFdi nt;
3093 intn ret_value = SUCCEED;
3094 CONSTR(FUNC, "DFSDIputndg");
3095
3096 HEclear();
3097
3098 /* Perform global, one-time initialization */
3099 if (library_terminate == FALSE)
3100 if(DFSDIstart()==FAIL)
3101 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3102
3103 if (!HDvalidfid(file_id))
3104 HGOTO_ERROR(DFE_BADCALL, FAIL);
3105 if (!ref)
3106 HGOTO_ERROR(DFE_BADREF, FAIL);
3107
3108 /* Check if temproray buffer has been allocated */
3109 if (ptbuf == NULL)
3110 {
3111 ptbuf = (uint8 *) HDmalloc(TBUF_SZ * sizeof(uint8));
3112 if (ptbuf == NULL)
3113 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3114 }
3115
3116 /* set number type and subclass */
3117 if (sdg->numbertype == DFNT_NONE)
3118 DFSDsetNT(DFNT_FLOAT32); /* default is float32 */
3119 numtype = sdg->numbertype;
3120 fileNTsize = DFKNTsize(numtype);
3121 scaleNTsize = fileNTsize; /* for now, assume same. MAY CHANGE */
3122 outNT = sdg->filenumsubclass;
3123 platnumsubclass = (uint8)DFKgetPNSC(numtype, (int32)DF_MT);
3124
3125 /* prepare to start writing ndg */
3126 if ((GroupID = DFdisetup(10)) < 0)
3127 HGOTO_ERROR(DFE_GROUPSETUP, FAIL);
3128
3129 /* put ND and ref */
3130 if (DFdiput(GroupID, sdg->data.tag, sdg->data.ref) < 0)
3131 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3132
3133 if (Ref.nt <= 0)
3134 { /* will not execute if has been written in putsdg */
3135 /* construct and write out NT */
3136 ntstring[0] = DFNT_VERSION; /* version */
3137 ntstring[1] = (uint8) (numtype & 0xff); /* type */
3138 ntstring[2] = (uint8) (fileNTsize * 8); /* width of number type in bits */
3139 ntstring[3] = outNT; /* class: IEEE or machine class */
3140 if (Hputelement(file_id, DFTAG_NT, ref, ntstring, (int32) 4) == FAIL)
3141 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3142 Ref.nt = (intn)ref;
3143 }
3144
3145 /* write out NDD (dimension record) */
3146 if (Ref.dims <= 0)
3147 { /* new NDD; write rank, dims, data NT and scale NTs */
3148 /* put rank & dimensions in buffer */
3149 bufp = ptbuf;
3150 UINT16ENCODE(bufp, sdg->rank);
3151 for (i = 0; i < sdg->rank; i++)
3152 INT32ENCODE(bufp, sdg->dimsizes[i]);
3153
3154 /* put data NT and scale NTs in buffer */
3155 nt.tag = DFTAG_NT;
3156 nt.ref = (uint16) Ref.nt; /* same NT for scales too */
3157
3158 /* "<=" used to put 1 data NT + rank scale NTs in buffer */
3159 for (i = 0; i <= sdg->rank; i++)
3160 { /* scale NTs written even if no scale! */
3161 UINT16ENCODE(bufp, nt.tag);
3162 UINT16ENCODE(bufp, nt.ref);
3163 }
3164 /* write out NDD record */
3165 if ( Hputelement(file_id, DFTAG_SDD, ref, ptbuf, (int32) (bufp - ptbuf)) == FAIL)
3166 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3167 Ref.dims = (intn)ref;
3168 }
3169 /* write dimension record tag/ref */
3170 if (DFdiput(GroupID, DFTAG_SDD, (uint16) Ref.dims) < 0)
3171 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3172
3173 /* write out label/unit/format */
3174 for (luf = LABEL; luf <= FORMAT; luf++)
3175 {
3176 luftag = (uint16) ((luf == LABEL) ? DFTAG_SDL :
3177 (luf == UNIT) ? DFTAG_SDU : DFTAG_SDF);
3178 bufp = ptbuf;
3179 /* this block of code checks if luf is NULL, else writes it */
3180 if (!Ref.luf[luf])
3181 { /* if luf was set */
3182 Ref.luf[luf] = -1; /* assume it is NULL */
3183
3184 /* if dataluf non-NULL, set up to write */
3185 if (sdg->dataluf[luf] && sdg->dataluf[luf][0])
3186 {
3187 HDstrcpy((char *) bufp, sdg->dataluf[luf]);
3188 bufp += HDstrlen(bufp) + 1;
3189 }
3190 else
3191 { /* dataluf NULL */
3192 *bufp++ = '\0';
3193 }
3194
3195 /* for each dimluf, if non-NULL, set up to write */
3196 for (i = 0; i < sdg->rank; i++)
3197 {
3198 if (sdg->dimluf[luf] && sdg->dimluf[luf][i]
3199 && sdg->dimluf[luf][i][0])
3200 { /* dimluf not NULL */
3201 HDstrcpy((char *) bufp, sdg->dimluf[luf][i]);
3202 bufp += HDstrlen(bufp) + 1;
3203 }
3204 else
3205 { /* dimluf NULL */
3206 *bufp++ = '\0';
3207 }
3208 } /* i loop */
3209 Ref.luf[luf] = (intn)ref; /* remember ref */
3210 if ( Hputelement(file_id, luftag, (uint16) Ref.luf[luf], ptbuf, (int32) (bufp - ptbuf)) == FAIL)
3211 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3212 } /* luf was set */
3213
3214 /* write luf tag/ref */
3215 if (Ref.luf[luf] > 0)
3216 {
3217 if (DFdiput(GroupID, luftag, (uint16) Ref.luf[luf]) < 0)
3218 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3219 }
3220 } /* luf loop */
3221
3222 /* check if there is a scale and write it out */
3223 if (!Ref.scales)
3224 { /* if scale set */
3225 Isscales = (uint8 *) HDmalloc((uint32) sdg->rank);
3226 if (Isscales == NULL)
3227 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3228 Ref.scales = (-1); /* assume there is no scale */
3229
3230 /* set up Isscales array */
3231 for (i = 0; i < sdg->rank; i++)
3232 {
3233 if (sdg->dimscales && sdg->dimscales[i])
3234 { /* a scale exists */
3235 Isscales[i] = 1;
3236 Ref.scales = 0; /* flag: write out scales */
3237 }
3238 else
3239 Isscales[i] = 0;
3240 }
3241 }
3242
3243 if (!Ref.scales)
3244 { /* write out scales */
3245 /* compute space needed for scales */
3246 len = 0;
3247 for (i = 0; i < sdg->rank; i++)
3248 {
3249 if (Isscales[i] == 1)
3250 len += (intn) (sdg->dimsizes[i] * scaleNTsize);
3251 }
3252 len += sdg->rank;
3253
3254 aid = Hstartwrite(file_id, DFTAG_SDS, ref, len);
3255 if (aid == FAIL)
3256 {
3257 HDfree((VOIDP) Isscales);
3258 HGOTO_ERROR(DFE_BADAID, FAIL);
3259 }
3260
3261 /* write Isscales */
3262 if (Hwrite(aid, (int32) sdg->rank, Isscales) == FAIL)
3263 {
3264 HDfree((VOIDP) Isscales);
3265 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
3266 }
3267
3268 /* Write scales */
3269 for (j = 0; j < sdg->rank; j++)
3270 {
3271 if (!Isscales[j])
3272 continue;
3273 if (platnumsubclass == outNT)
3274 { /* no conversion needed */
3275 if (Hwrite(aid, (int32) (fileNTsize * sdg->dimsizes[j]),
3276 (uint8 *) sdg->dimscales[j]) == FAIL)
3277 {
3278 HDfree((VOIDP) Isscales);
3279 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
3280 }
3281 }
3282 else
3283 { /* convert and write */
3284 /* allocate buffer */
3285 buf = (uint8 *) HDmalloc((uint32) (fileNTsize * sdg->dimsizes[j]));
3286 if (buf == NULL)
3287 {
3288 HDfree((VOIDP) Isscales);
3289 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3290 }
3291 /* convert, all at once */
3292 DFKconvert((VOIDP) sdg->dimscales[j], (VOIDP) buf, numtype,
3293 sdg->dimsizes[j], DFACC_WRITE, 0, 0);
3294 /* write it all out */
3295 if (Hwrite(aid, (int32) (fileNTsize * sdg->dimsizes[j]), buf)
3296 == FAIL)
3297 {
3298 HDfree((VOIDP) Isscales);
3299 HDfree((VOIDP) buf);
3300 HGOTO_ERROR(DFE_WRITEERROR, FAIL);
3301 }
3302 HDfree((VOIDP) buf);
3303 }
3304 }
3305
3306 Ref.scales = (intn)ref;
3307 Hendaccess(aid);
3308 }
3309 if (Isscales != NULL)
3310 HDfree((VOIDP) Isscales);
3311 Isscales = NULL;
3312 if (Ref.scales > 0)
3313 if (DFdiput(GroupID, DFTAG_SDS, (uint16) Ref.scales) < 0)
3314 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3315
3316 /* write coordsys */
3317 if (!sdg->coordsys || !sdg->coordsys[0])
3318 Ref.coordsys = (-1);
3319 if (!Ref.coordsys)
3320 {
3321 if ( Hputelement(file_id, DFTAG_SDC, ref, (uint8 *) sdg->coordsys, (int32) (HDstrlen(sdg->coordsys) + 1)) == FAIL)
3322 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3323 Ref.coordsys = (intn)ref;
3324 }
3325 if (Ref.coordsys > 0)
3326 {
3327 if (DFdiput(GroupID, DFTAG_SDC, (uint16) Ref.coordsys) < 0)
3328 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3329 }
3330
3331 /* write max/min */
3332 if (!Ref.maxmin)
3333 {
3334 if (platnumsubclass == outNT)
3335 { /* no conversion */
3336 if ( Hputelement(file_id, DFTAG_SDM, ref, (uint8 *) &(sdg->max_min[0]), (int32) (2 * fileNTsize)) == FAIL)
3337 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3338 Ref.maxmin = (intn)ref;
3339 }
3340 else
3341 {
3342 /* allocate buffer */
3343 buf = (uint8 *) HDmalloc((size_t) (2 * fileNTsize)); /* max/min is 8 bytes */
3344 if (buf == NULL)
3345 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3346
3347 /* convert */
3348 DFKconvert((VOIDP) &(sdg->max_min[0]), (VOIDP) buf,
3349 numtype, 2, DFACC_WRITE, 0, 0);
3350
3351 /* write */
3352 if ( Hputelement(file_id, DFTAG_SDM, ref, buf, (int32) (2 * fileNTsize)) == FAIL)
3353 {
3354 HDfree((VOIDP) buf);
3355 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3356 }
3357
3358 Ref.maxmin = (intn)ref;
3359 HDfree((VOIDP) buf);
3360 }
3361 }
3362 if (Ref.maxmin > 0)
3363 {
3364 if (DFdiput(GroupID, DFTAG_SDM, (uint16) Ref.maxmin) < 0)
3365 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3366 }
3367 Ref.maxmin = (-1); /* max/min should be reset for each data set */
3368
3369 /* Write calibration. */
3370 if (!Ref.cal)
3371 {
3372 if (platnumsubclass == outNT)
3373 { /* no conversion */
3374 if (Hputelement(file_id, DFTAG_CAL, ref,
3375 (unsigned char *) &sdg->cal,
3376 (int32) 36) < 0)
3377 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3378 Ref.cal = (intn)ref;
3379 }
3380 else
3381 {
3382 /* allocate buffer */
3383 uint8 buf2[4 * sizeof(float64) + sizeof(int32)];
3384
3385 /* convert doubles */
3386 DFKconvert((VOIDP) &sdg->cal, (VOIDP) buf2,
3387 DFNT_FLOAT64, 4, DFACC_WRITE, 0, 0);
3388
3389 /* convert int */
3390 DFKconvert((VOIDP) &sdg->cal_type, (VOIDP) (buf2 + 32),
3391 DFNT_INT32, 1, DFACC_WRITE, 0, 0);
3392
3393 /* write it into the file */
3394 if (Hputelement(file_id, DFTAG_CAL, ref,
3395 (unsigned char *) buf2, (int32) 36) < 0)
3396 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3397 Ref.cal = (intn)ref;
3398
3399 }
3400 }
3401
3402 if (Ref.cal > 0)
3403 {
3404 if (DFdiput(GroupID, DFTAG_CAL, (uint16) Ref.cal) < 0)
3405 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3406 }
3407 Ref.cal = (-1); /* Calibration should be reset for each data set */
3408
3409 /* Write fill value. */
3410 if (!Ref.fill_value)
3411 {
3412 if (platnumsubclass == outNT)
3413 { /* No conversion */
3414 if (Hputelement(file_id, DFTAG_FV, ref,
3415 (unsigned char *) sdg->fill_value,
3416 (int32) fileNTsize) == FAIL)
3417 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3418 Ref.fill_value = (intn)ref;
3419 }
3420 else
3421 {
3422 /* Allocate buffer */
3423 uint8 buf2[DFSD_MAXFILL_LEN];
3424
3425 /* Convert from native to IEEE */
3426 DFKconvert((VOIDP) sdg->fill_value, (VOIDP) buf2,
3427 numtype, 1, DFACC_WRITE, 0, 0);
3428
3429 /* Write it into the file */
3430 if (Hputelement(file_id, DFTAG_FV, ref,
3431 (unsigned char *) buf2,
3432 (int32) fileNTsize) == FAIL)
3433 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3434
3435 Ref.fill_value = (intn)ref;
3436 }
3437 }
3438
3439 /* Check to add to DFgroup */
3440 if (Ref.fill_value > 0)
3441 {
3442 if (DFdiput(GroupID, DFTAG_FV, (uint16) Ref.fill_value) == FAIL)
3443 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3444 }
3445 Ref.fill_value = (-1); /* Fill value should be reset for each data set */
3446
3447 if (!Ref.transpose)
3448 { /* if transposed, add transpose tag */
3449 if (Hdupdd(file_id, DFTAG_SDT, ref, DFTAG_SDD, ref) == FAIL)
3450 HGOTO_ERROR(DFE_DUPDD, FAIL);
3451 Ref.transpose = (intn)ref;
3452 }
3453 if (Ref.transpose > 0)
3454 {
3455 if (DFdiput(GroupID, DFTAG_SDT, (uint16) Ref.transpose) < 0)
3456 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3457 }
3458
3459 if (numtype == DFNT_FLOAT32)
3460 { /* if float32, add a DFTAG_SDLNK */
3461 DFdi lnkdd[2];
3462
3463 issdg = 1;
3464 lnkdd[0].tag = DFTAG_NDG;
3465 lnkdd[0].ref = ref;
3466 lnkdd[1].tag = DFTAG_SDG;
3467 lnkdd[1].ref = ref;
3468 bufp = ptbuf;
3469
3470 for (i = 0; i < 2; i++)
3471 {
3472 UINT16ENCODE(bufp, lnkdd[i].tag);
3473 UINT16ENCODE(bufp, lnkdd[i].ref);
3474 }
3475 if ( Hputelement(file_id, DFTAG_SDLNK, ref, ptbuf, (int32) (bufp - ptbuf)) == FAIL)
3476 HGOTO_ERROR(DFE_PUTELEM, FAIL);
3477
3478 /* write DFTAG_SDLNK */
3479 if (DFdiput(GroupID, DFTAG_SDLNK, ref) < 0)
3480 HGOTO_ERROR(DFE_PUTGROUP, FAIL);
3481 }
3482
3483 /* write out NDG */
3484 if (DFdiwrite(file_id, GroupID, DFTAG_NDG, ref) < 0)
3485 HGOTO_ERROR(DFE_GROUPWRITE, FAIL);
3486
3487 /* write an SDG point to the dataset if it is an NDG SDG */
3488 if (issdg)
3489 {
3490 if (Hdupdd(file_id, DFTAG_SDG, ref, DFTAG_NDG, ref) == FAIL)
3491 HCLOSE_GOTO_ERROR(file_id,DFE_DUPDD, FAIL);
3492 }
3493
3494 done:
3495 if(ret_value == FAIL)
3496 { /* Error condition cleanup */
3497
3498 } /* end if */
3499
3500 /* Normal function cleanup */
3501
3502 return ret_value;
3503 }
3504
3505 /*-----------------------------------------------------------------------------
3506 * Name: DFSDIendslice
3507 * Purpose: Write of data to SDG completed, write SDG and close file
3508 * Inputs: isfortran: true if called from Fortran
3509 * Returns: 0 on success, FAIL on failure with error set
3510 * Users: DFSDIputdata
3511 * Invokes: DFSDputsdg, Hclose, HERROR
3512 * Method: call DFSDputsdg, close Sfile_id
3513 * Remarks: checks that slice writes were completed.
3514 *---------------------------------------------------------------------------*/
3515 intn
DFSDIendslice(intn isfortran)3516 DFSDIendslice(intn isfortran)
3517 {
3518 intn i;
3519 intn ret_value = SUCCEED;
3520 CONSTR(FUNC, "DFSDIendslice");
3521
3522 HEclear();
3523
3524 if (Sfile_id == DF_NOFILE)
3525 HGOTO_ERROR(DFE_BADCALL, FAIL);
3526
3527 /* Perform global, one-time initialization */
3528 if (library_terminate == FALSE)
3529 if(DFSDIstart()==FAIL)
3530 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3531
3532 /* check if slice writes complete */
3533 for (i = 0; i < Writesdg.rank; i++)
3534 {
3535 if (!Fortorder && (i == 0) && (Sddims[i] == Writesdg.dimsizes[i]))
3536 continue;
3537 if ((isfortran || Fortorder) && (i == Writesdg.rank - 1)
3538 && (Sddims[i] == Writesdg.dimsizes[i]))
3539 continue;
3540 if ((isfortran || Fortorder || i > 0)
3541 && (!Fortorder || i < Writesdg.rank - 1) && (Sddims[i] == 0))
3542 continue;
3543
3544 HGOTO_ERROR(DFE_BADCALL, FAIL);
3545 }
3546
3547 if (DFSDIputndg(Sfile_id, Writeref, &Writesdg) < 0)
3548 HCLOSE_GOTO_ERROR(Sfile_id,DFE_INTERNAL,FAIL);
3549
3550 /* old nsdg table should be reset next time */
3551 if (nsdghdr != NULL)
3552 {
3553 if (nsdghdr->nsdg_t != NULL)
3554 {
3555 DFnsdgle *rear, *front;
3556
3557 rear = nsdghdr->nsdg_t;
3558 front = rear->next;
3559 while (rear != NULL)
3560 {
3561 HDfreenclear(rear);
3562 rear = front;
3563 if (rear != NULL)
3564 front = rear->next;
3565 }
3566 nsdghdr->size = 0;
3567 nsdghdr->nsdg_t = NULL;
3568 lastnsdg.tag = DFTAG_NULL;
3569 lastnsdg.ref = 0;
3570 }
3571 HDfreenclear(nsdghdr);
3572 }
3573
3574 Lastref = Writeref; /* remember ref written */
3575 Writeref = 0; /* don't know ref to write next */
3576
3577 Hendaccess(Writesdg.aid);
3578 ret_value = Hclose(Sfile_id);
3579 Sfile_id = 0; /* partial write complete */
3580 HDfreenclear(Sddims);
3581
3582 done:
3583 if(ret_value == FAIL)
3584 { /* Error condition cleanup */
3585
3586 } /* end if */
3587
3588 /* Normal function cleanup */
3589
3590 return ret_value;
3591 }
3592
3593 /******************************************************************************/
3594 /*----------------------- Internal routines ---------------------------------*/
3595 /******************************************************************************/
3596
3597 /*-----------------------------------------------------------------------------
3598 * Name: DFSDIopen
3599 * Purpose: open or reopen a file
3600 * Inputs: filename: name of file to open
3601 * acc_mode : access mode
3602 * Returns: file id on success, -1 (FAIL) on failure with error set
3603 * Users: HDF systems programmers, many SD routines
3604 * Invokes: DFopen
3605 * Remarks: This is a hook for someday providing more efficient ways to
3606 * reopen a file, to avoid re-reading all the headers
3607 *---------------------------------------------------------------------------*/
3608 int32
DFSDIopen(const char * filename,intn acc_mode)3609 DFSDIopen(const char *filename, intn acc_mode)
3610 {
3611 int32 file_id;
3612 int32 ret_value = SUCCEED;
3613 CONSTR(FUNC, "DFSDIopen");
3614
3615 /* Perform global, one-time initialization */
3616 if (library_terminate == FALSE)
3617 if(DFSDIstart()==FAIL)
3618 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3619
3620 if (Sfile_id != DF_NOFILE) /* in the middle of a partial write */
3621 HGOTO_ERROR(DFE_ALROPEN, FAIL);
3622
3623 /* if last filename buffer has not been allocated
3624 * allocate buffer for "Lastfile" and open file
3625 * else if same file as last time
3626 * use reopen - more efficient
3627 * else
3628 * open file for first time
3629 */
3630 if (Lastfile == NULL)
3631 {
3632 Lastfile = (char *) HDmalloc((DF_MAXFNLEN + 1) * sizeof(char));
3633 if (Lastfile == NULL)
3634 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3635 /* open file */
3636 if (( file_id = Hopen(filename, acc_mode, (int16) 0)) == FAIL)
3637 HGOTO_ERROR(DFE_BADOPEN, FAIL);
3638 }
3639 else if ((HDstrcmp(Lastfile, filename)) || (acc_mode == DFACC_CREATE))
3640 { /* open a new file, delete nsdg table and reset lastnsdg */
3641 if (nsdghdr != NULL)
3642 {
3643 if (nsdghdr->nsdg_t != NULL)
3644 {
3645 DFnsdgle *rear, *front;
3646
3647 rear = nsdghdr->nsdg_t;
3648 while (rear != NULL)
3649 {
3650 front = rear->next;
3651 HDfreenclear(rear);
3652 rear = front;
3653 }
3654 nsdghdr->size = 0;
3655 nsdghdr->nsdg_t = NULL;
3656 lastnsdg.tag = DFTAG_NULL;
3657 lastnsdg.ref = 0;
3658 }
3659 HDfreenclear(nsdghdr);
3660 }
3661
3662 /* treat create as different file */
3663 if (( file_id = Hopen(filename, acc_mode, (int16) 0))== FAIL)
3664 HGOTO_ERROR(DFE_BADOPEN, FAIL);
3665 Newdata = (-1); /* data in Readsdg is not fresh */
3666 Readsdg.data.ref = 0; /* No SDG read yet */
3667
3668 /* remember no info written to file */
3669 Ref.scales = (Ref.scales >= 0) ? 0 : Ref.scales;
3670 Ref.luf[LABEL] = (Ref.luf[LABEL] >= 0) ? 0 : Ref.luf[LABEL];
3671 Ref.luf[UNIT] = (Ref.luf[UNIT] >= 0) ? 0 : Ref.luf[UNIT];
3672 Ref.luf[FORMAT] = (Ref.luf[FORMAT] >= 0) ? 0 : Ref.luf[FORMAT];
3673 Ref.dims = (Ref.dims >= 0) ? 0 : Ref.dims;
3674 Ref.coordsys = (Ref.coordsys >= 0) ? 0 : Ref.coordsys;
3675 Ref.maxmin = (Ref.maxmin >= 0) ? 0 : Ref.maxmin;
3676 Ref.nt = (Ref.nt >= 0) ? 0 : Ref.nt;
3677 Ref.transpose = (Ref.transpose >= 0) ? 0 : Ref.transpose;
3678 }
3679 else
3680 {
3681 if (( file_id = Hopen(filename, acc_mode, (int16) 0))== FAIL)
3682 HGOTO_ERROR(DFE_BADOPEN, FAIL);
3683 }
3684
3685 /* if read, set up nsdg table */
3686 if (nsdghdr == NULL)
3687 {
3688 nsdghdr = (DFnsdg_t_hdr *) HDmalloc((uint32) sizeof(DFnsdg_t_hdr));
3689 if (nsdghdr == NULL)
3690 HGOTO_ERROR(DFE_NOSPACE, FAIL);
3691 nsdghdr->size = 0;
3692 nsdghdr->nsdg_t = NULL;
3693 }
3694 if ((nsdghdr->nsdg_t == NULL) && (acc_mode == DFACC_READ))
3695 {
3696 if (DFSDIsetnsdg_t(file_id, nsdghdr) < 0)
3697 HGOTO_ERROR(DFE_INTERNAL, FAIL);
3698 lastnsdg.tag = DFTAG_NULL;
3699 lastnsdg.ref = 0;
3700 }
3701
3702 HIstrncpy(Lastfile, filename, DF_MAXFNLEN);
3703 /* remember filename, so reopen may be used next time if same file */
3704
3705 ret_value = file_id;
3706
3707 done:
3708 if(ret_value == FAIL)
3709 { /* Error condition cleanup */
3710
3711 } /* end if */
3712
3713 /* Normal function cleanup */
3714
3715 return ret_value;
3716 }
3717
3718 /*-----------------------------------------------------------------------------
3719 * Name: DFSDIsdginfo
3720 * Purpose: Locates next sdg in file
3721 * Inputs: file_id: pointer to DF file
3722 * Returns: 0 on success, FAIL on failure with error set
3723 * Users: HDF systems programmers, DFSDgetdims, DFSDgetdata
3724 * Invokes: DFIfind, DFSDIgetndg
3725 * Method: Call DFIfind to find SDG, then DFSDIgetndg to read it in to Readsdg
3726 * Remarks: none
3727 *---------------------------------------------------------------------------*/
3728 intn
DFSDIsdginfo(int32 file_id)3729 DFSDIsdginfo(int32 file_id)
3730 {
3731 DFdi ptr;
3732 CONSTR(FUNC, "DFSDIsdginfo");
3733 int32 aid;
3734 intn ret_value = SUCCEED;
3735
3736 HEclear();
3737
3738 /* Perform global, one-time initialization */
3739 if (library_terminate == FALSE)
3740 if(DFSDIstart()==FAIL)
3741 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3742
3743 if (!HDvalidfid(file_id))
3744 HGOTO_ERROR(DFE_BADCALL, FAIL);
3745
3746 if (Readref != 0)
3747 {
3748 aid = Hstartread(file_id, DFTAG_NDG, Readref);
3749 if (aid != FAIL)
3750 {
3751 ptr.ref = Readref;
3752 ptr.tag = DFTAG_NDG;
3753 Hendaccess(aid);
3754 }
3755 else
3756 {
3757 aid = Hstartread(file_id, DFTAG_SDG, Readref);
3758 if (aid != FAIL)
3759 {
3760 ptr.ref = Readref;
3761 ptr.tag = DFTAG_SDG;
3762 Hendaccess(aid);
3763 }
3764 else
3765 HGOTO_ERROR(DFE_BADAID, FAIL);
3766 }
3767 }
3768 else
3769 {
3770 if (DFSDInextnsdg(nsdghdr, &ptr) < 0)
3771 HGOTO_ERROR(DFE_INTERNAL, FAIL);
3772 if ((ptr.tag != DFTAG_NDG) && (ptr.tag != DFTAG_SDG))
3773 HGOTO_ERROR(DFE_BADTAG, FAIL);
3774 if (ptr.ref == DFREF_WILDCARD)
3775 HGOTO_ERROR(DFE_BADREF, FAIL);
3776 Readref = ptr.ref;
3777 }
3778
3779 /* find next sd object */
3780 if (DFSDIgetndg(file_id, ptr.tag, ptr.ref, &Readsdg) < 0)
3781 HGOTO_ERROR(DFE_INTERNAL, FAIL);
3782
3783 /* remember what type of thing we just read */
3784 Readsdg.isndg = (ptr.tag == DFTAG_NDG) ? 1 : 0;
3785
3786 Lastref = ptr.ref; /* remember ref read */
3787 lastnsdg.tag = ptr.tag;
3788 lastnsdg.ref = ptr.ref;
3789
3790 Newdata = 1; /* now Readsdg is fresh */
3791 Readref = 0;
3792
3793 done:
3794 if(ret_value == FAIL)
3795 { /* Error condition cleanup */
3796
3797 } /* end if */
3798
3799 /* Normal function cleanup */
3800
3801 return ret_value;
3802 }
3803
3804 /*-----------------------------------------------------------------------------
3805 * Name: DFSDIrefresh
3806 * Purpose: get next sdg if Readsdg is not fresh
3807 * Inputs: filename
3808 * Returns: 0 on success, FAIL on failure with error set
3809 * Users: HDF systems programmers, functions in dfsdF.c
3810 * Invokes: DFSDIopen, DFSDIsdginfo
3811 * Method: test Newdata and Nextsdg, call DFSDIsdginfo if necessary
3812 * Remarks: none
3813 *---------------------------------------------------------------------------*/
3814 intn
DFSDIrefresh(char * filename)3815 DFSDIrefresh(char *filename)
3816 {
3817 int32 file_id;
3818 intn ret_value = SUCCEED;
3819 CONSTR(FUNC, "DFSDIrefresh");
3820
3821 HEclear();
3822
3823 /* Perform global, one-time initialization */
3824 if (library_terminate == FALSE)
3825 if(DFSDIstart()==FAIL)
3826 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3827
3828 if (Newdata != 1 || Nextsdg)
3829 { /* if Readsdg not fresh */
3830 if (( file_id = DFSDIopen(filename, DFACC_READ))== FAIL)
3831 HGOTO_ERROR(DFE_BADOPEN, FAIL);
3832 if (DFSDIsdginfo(file_id) < 0)
3833 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL, FAIL);
3834 if (Hclose(file_id) < 0)
3835 HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
3836 Nextsdg = 0;
3837 }
3838
3839 done:
3840 if(ret_value == FAIL)
3841 { /* Error condition cleanup */
3842
3843 } /* end if */
3844
3845 /* Normal function cleanup */
3846
3847 return ret_value;
3848 }
3849
3850 /*-----------------------------------------------------------------------------
3851 * Name: DFSDIisndg
3852 * Purpose: is the current read sds an sdg or nsdg/ndg
3853 * Inputs: isndg: 0 -- pure sdg( written by 3.1); 1 -- nsdg/ndg
3854 * Returns: 0 on success, FAIL on failure with error set
3855 * Users: HDF systems programmers, functions in dfsdF.c
3856 * Invokes: none
3857 * Method: Assigns Readsdg.isndg to isndg.
3858 * Remarks: none
3859 *---------------------------------------------------------------------------*/
3860 intn
DFSDIisndg(intn * isndg)3861 DFSDIisndg(intn *isndg)
3862 {
3863 intn ret_value = SUCCEED;
3864
3865 *isndg = (intn) Readsdg.isndg;
3866
3867 return ret_value;
3868 }
3869
3870 /*-----------------------------------------------------------------------------
3871 * Name: DFSDIgetrrank
3872 * Purpose: get rank of the current sdg, to transpose dims for Fortran
3873 * Inputs: &rank: address to return the rank
3874 * Returns: 0 on success, FAIL on failure with error set
3875 * Users: HDF systems programmers, functions in dfsdF.c
3876 * Invokes: none
3877 * Method: Assigns Readsdg.rank to rank.
3878 * Remarks: none
3879 *---------------------------------------------------------------------------*/
3880 intn
DFSDIgetrrank(intn * rank)3881 DFSDIgetrrank(intn *rank)
3882 {
3883 intn ret_value = SUCCEED;
3884
3885 *rank = (intn) Readsdg.rank;
3886
3887 return ret_value;
3888 }
3889
3890 /*-----------------------------------------------------------------------------
3891 * Name: DFSDIgetwrank
3892 * Purpose: get rank of the current sdg, to transpose dims for Fortran
3893 * Inputs: &rank: address to return the rank
3894 * Returns: 0 on success, FAIL on failure with error set
3895 * Users: HDF systems programmers, functions in dfsdF.c
3896 * Invokes: none
3897 * Method: Assigns Readsdg.rank to rank.
3898 * Remarks: none
3899 *---------------------------------------------------------------------------*/
3900 intn
DFSDIgetwrank(intn * rank)3901 DFSDIgetwrank(intn *rank)
3902 {
3903 intn ret_value = SUCCEED;
3904
3905 *rank = (intn) Writesdg.rank;
3906
3907 return ret_value;
3908 }
3909
3910 /*-----------------------------------------------------------------------------
3911 * Name: DFSDIclear
3912 * Purpose: Reset all "set" values, free allocated space
3913 * Inputs: sdg: pointer to sdg struct to clear
3914 * Globals: Ref
3915 * Returns: 0 on success, FAIL on error with error set
3916 * Users: HDF users, utilities, other routines
3917 * Invokes: none
3918 * Method: Release space in sdg
3919 * Remarks: none
3920 *---------------------------------------------------------------------------*/
3921 intn
DFSDIclear(DFSsdg * sdg)3922 DFSDIclear(DFSsdg * sdg)
3923 {
3924 intn i;
3925 intn luf;
3926 intn ret_value = SUCCEED;
3927 CONSTR(FUNC, "DFSDIclear");
3928
3929 HEclear();
3930
3931 /* Perform global, one-time initialization */
3932 if (library_terminate == FALSE)
3933 if(DFSDIstart()==FAIL)
3934 HGOTO_ERROR(DFE_CANTINIT, FAIL);
3935
3936 if (Sfile_id != DF_NOFILE) /* cannot clear during slice writes */
3937 HGOTO_ERROR(DFE_BADCALL, FAIL);
3938
3939 HDfreenclear(sdg->dimsizes);
3940 HDfreenclear(sdg->coordsys);
3941
3942 /* free label/unit/format pointers */
3943 for (luf = LABEL; luf <= FORMAT; luf++)
3944 {
3945 if (sdg->dimluf[luf])
3946 { /* free strings */
3947 for (i = 0; i < sdg->rank; i++)
3948 HDfreenclear(sdg->dimluf[luf][i]);
3949 }
3950
3951 /* free string pointers */
3952 HDfreenclear(sdg->dimluf[luf]);
3953
3954 /* free data string */
3955 HDfreenclear(sdg->dataluf[luf]);
3956 }
3957
3958 /* free scale pointers */
3959 if (sdg->dimscales)
3960 {
3961 for (i = 0; i < sdg->rank; i++)
3962 HDfreenclear(sdg->dimscales[i]);
3963 }
3964
3965 /* free array of scale pointers */
3966 HDfreenclear(sdg->dimscales);
3967 sdg->rank = 0;
3968
3969 /* number type is independant to dimsizes 4/7/92 sxu
3970 sdg->numbertype = DFNT_NONE;
3971 sdg->filenumsubclass = DFNTF_NONE;
3972 */
3973 sdg->aid = (int32) -1;
3974 sdg->compression = (int32) 0;
3975 FileTranspose = 0;
3976 sdg->fill_fixed = FALSE; /* allow fill_value to be changed */
3977
3978 Ref.dims = -1;
3979 Ref.scales = Ref.luf[LABEL] = Ref.luf[UNIT] = Ref.luf[FORMAT] = (-1);
3980 Ref.coordsys = Ref.maxmin = (-1);
3981 Ref.new_ndg = -1;
3982 Ref.fill_value = -1;
3983
3984 done:
3985 if(ret_value == FAIL)
3986 { /* Error condition cleanup */
3987
3988 } /* end if */
3989
3990 /* Normal function cleanup */
3991
3992 return ret_value;
3993 }
3994
3995 /*-----------------------------------------------------------------------------
3996 * Name: DFSDIgetdata
3997 * Purpose: Get data from SDG. Will sequence to next SDG if DFSDgetdims not
3998 * called.
3999 * Inputs: filename: name of HDF file to use
4000 * rank: no of dimensions of array "data"
4001 * maxsizes: actual dimensions of array "data"
4002 * data: data for returning scientific data
4003 * isfortran : 0 if called from C, 1 when called from FORTRAN
4004 * Returns: 0 on success, FAIL on failure with error set
4005 * Outputs: actual scientific data in array
4006 * Users: DFSDgetdata
4007 * Invokes: DFSDIgetslice, HDmalloc, HDfree, DFSDIopen, Hclose,
4008 * HERROR, DFSDIsdginfo
4009 * Method: Open file, call DFSDIsdginfo to read sdg if necessary, set up
4010 * window start and end arrays, call DFSDIgetslice.
4011 * Remarks: maxsizes may be larger than actual size. In that event, the actual
4012 * data may not be contiguous in the array "data"
4013 * User sets maxsizes before call.
4014 *---------------------------------------------------------------------------*/
4015 intn
DFSDIgetdata(const char * filename,intn rank,int32 maxsizes[],VOIDP data,intn isfortran)4016 DFSDIgetdata(const char *filename, intn rank, int32 maxsizes[], VOIDP data,
4017 intn isfortran)
4018 {
4019 intn i;
4020 int32 *winst;
4021 int32 *windims;
4022 int32 file_id;
4023 intn ret_value = SUCCEED;
4024 CONSTR(FUNC, "DFSDIgetdata");
4025
4026 HEclear();
4027
4028 /* Perform global, one-time initialization */
4029 if (library_terminate == FALSE)
4030 if(DFSDIstart()==FAIL)
4031 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4032
4033 if (Newdata != 1 || Nextsdg)
4034 { /* if Readsdg not fresh */
4035 if (( file_id = DFSDIopen(filename, DFACC_READ))== DF_NOFILE)
4036 HGOTO_ERROR(DFE_BADOPEN, FAIL);
4037 if (DFSDIsdginfo(file_id) < 0)
4038 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL, FAIL);
4039 if (Hclose(file_id) == FAIL)
4040 HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
4041 }
4042
4043 winst = (int32 *) HDmalloc((uint32) Readsdg.rank * sizeof(int32));
4044 if (winst == NULL)
4045 HGOTO_ERROR(DFE_NOSPACE,FAIL);
4046
4047 windims = (int32 *) HDmalloc((uint32) Readsdg.rank * sizeof(int32));
4048 if (windims == NULL)
4049 {
4050 HDfree((VOIDP) winst);
4051 HGOTO_ERROR(DFE_NOSPACE,FAIL);
4052 }
4053
4054 for (i = 0; i < rank; i++)
4055 {
4056 winst[i] = 1;
4057 windims[i] = Readsdg.dimsizes[i];
4058 }
4059
4060 ret_value = DFSDIgetslice(filename, winst, windims, data, maxsizes, isfortran);
4061 Nextsdg = 1;
4062 HDfree((VOIDP) winst);
4063 HDfree((VOIDP) windims);
4064
4065 done:
4066 if(ret_value == FAIL)
4067 { /* Error condition cleanup */
4068
4069 } /* end if */
4070
4071 /* Normal function cleanup */
4072
4073 return ret_value;
4074 }
4075
4076 /*-----------------------------------------------------------------------------
4077 * Name: DFSDIputdata
4078 * Purpose: Writes entire SDG to file
4079 * Inputs: filename: name of HDF file to use
4080 * rank: rank of data array
4081 * dimsizes: sizes of the dimensions of data array
4082 * data: array that holds data
4083 * accmode: 0 if write to new file, 1 if append to file
4084 * isfortran: 0 if C, 1 if FORTRAN
4085 * Globals: Writeref
4086 * Returns: 0 on success, FAIL on failure with error set
4087 * Users: HDF users, utilities, other routines
4088 * Invokes: DFSDIopen, Hclose, HDmalloc, HDfree, DFSDIputslice,
4089 * DFSDstartslice, DFSDIendslice
4090 * Method: Create file if necessary, allocate arrays, call slice routines
4091 *---------------------------------------------------------------------------*/
4092 intn
DFSDIputdata(const char * filename,intn rank,int32 * dimsizes,VOIDP data,intn accmode,intn isfortran)4093 DFSDIputdata(const char *filename, intn rank, int32 *dimsizes, VOIDP data,
4094 intn accmode, intn isfortran)
4095 {
4096 int32 file_id;
4097 intn ret_value = SUCCEED;
4098 CONSTR(FUNC, "DFSDIputdata");
4099
4100 HEclear();
4101
4102 /* Perform global, one-time initialization */
4103 if (library_terminate == FALSE)
4104 if(DFSDIstart()==FAIL)
4105 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4106
4107 if (!accmode)
4108 { /* new file */
4109 if (( file_id = DFSDIopen(filename, DFACC_CREATE))== DF_NOFILE)
4110 HGOTO_ERROR(DFE_BADOPEN, FAIL);
4111 if (Hclose(file_id) == FAIL)
4112 HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
4113 }
4114
4115 if (Ref.dims)
4116 { /* don't call setdims if already called */
4117 if (DFSDsetdims(rank, dimsizes) < 0)
4118 HGOTO_ERROR(DFE_INTERNAL, FAIL);
4119 }
4120
4121 if (DFSDstartslice(filename) < 0)
4122 HGOTO_ERROR(DFE_INTERNAL, FAIL);
4123
4124 if (DFSDIputslice(Writesdg.dimsizes, data, dimsizes, isfortran) < 0)
4125 HGOTO_ERROR(DFE_INTERNAL, FAIL);
4126
4127 ret_value = DFSDIendslice(isfortran);
4128
4129 done:
4130 if(ret_value == FAIL)
4131 { /* Error condition cleanup */
4132
4133 } /* end if */
4134
4135 /* Normal function cleanup */
4136
4137 return ret_value;
4138 }
4139
4140 /*----------------------------------------------------------------------------
4141 * Name: DFSDIgetslice
4142 * Purpose: Get slice of data from SDG. Will sequence to next SDG if
4143 * DFSDgetdims, DFSDgetdata or DFSDgetslice not called earlier.
4144 * Inputs: filename: name of HDF file to use
4145 * winst: array of size = rank of data, containing start of slice
4146 * windims: array of size rank, containing size of slice
4147 * data: array for returning slice
4148 * dims: dimensions of array data
4149 * isfortran : 0 if called from C, 1 when called from FORTRAN
4150 * Returns: 0 on success, FAIL on failure with error set
4151 * Outputs: slice of data in data
4152 * Users: DFSDIgetdata
4153 * Invokes: DFSDIopen, Hclose, HERROR, DFSDIsdginfo, DFaccess, DFread
4154 * Method: Open file, call DFSDIsdginfo to read sdg if necessary, read the
4155 * data, convert types if necessary, place in data as appropriate
4156 * data is assumed column major for FORTRAN, row major for C
4157 * Remarks: dims may be larger than size of slice. In that event, the actual
4158 * data may not be contiguous in the array "data".
4159 * User sets dims before call.
4160 *--------------------------------------------------------------------------*/
4161
4162 /*****************************************************************************/
4163 /* DESIGN DECISIONS */
4164 /*****************************************************************************/
4165 /*
4166 A. All stride/index/offset value will, when this is done -- refer to
4167 element counts rather than byte counts in the name of consistency.
4168
4169 B. The conversion buffers/allcated areas... will all be char buffers --
4170 providing that the Cray-2 is cooperative.
4171 */
4172 /*****************************************************************************/
4173
4174 /*****************************************************************************/
4175 /* CHANGE LOG */
4176 /*****************************************************************************/
4177 /*
4178 A.
4179 */
4180 /*****************************************************************************/
4181 intn
DFSDIgetslice(const char * filename,int32 winst[],int32 windims[],VOIDP data,int32 dims[],intn isfortran)4182 DFSDIgetslice(const char *filename, int32 winst[], int32 windims[],
4183 VOIDP data, int32 dims[], intn isfortran)
4184 {
4185 intn rank; /* number of dimensions in data[] */
4186 int32 leastsig; /* fastest varying subscript in the array */
4187 int32 error; /* flag if an error occurred, */
4188 /* used by DFconvert macro */
4189 int32 convert; /* true if machine NT != NT to be read */
4190 int32 transposed; /* true if we must transpose the data before writing */
4191 int32 done; /* true if we are at the end of the slice */
4192 int32 aid;
4193 int32 i, j; /* temporary loop index */
4194 int32 issdg; /* 1 -- pure sdg. do what HDF3.1 does */
4195 int32 *wstart; /* tmp array containing starting slice dims */
4196 int32 *wdims; /* tmp array containing the slice size */
4197 int32 *adims; /* tmp array containing the dimensions of data[] */
4198 int32 *fdims; /* tmp array containing the dimensions */
4199 /* of the dataset in the file */
4200 int32 numtype; /* current number type */
4201 int32 fileNTsize; /* size of this NT in the file */
4202 int32 localNTsize; /* size of this NT as it occurs in this machine */
4203 int32 numelements; /* number of floats to read at once */
4204 int32 readsize; /* number of bytes to read at once */
4205 int32 datastride; /* number of floats in one row of data[] */
4206 int32 *offset; /* array for accessing the next element in data[] */
4207 int32 *foffset; /* array for accessing the next element in the file */
4208 int32 *dimsleft; /* array for tracking the current position in data[] */
4209 int32 isnative;
4210 int32 fileoffset; /* offset into the current dataset in the file */
4211 uint8 platnumsubclass; /* class of this NT for this platform */
4212 uint8 fileNT; /* file number subclass */
4213 uint8 *scatterbuf; /* buffer to hold the current row contiguously */
4214 uint8 *sp; /* ptr into scatterbuf */
4215 uint8 *datap; /* ptr into data[] at starting offset */
4216 /* of current block */
4217 uint8 *dp; /* ptr into data[] at an element of the current row */
4218 uint8 *buf; /* buffer containing the converted current row */
4219 int32 file_id; /* HDF file pointer */
4220 intn ret_value = SUCCEED;
4221 CONSTR(FUNC, "DFSDIgetslice");
4222
4223 HEclear();
4224
4225 /* Perform global, one-time initialization */
4226 if (library_terminate == FALSE)
4227 if(DFSDIstart()==FAIL)
4228 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4229
4230 if (data == NULL)
4231 HGOTO_ERROR(DFE_BADPTR, FAIL);
4232
4233 if (( file_id = DFSDIopen(filename, DFACC_READ))== DF_NOFILE)
4234 HGOTO_ERROR(DFE_BADOPEN, FAIL);
4235
4236 if (Newdata != 1)
4237 { /* if Readsdg not fresh */
4238 if (DFSDIsdginfo(file_id) < 0) /* reads next SDG from file */
4239 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL, FAIL);
4240 }
4241 rank = Readsdg.rank;
4242 numtype = Readsdg.numbertype;
4243 fileNT = Readsdg.filenumsubclass;
4244 issdg = Readsdg.isndg ? 0 : 1;
4245 isnative = DFNT_NATIVE;
4246 localNTsize = DFKNTsize((numtype | isnative) & (~DFNT_LITEND));
4247 fileNTsize = DFKNTsize(numtype);
4248 platnumsubclass = (uint8)DFKgetPNSC(numtype & (~DFNT_LITEND), (int32)DF_MT);
4249
4250 /* get dimensions of slice to extract, set nwindims. also err check */
4251 for (i = 0; i < (int32) rank; i++)
4252 {
4253 /* check validity for the dimension ranges */
4254 if ((windims[i] < 1) || (winst[i] < 1)
4255 || (winst[i] + windims[i] - 1 > Readsdg.dimsizes[i]))
4256 {
4257 HCLOSE_GOTO_ERROR(file_id, DFE_BADDIM, FAIL);
4258 }
4259 /* check if space allocated is sufficient */
4260 if (dims[i] < windims[i])
4261 {
4262 HCLOSE_GOTO_ERROR(file_id, DFE_NOTENOUGH, FAIL);
4263 }
4264 }
4265 /* allocate buffers */
4266 wstart = (int32 *) HDmalloc((size_t) (4 * rank) * sizeof(int32));
4267 if (wstart == NULL)
4268 {
4269 HCLOSE_GOTO_ERROR(file_id, DFE_NOSPACE, FAIL);
4270 }
4271 wdims = wstart + rank;
4272 adims = wdims + rank;
4273 fdims = adims + rank;
4274
4275 /* copy arrays to private workspace (so that they are in row major order) */
4276 for (i = 0; i < (int32) rank; i++)
4277 {
4278 int32 ii = (issdg && isfortran) ? rank - i - 1 : i;
4279
4280 adims[i] = dims[ii];
4281 ii = (issdg && FileTranspose) ? rank - i - 1 : i;
4282 wstart[i] = winst[ii] - 1; /* translate to 0 origin */
4283 wdims[i] = windims[ii];
4284 fdims[i] = Readsdg.dimsizes[ii];
4285 }
4286
4287 convert = (fileNT != platnumsubclass); /* is conversion necessary */
4288 transposed = issdg && (isfortran ^ FileTranspose); /* is transposition needed */
4289
4290 /*
4291 * Note that if the data is transposed we must work on a row by row
4292 * basis and cannot collapse dimensions.
4293 */
4294 if (!transposed)
4295 {
4296 /* collapse dimensions if contiguous both in the file and in memory */
4297 for (i = (int32) rank - 1; i > 0; i--)
4298 { /* stop before most sig dim */
4299 if (adims[i] > wdims[i] /* not all of data[] will be filled */
4300 || wstart[i] != 0 /* reading only part of the dataset */
4301 || wdims[i] < fdims[i])
4302 {
4303 break;
4304 }
4305 wstart[i - 1] *= fdims[i];
4306 wdims[i - 1] *= wdims[i];
4307 adims[i - 1] *= adims[i];
4308 fdims[i - 1] *= fdims[i];
4309 rank--;
4310 }
4311 }
4312 leastsig = (int32) rank - 1; /* which is least sig dim */
4313
4314 /* position at start of data set */
4315 aid = Hstartread(file_id, Readsdg.data.tag, Readsdg.data.ref);
4316 if (aid == FAIL)
4317 {
4318 HDfree((VOIDP) wstart);
4319 HCLOSE_GOTO_ERROR(file_id,DFE_BADAID, FAIL);
4320 }
4321
4322 error = 0;
4323 if (rank == 1 && !convert)
4324 {
4325 /* all data is contiguous with no conversions */
4326 readsize = adims[0] * fileNTsize;
4327 if ((Hseek(aid, wstart[0] * fileNTsize, 0) == FAIL)
4328 || (readsize != Hread(aid, readsize, (uint8 *) data)))
4329 {
4330 error = 1;
4331 }
4332 }
4333 else
4334 {
4335 /*
4336 * The data must be further manipulated.
4337 * It may be transposed, may need conversion, may not be contiguous, or
4338 * any combination of these.
4339 */
4340 numelements = wdims[leastsig];
4341 readsize = numelements * fileNTsize;
4342
4343 /* allocate 1 row buffers */
4344 if (convert)
4345 {
4346 if ((buf = (uint8 *) HDmalloc((uint32) readsize)) == NULL)
4347 {
4348 HDfree((VOIDP) wstart);
4349 Hendaccess(aid);
4350 HCLOSE_GOTO_ERROR(file_id, DFE_NOSPACE, FAIL);
4351 }
4352 }
4353 else
4354 buf = NULL;
4355
4356 if (transposed)
4357 {
4358 scatterbuf =
4359 (uint8 *) HDmalloc((size_t) (numelements * localNTsize));
4360
4361 if (scatterbuf == NULL)
4362 {
4363 HDfree((VOIDP) wstart);
4364 HDfree((VOIDP) buf);
4365 Hendaccess(aid);
4366 HCLOSE_GOTO_ERROR(file_id, DFE_NOSPACE, FAIL);
4367 }
4368 }
4369 else
4370 scatterbuf = NULL;
4371
4372 offset = (int32 *) HDmalloc((size_t) (3 * rank) * sizeof(int32));
4373 if (offset == NULL)
4374 {
4375 HDfree((VOIDP) wstart);
4376 HDfree((VOIDP) buf);
4377 HDfree((VOIDP) scatterbuf);
4378 Hendaccess(aid);
4379 HCLOSE_GOTO_ERROR(file_id, DFE_NOSPACE, FAIL);
4380 }
4381 foffset = offset + rank;
4382 dimsleft = foffset + rank;
4383
4384 /* compute initial position in the data */
4385 for (i = leastsig; i >= 0; i--)
4386 dimsleft[i] = wdims[i];
4387
4388 /* compute offsets in the source array */
4389 if (transposed)
4390 {
4391 offset[0] = 1 * localNTsize;
4392 for (i = 0; i < leastsig; i++)
4393 offset[i + 1] = offset[i] * adims[leastsig - i];
4394 }
4395 else
4396 {
4397 offset[leastsig] = 1 * localNTsize;
4398 for (i = leastsig; i > 0; i--)
4399 offset[i - 1] = offset[i] * adims[i];
4400 }
4401 datastride = offset[leastsig];
4402
4403 /* compute offsets in the file */
4404 for (i = leastsig, foffset[i] = 1 * fileNTsize; i > 0; i--)
4405 foffset[i - 1] = foffset[i] * fdims[i];
4406
4407 /*
4408 * Compute starting position in file
4409 * All file reads are done relative to this starting offset.
4410 * Cumulative offset is from most sig to next to least sig dim.
4411 */
4412 for (i = 0, fileoffset = 0; i < leastsig; i++)
4413 fileoffset = (fileoffset + wstart[i]) * fdims[i + 1];
4414 fileoffset += wstart[leastsig]; /* adjust for last dim */
4415 fileoffset *= fileNTsize; /* convert to bytes */
4416
4417 datap = (uint8 *) data;
4418 done = 0;
4419 /* -- now read in the data */
4420 do
4421 {
4422 /* move to the next data element in the file */
4423 if (Hseek(aid, fileoffset, 0) == FAIL)
4424 {
4425 error = 1;
4426 break;
4427 }
4428
4429 /* read and convert one contiguous block of data */
4430 if (convert)
4431 {
4432 if (readsize != Hread(aid, readsize, buf))
4433 {
4434 error = 1;
4435 break;
4436 }
4437 DFKconvert((VOIDP) buf, transposed ? (VOIDP) scatterbuf :
4438 (VOIDP) datap, numtype, numelements, DFACC_READ, 0, 0);
4439 }
4440 else
4441 {
4442 if (readsize != Hread(aid, readsize,
4443 transposed ? scatterbuf : datap))
4444 {
4445 error = 1;
4446 break;
4447 }
4448 }
4449 if (transposed)
4450 {
4451 /* scatter out the elements of one row */
4452 for (dp = datap, sp = scatterbuf, i = 0; i < numelements; i++)
4453 {
4454 for (j = 0; j < localNTsize; j++)
4455 *(dp + j) = *(sp + j);
4456 sp += localNTsize;
4457 dp += datastride;
4458 }
4459 }
4460
4461 /*
4462 * Find starting place of the next row/block.
4463 * Note that all moves are relative:
4464 * this preserves the starting offsets of each dimension
4465 */
4466 for (i = leastsig - 1; i >= 0; i--)
4467 {
4468 if (--dimsleft[i] > 0)
4469 {
4470 /* move to next element in the current dimension */
4471 datap += offset[i];
4472 fileoffset += foffset[i];
4473 break;
4474 }
4475 else
4476 {
4477 dimsleft[i] = wdims[i];
4478 /*
4479 * Note that we are still positioned at the beginning of
4480 * the last element in the current dimension
4481 */
4482 /* move back to the beginning of dimension i */
4483 datap -= offset[i] * (wdims[i] - 1);
4484 /* move back to beginning read position of dimension i */
4485 fileoffset -= foffset[i] * (wdims[i] - 1);
4486 if (i == 0)
4487 done = 1;
4488 }
4489 }
4490 }
4491 while (!done && leastsig > 0);
4492
4493 if (buf != NULL)
4494 HDfree((VOIDP) buf);
4495 if (scatterbuf != NULL)
4496 HDfree((VOIDP) scatterbuf);
4497 if (offset != NULL)
4498 HDfree((VOIDP) offset);
4499 }
4500
4501 Hendaccess(aid);
4502 HDfree((VOIDP) wstart);
4503 if (error)
4504 {
4505 Hclose(file_id);
4506 ret_value = FAIL;
4507 }
4508 else
4509 ret_value = Hclose(file_id);
4510
4511 done:
4512 if(ret_value == FAIL)
4513 { /* Error condition cleanup */
4514
4515 } /* end if */
4516
4517 /* Normal function cleanup */
4518
4519 return ret_value;
4520 }
4521
4522 /*----------------------------------------------------------------------------
4523 * Name: DFSDIputslice
4524 * Purpose: Put slice of data to SDG.
4525 * Inputs: windims: array of size rank, containing size of slice
4526 * data: array containing slice
4527 * dims: dimensions of array data
4528 * isfortran: 0 for C, 1 for Fortran
4529 * Returns: 0 on success, FAIL on failure with error set
4530 * Users: DFSDputslice
4531 * Invokes: DFwrite, HDmalloc, HDfree,DFKnumout(if conversion
4532 required)
4533 * Method: check dimensions for contiguity, convert types if necessary
4534 * write to file
4535 * Remarks: dims may be larger than size of slice. In that event, the actual
4536 * data may not be contiguous in the array "data".
4537 * DFSDstartslice must have been called first
4538 * If DFKnumout is called, DFSDsetNT may need to have been
4539 * called
4540 * Note, writes must be contiguous - successive calls to putslice
4541 * must write out array consecutively, according to the setting
4542 * of the Fortorder variable - row major if 0, column major if 1
4543 *--------------------------------------------------------------------------*/
4544 intn
DFSDIputslice(int32 windims[],VOIDP data,int32 dims[],intn isfortran)4545 DFSDIputslice(int32 windims[], VOIDP data, int32 dims[], intn isfortran)
4546 {
4547 intn rank; /* number of dimensions in data[] */
4548 int32 leastsig; /* fastest varying subscript in the array */
4549 int32 convert; /* true if machine NT = NT to be written */
4550 int32 contiguous; /* true if there are no gaps in the data to be written */
4551 int32 numtype; /* current number type */
4552 int32 platnumsubclass; /* class of this NT for this platform */
4553 int32 fileNTsize; /* size of this NT as it will be in the file */
4554 int32 fileNT; /* class of NT for the data to write */
4555 int32 isnative;
4556 int32 localNTsize; /* size of this NT as it occurs in theis machine */
4557 int32 ret = SUCCEED; /* return code from DFwrite */
4558 int32 i, j; /* temporaries */
4559 int32 numelements; /* number of elements to write out per row */
4560 int32 writesize; /* number of bytes to write out per row */
4561 int32 datastride; /* number of bytes in one row of data[] */
4562 uint8 *datap; /* pointer into data[] at */
4563 /* the start of the current row */
4564 uint8 *buf; /* buffer containing converted current row */
4565 intn ret_value = SUCCEED;
4566 CONSTR(FUNC, "DFSDIputslice");
4567
4568 /* shut compiler up */
4569 isfortran = isfortran;
4570
4571 HEclear();
4572
4573 /* Perform global, one-time initialization */
4574 if (library_terminate == FALSE)
4575 if(DFSDIstart()==FAIL)
4576 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4577
4578 if (!data)
4579 HGOTO_ERROR(DFE_BADPTR, FAIL);
4580
4581 if (Sfile_id == DF_NOFILE)
4582 HGOTO_ERROR(DFE_BADCALL, FAIL);
4583
4584 rank = Writesdg.rank;
4585
4586 for (i = 0; i < (int32) rank; i++)
4587 {
4588 /* check validity for the dimension ranges */
4589 if ((windims[i] <= 0) || (windims[i] > Writesdg.dimsizes[i]))
4590 HGOTO_ERROR(DFE_BADDIM, FAIL);
4591
4592 /* check if space allocated is sufficient */
4593 if (dims[i] < windims[i])
4594 HGOTO_ERROR(DFE_NOTENOUGH, FAIL);
4595 }
4596
4597 /* check to see if the slices fit together */
4598 /* Same for Fortran or C */
4599 /* find the first significant dimension */
4600 for (i = 0; windims[i] == 1 && i < (int32) rank - 1; i++)
4601 /* empty */ ;
4602 /* check that all 'lesser' dims match */
4603 for (j = i + 1; j < (int32) rank; j++)
4604 {
4605 if (Writesdg.dimsizes[j] != windims[j])
4606 HGOTO_ERROR(DFE_BADDIM, FAIL);
4607 }
4608
4609 /* update Sddims to reflect new write */
4610 Sddims[i] += windims[i];
4611 for (; i > 0 && Sddims[i] >= Writesdg.dimsizes[i]; i--)
4612 {
4613 Sddims[i - 1] += Sddims[i] / Writesdg.dimsizes[i];
4614 /* promote the unit */
4615 Sddims[i] %= Writesdg.dimsizes[i];
4616 }
4617
4618 leastsig = (int32) rank - 1; /* which is least sig dim */
4619 numtype = Writesdg.numbertype;
4620
4621 /* get class of this num type for this platform */
4622 fileNT = (int32)Writesdg.filenumsubclass;
4623 isnative = DFNT_NATIVE;
4624 fileNTsize = DFKNTsize(numtype);
4625 localNTsize = DFKNTsize((numtype | isnative) & (~DFNT_LITEND));
4626 platnumsubclass = (int32)DFKgetPNSC(numtype & (~DFNT_LITEND), (int32)DF_MT);
4627 convert = (platnumsubclass != fileNT);
4628
4629 contiguous = 1;
4630 for (i = 0; contiguous && i < (int32) rank; i++)
4631 {
4632 /* check if data at the end of the users array will be contiguous */
4633 if (dims[i] > Writesdg.dimsizes[i])
4634 contiguous = 0;
4635 /* Note: if a winstart[] array is ever added, will also need */
4636 /* to check if data at start of users array will be */
4637 /* contig */
4638 }
4639
4640 /*
4641 * 2 Factors that determine how we write (in order of importance)
4642 * conversion and contiguous
4643 */
4644 datap = (uint8 *) data;
4645 if (!convert && contiguous)
4646 {
4647 /* compute total number of elements to write */
4648 for (i = 0, numelements = 1; i < (int32) rank; i++)
4649 numelements *= windims[i];
4650 writesize = numelements * fileNTsize;
4651
4652 if ( Hwrite(Writesdg.aid, writesize, (uint8 *) data) == FAIL)
4653 HCLOSE_GOTO_ERROR(Sfile_id,DFE_WRITEERROR, FAIL);
4654 }
4655 else
4656 { /* must step through the data */
4657 /* compute number of occurrences of the least sig dim */
4658 if (Fortorder)
4659 {
4660 for (i = (int32) rank - 1, j = 1; i > 0; i--)
4661 j *= windims[i];
4662 }
4663 else
4664 {
4665 for (i = 0, j = 1; i < (int32) rank - 1; i++)
4666 j *= windims[i];
4667 }
4668
4669 numelements = windims[leastsig];
4670 writesize = numelements * fileNTsize;
4671 datastride = dims[leastsig] * localNTsize;
4672 if (convert)
4673 {
4674 buf = (uint8 *) HDmalloc((uint32) writesize);
4675 if (buf == NULL)
4676 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
4677 for (i = 0; i < j; i++, datap += datastride)
4678 {
4679 DFKconvert((VOIDP) datap, (VOIDP) buf, numtype,
4680 numelements, DFACC_WRITE, 0, 0);
4681 ret = Hwrite(Writesdg.aid, writesize, buf); /* done */
4682 if (ret == FAIL)
4683 {
4684 HDfree((VOIDP) buf);
4685 HCLOSE_GOTO_ERROR(Sfile_id,DFE_WRITEERROR, FAIL);
4686 }
4687 }
4688 HDfree((VOIDP) buf);
4689 }
4690 else
4691 { /* !contiguous */
4692 for (i = 0; i < j; i++, datap += datastride)
4693 if ( Hwrite(Writesdg.aid, writesize, datap) == FAIL)
4694 HCLOSE_GOTO_ERROR(Sfile_id,DFE_WRITEERROR, FAIL);
4695 }
4696 }
4697
4698 ret_value = (ret >= 0 ? 0 : -1);
4699
4700 done:
4701 if(ret_value == FAIL)
4702 { /* Error condition cleanup */
4703
4704 } /* end if */
4705
4706 /* Normal function cleanup */
4707
4708 return ret_value;
4709 }
4710
4711 /*-----------------------------------------------------------------------------
4712 NAME
4713 DFSDgetcal
4714 USAGE
4715 int DFSDgetcal(pcal, pcal_err, pioff, pioff_err, cal_nt)
4716 float64 *pcal; OUT: calibration factor
4717 float64 *pcal_err; OUT: calibration error value
4718 float64 *pioff; OUT: uncalibrated offset value
4719 float64 *pioff_err; OUT: uncalibrated offset error value
4720 int32 *cal_nt; OUT: Nunber type of uncalibrated data
4721
4722 RETURNS
4723 Returns SUCCED(0) if successful and FAIL(-1) otherwise.
4724 DESCRIPTION
4725 This routine reads the calibration record, if there is one, attached
4726 to the scientific data set. A calibration record contains four 64-bit
4727 floating point values followed by a 32-bit integer, to be interpreted
4728 as follows:
4729
4730 cal - calibration factor
4731 cal_err - calibration error
4732 offset - uncalibrated offset
4733 offset_err - uncalibrated offset error
4734 num_type - number type of uncalibrated data
4735
4736 The relationship between a value 'iy' stored in a data set and the
4737 actual value 'y' is defined as:
4738
4739 y = cal * (iy - offset)
4740
4741 The variable "offset_err" contains a potential error of offset,
4742 and "cal_err" contains a potential error of "cal". Currently the
4743 calibration record is provided for information only. The DFSD
4744 interface performs no operations on the data based on the calibration
4745 tag.
4746
4747 ----------------------------------------------------------------------------*/
4748 intn
DFSDgetcal(float64 * pcal,float64 * pcal_err,float64 * pioff,float64 * pioff_err,int32 * cal_nt)4749 DFSDgetcal(float64 *pcal, float64 *pcal_err, float64 *pioff,
4750 float64 *pioff_err, int32 *cal_nt)
4751 {
4752 intn ret_value = SUCCEED;
4753 CONSTR(FUNC, "DFSDgetcal");
4754
4755 HEclear();
4756
4757 /* Perform global, one-time initialization */
4758 if (library_terminate == FALSE)
4759 if(DFSDIstart()==FAIL)
4760 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4761
4762 if (Newdata < 0)
4763 HGOTO_ERROR(DFE_BADCALL, FAIL);
4764
4765 if (IsCal)
4766 {
4767 *pcal = Readsdg.cal;
4768 *pcal_err = Readsdg.cal_err;
4769 *pioff = Readsdg.ioff;
4770 *pioff_err = Readsdg.ioff_err;
4771 *cal_nt = Readsdg.cal_type;
4772 ret_value = SUCCEED;
4773 }
4774 else
4775 HGOTO_ERROR(DFE_NOVALS, FAIL);
4776
4777 done:
4778 if(ret_value == FAIL)
4779 { /* Error condition cleanup */
4780
4781 } /* end if */
4782
4783 /* Normal function cleanup */
4784 return ret_value;
4785 } /* DFSDgetcal */
4786
4787 /*-----------------------------------------------------------------------------
4788 NAME
4789 DFSDsetcal
4790 USAGE
4791 intn DFSDsetcal(cal, cal_err, ioff, ioff_err, cal_nt)
4792 float64 cal; IN: calibration factor
4793 float64 cal_err; IN: calibration error
4794 float64 ioff; IN: uncalibrated offset
4795 float64 ioff_err; IN: uncalibrated offset error
4796 int32 cal_nt; IN: number type of uncalibrated data
4797 RETURNS
4798 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
4799 DESCRIPTION
4800 Sets the calibration information associated with data. This routine
4801 sets the calibration record attached to a data set. A calibration
4802 record contains four 64-bit floating point values followed by a
4803 32-bit integer, to be interpreted as follows:
4804
4805 cal - calibration factor
4806 cal_err - calibration error
4807 offset - uncalibrated offset
4808 offset_err - uncalibrated offset error
4809 num_type - number type of uncalibrated data
4810
4811 The relationship between a value 'iy' stored in a data set and the
4812 actual value 'y' is defined as:
4813
4814 y = cal * (iy - offset)
4815
4816 The variable "offset_err" contains a potential error of offset,
4817 and "cal_err" contains a potential error of "cal". Currently the
4818 calibration record is provided for information only. The DFSD
4819 interface performs no operations on the data based on the calibration
4820 tag. "DFSDsetcal" works like other "DFSDset*" routines, with one
4821 exception: the calibration information is automatically cleared
4822 after a call to "DFSDputdata" or "DFSDadddata". Hence, "DFSDsetcal"
4823 must be called anew for each data set that is to be written.
4824 ----------------------------------------------------------------------------*/
4825 intn
DFSDsetcal(float64 cal,float64 cal_err,float64 ioff,float64 ioff_err,int32 cal_nt)4826 DFSDsetcal(float64 cal, float64 cal_err, float64 ioff, float64 ioff_err,
4827 int32 cal_nt)
4828 {
4829 CONSTR(FUNC, "DFSDsetcal");
4830 intn ret_value = SUCCEED;
4831
4832 HEclear();
4833
4834 /* Perform global, one-time initialization */
4835 if (library_terminate == FALSE)
4836 if(DFSDIstart()==FAIL)
4837 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4838
4839 Writesdg.cal = (float64) cal;
4840 Writesdg.cal_err = (float64) cal_err;
4841 Writesdg.ioff = (float64) ioff;
4842 Writesdg.ioff_err = (float64) ioff_err;
4843 Writesdg.cal_type = (int32) cal_nt;
4844
4845 Ref.cal = 0;
4846
4847 done:
4848 if(ret_value == FAIL)
4849 { /* Error condition cleanup */
4850
4851 } /* end if */
4852
4853 /* Normal function cleanup */
4854 return ret_value;
4855 }
4856
4857 /*-----------------------------------------------------------------------------
4858 NAME
4859 DFSDwriteref
4860 USAGE
4861 int DFSDwriteref(filename, ref)
4862 char *filename; IN: HDF file to write to
4863 uint16 ref; IN: reference number for the next writing of data
4864 RETURNS
4865 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
4866 DESCRIPTION
4867 Specifies the data set to be written to next by using the reference
4868 number. Note that there is no gaurantee that reference numbers appear
4869 in sequence in and HDF file; therefore, it is not safe to assume
4870 that a reference number is the sequence number for a data set.
4871 -----------------------------------------------------------------------------*/
4872 intn
DFSDwriteref(const char * filename,uint16 ref)4873 DFSDwriteref(const char *filename, uint16 ref)
4874 {
4875 int32 file_id;
4876 int32 aid;
4877 intn ret_value = SUCCEED;
4878 CONSTR(FUNC, "DFSDwriteref");
4879
4880 /* Clear error stack */
4881 HEclear();
4882
4883 /* Perform global, one-time initialization */
4884 if (library_terminate == FALSE)
4885 if(DFSDIstart()==FAIL)
4886 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4887
4888 /* Open file for read access */
4889 if (( file_id = DFSDIopen(filename, DFACC_READ))== DF_NOFILE)
4890 HGOTO_ERROR(DFE_BADOPEN, FAIL);
4891
4892 /* Check for existence of SDG */
4893 if ((aid = Hstartread(file_id, DFTAG_SDG, ref)) == FAIL
4894 && (aid = Hstartread(file_id, DFTAG_NDG, ref)) == FAIL)
4895 {
4896 HCLOSE_GOTO_ERROR(file_id, DFE_NOMATCH, FAIL);
4897 }
4898
4899 /*
4900 ** Probably need to call DFSDgetndg to intialize Writesdg struct
4901 ** This is so that we use the information of an SDG that has
4902 ** already been written out. Once a SDG has been written out,
4903 ** a user should not be able to change attributes such as
4904 ** numbertype, dimensions or fill value.
4905 */
4906 if ((DFSDIgetndg(file_id, DFTAG_SDG, ref, &Writesdg) < 0)
4907 && (DFSDIgetndg(file_id, DFTAG_NDG, ref, &Writesdg) < 0))
4908 {
4909 Hendaccess(aid);
4910 HCLOSE_GOTO_ERROR(file_id, DFE_INTERNAL, FAIL);
4911 }
4912
4913 /* Close access to file, set Writeref */
4914 Hendaccess(aid);
4915 Writeref = ref;
4916 Lastref = ref;
4917
4918 ret_value = Hclose(file_id);
4919
4920 done:
4921 if(ret_value == FAIL)
4922 { /* Error condition cleanup */
4923
4924 } /* end if */
4925
4926 /* Normal function cleanup */
4927 return ret_value;
4928 }
4929
4930 /*-----------------------------------------------------------------------------
4931 NAME
4932 DFSDsetfillvalue
4933 USAGE
4934 int DFSDsetfillvalue(fill_value)
4935 VOID *fill_value; IN: number to be stored in any unwritten locations
4936 of the scientific data set
4937 RETURNS
4938 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
4939 DESCRIPTION
4940 Set the value used to fill in any unwritten location in a scientific
4941 data set. Since the data is written in hyperslabs, it is possible
4942 that not alof the possible locations in a given data set are written
4943 to. The fill value is placed into all unwritten locations. The value
4944 gets written if the following "DFSDwriteslab" call is the first
4945 call to the data set i.e. the data set is created. It is assumed that
4946 the fille value has the same number type as the data set.
4947 WARNING
4948 Memory bug on SGI's if you try to free allocated space for fill values.
4949 -----------------------------------------------------------------------------*/
4950 intn
DFSDsetfillvalue(VOIDP fill_value)4951 DFSDsetfillvalue(VOIDP fill_value)
4952 {
4953 int32 numtype; /* current number type */
4954 uint32 localNTsize; /* size of this NT on as it is on this machine */
4955 intn ret_value = SUCCEED;
4956 CONSTR(FUNC, "DFSDsetfillvalue");
4957
4958 /* Clear error stack */
4959 HEclear();
4960
4961 /* Perform global, one-time initialization */
4962 if (library_terminate == FALSE)
4963 if(DFSDIstart()==FAIL)
4964 HGOTO_ERROR(DFE_CANTINIT, FAIL);
4965
4966 /* Check to see if fill value written out already */
4967 if (Ref.fill_value == -1 && Writesdg.fill_fixed == TRUE)
4968 {
4969 HGOTO_ERROR(DFE_INTERNAL, FAIL);
4970 }
4971 else
4972 {
4973 /* Get local and file number type sizes */
4974 numtype = Writesdg.numbertype;
4975 localNTsize = (uint32)DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
4976
4977 /* Set fill value in Writesdg struct, and set fill value flag */
4978 Ref.fill_value = 0;
4979 if (HDmemcpy(Writesdg.fill_value, fill_value, localNTsize) != NULL)
4980 ret_value = SUCCEED;
4981 else
4982 ret_value = FAIL;
4983 }
4984
4985 done:
4986 if(ret_value == FAIL)
4987 { /* Error condition cleanup */
4988
4989 } /* end if */
4990
4991 /* Normal function cleanup */
4992 return ret_value;
4993 }
4994
4995 /*-----------------------------------------------------------------------------
4996 NAME
4997 DFSDgetfillvalue
4998 USAGE
4999 int DFSDgetfillvalue(fill_value)
5000 VOID *fill_value; OUT: Number to be stored in any unwritten
5001 locations of the scientific data set
5002 RETURNS
5003 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
5004 DESCRIPTION
5005 Gets the value used to fill any unwritten location in a scientific
5006 data set. The value is set by "DFSDsetfillvalue". Note that a call
5007 that initializes file information structures such as "DFSDgetdims"
5008 is required in order for "DFSDgetfillvalue" to succeed. This is because
5009 "DFSDgetfillvalue" does not take a file name as an arguement.
5010 -----------------------------------------------------------------------------*/
5011 intn
DFSDgetfillvalue(VOIDP fill_value)5012 DFSDgetfillvalue(VOIDP fill_value)
5013 {
5014 int32 numtype; /* current number type */
5015 uint32 localNTsize; /* size of this NT on as it is on this machine */
5016 intn ret_value = SUCCEED;
5017 CONSTR(FUNC, "DFSDgetfillvalue");
5018
5019 /* Clear error stack */
5020 HEclear();
5021
5022 /* Perform global, one-time initialization */
5023 if (library_terminate == FALSE)
5024 if(DFSDIstart()==FAIL)
5025 HGOTO_ERROR(DFE_CANTINIT, FAIL);
5026
5027 /* Check if Readsdg is fresh */
5028 if (Newdata < 0)
5029 HGOTO_ERROR(DFE_BADCALL, FAIL);
5030
5031 /* Get local number type size */
5032 numtype = Readsdg.numbertype;
5033 localNTsize = (uint32)DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
5034
5035 /* Set return fill value */
5036 if (HDmemcpy(fill_value, Readsdg.fill_value, localNTsize) != NULL)
5037 ret_value = SUCCEED;
5038 else
5039 ret_value = FAIL;
5040
5041 done:
5042 if(ret_value == FAIL)
5043 { /* Error condition cleanup */
5044
5045 } /* end if */
5046
5047 /* Normal function cleanup */
5048 return ret_value;
5049 }
5050
5051 /*-----------------------------------------------------------------------------
5052 NAME
5053 DFSDreadslab
5054 USAGE
5055 int DFSDreadslab(filename, start, slab_size, stride, buffer, buffer_size)
5056 char *filename; IN: name of HDF file to write to
5057 int32 start[]; IN: array of size rank containing the coordinates
5058 for the start of the slab of data
5059 int32 slab_size[]; IN: array of size rank containing the size of
5060 each dimension in the slab of data
5061 int32 stride[]; IN: sub-sampling stride(not implemented)
5062 VOIDP buffer; OUT: buffer to hold the extracted slab of data
5063 int32 buffer_size[]; OUT: array containing the dimensions of the buffer
5064 RETURNS
5065 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
5066 DESCRIPTION
5067 Reads a sub-array of data from a scientific data set. "DFSDreadslab"
5068 will sequence to the next scientific data set if "DFSDgetdims" or
5069 "DFSDgetdata" is not called earlier. The "start[]" indices are relative
5070 to 1. The rank(size) of "start[]" must be the same as the number of
5071 dimensions of the specified variable. The elements of "slab_size[]"
5072 must be no larger than the dimensions of the scientific data set.
5073 The stride feature is not currently implemented. For now just pass
5074 the "start[]" array as the arguement for "stride[]" where it will be
5075 ignored. To extract a slab of lower dimension than that of the data
5076 set, enter 1 in the "slab_size[] array for each ommitted dimension.
5077 For example, to extract a 2D slab from a 3D data set, specify the
5078 beginning coordiantes in 3 dimensions in "start[]" and enter a 1 for
5079 the for the missing dimension in the array "slab_size[]". More
5080 specifically, to extract a 3x4 slab containing the elements (6,7,8)
5081 through (8.7,11) specify the begining coordiantes as {6,7,8} and
5082 the slab size as {3,1,4}.
5083 -----------------------------------------------------------------------------*/
5084 intn
DFSDreadslab(const char * filename,int32 start[],int32 slab_size[],int32 stride[],VOIDP buffer,int32 buffer_size[])5085 DFSDreadslab(const char *filename, int32 start[], int32 slab_size[],
5086 int32 stride[], VOIDP buffer, int32 buffer_size[])
5087 {
5088 intn ret_value = SUCCEED;
5089 /* shut compiler up */
5090 stride = stride;
5091
5092 ret_value = (DFSDgetslice(filename, start, slab_size, buffer, buffer_size));
5093
5094 return ret_value;
5095 }
5096
5097 /*-----------------------------------------------------------------------------
5098 NAME
5099 DFSDstartslab
5100 USAGE
5101 int DFSDstartslab(filename)
5102 char *filename; IN: name of HDF file to write to
5103 RETURNS
5104 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
5105 DESCRIPTION
5106 Prepares the DFSD interface to write a slab(s) od data to a scientific
5107 data set. "DFSDsetdims" must be called before calling "DFSDstartslab".
5108 No call which needs to open a file may be made after a "DFSDstartslab"
5109 call until "DFSDendslab" is called. This routine will write out the
5110 fill values if "DFSDsetfillvalue" is called before this routine and
5111 this is the first write(i.e. creation) to the data set.
5112 -----------------------------------------------------------------------------*/
5113 intn
DFSDstartslab(const char * filename)5114 DFSDstartslab(const char *filename)
5115 {
5116 int32 i;
5117 int32 sdg_size;
5118 int32 localNTsize;
5119 int32 fileNTsize;
5120 int32 fill_bufsize = 16384; /* Chosen for the PC */
5121 int32 odd_size;
5122 uint8 *fill_buf;
5123 uint8 platnumsubclass;
5124 uint8 outNT; /* file number type subclass */
5125 intn ret_value = SUCCEED;
5126 CONSTR(FUNC, "DFSDstartslab");
5127
5128 /* Clear errors */
5129 HEclear();
5130
5131 /* Perform global, one-time initialization */
5132 if (library_terminate == FALSE)
5133 if(DFSDIstart()==FAIL)
5134 HGOTO_ERROR(DFE_CANTINIT, FAIL);
5135
5136 /* Check rank set i.e. DFSDsetdims() */
5137 if (!Writesdg.rank)
5138 HGOTO_ERROR(DFE_BADDIM, FAIL);
5139
5140 /* If NT not set(i.e. DFSDsetNT() not called), default to float32 */
5141 if (Writesdg.numbertype == DFNT_NONE)
5142 DFSDsetNT(DFNT_FLOAT32);
5143
5144 /* Open file */
5145 if (( Sfile_id = DFSDIopen(filename, DFACC_WRITE))== DF_NOFILE)
5146 HGOTO_ERROR(DFE_BADOPEN, FAIL);
5147
5148 /*
5149 ** Check for Writeref set i.e. DFSDwriteref() called?
5150 ** If not Writeref then we create a new Writeref i.e new SDG
5151 ** Else use existing one.
5152 */
5153 /* Set tag, ref of SDG to write */
5154 Writesdg.data.tag = DFTAG_SD;
5155 if (!Writeref)
5156 Writeref = Hnewref(Sfile_id);
5157 if (!Writeref)
5158 HGOTO_ERROR(DFE_BADREF, FAIL);
5159 Writesdg.data.ref = Writeref;
5160
5161 /* Intialize a few local variables */
5162 localNTsize = DFKNTsize((Writesdg.numbertype | DFNT_NATIVE) & (~DFNT_LITEND));
5163 fileNTsize = DFKNTsize(Writesdg.numbertype);
5164
5165 /* Calculate size of of dataset */
5166 sdg_size = fileNTsize;
5167 for (i = 0; i < Writesdg.rank; i++)
5168 sdg_size *= Writesdg.dimsizes[i];
5169
5170 /* set up to write data */
5171 Writesdg.aid = Hstartwrite(Sfile_id, DFTAG_SD, Writeref, sdg_size);
5172 if (Writesdg.aid == FAIL)
5173 HCLOSE_GOTO_ERROR(Sfile_id,DFE_BADAID, FAIL);
5174
5175 /*
5176 ** Check if fill value is set
5177 */
5178 if (!Ref.fill_value)
5179 {
5180 /* make the fill buffer smaller if possible */
5181 if (fill_bufsize > sdg_size && localNTsize == fileNTsize)
5182 fill_bufsize = sdg_size;
5183
5184 /* Allocate space for fill buffer */
5185 if ((fill_buf = (uint8 *) HDmalloc((uint32) fill_bufsize)) == NULL)
5186 {
5187 Hendaccess(Writesdg.aid);
5188 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
5189 }
5190
5191 /* Get number types and compare */
5192 outNT = Writesdg.filenumsubclass;
5193 platnumsubclass = (uint8)DFKgetPNSC(Writesdg.numbertype, (int32)DF_MT);
5194
5195 if (platnumsubclass != outNT)
5196 { /* conversion */
5197 /* Allocate buffer */
5198 uint8 buf2[DFSD_MAXFILL_LEN];
5199
5200 /* Convert from native to IEEE */
5201 DFKconvert((VOIDP)&Writesdg.fill_value, (VOIDP) buf2,
5202 Writesdg.numbertype, 1, DFACC_WRITE, 0, 0);
5203
5204 /* Intialize buffer to fill value */
5205 for (i = 0; i < fill_bufsize; i = i + localNTsize)
5206 HDmemcpy(&(fill_buf[i]), buf2, localNTsize);
5207
5208 }
5209 else /* no conversion */
5210 {
5211 /* Intialize buffer to fill value */
5212 for (i = 0; i < fill_bufsize; i = i + localNTsize)
5213 HDmemcpy(&(fill_buf[i]), Writesdg.fill_value, localNTsize);
5214 }
5215
5216
5217 /* Write fill values */
5218 if (sdg_size <= fill_bufsize)
5219 odd_size = sdg_size;
5220 else
5221 {
5222 odd_size = sdg_size % fill_bufsize;
5223 for (i = 0; i < (sdg_size / fill_bufsize); i++)
5224 { /* Write out fill buffer X times */
5225 if (Hwrite(Writesdg.aid, fill_bufsize, fill_buf) == FAIL)
5226 {
5227 Hendaccess(Writesdg.aid);
5228 HDfree((VOIDP) fill_buf);
5229 HCLOSE_GOTO_ERROR(Sfile_id,DFE_WRITEERROR, FAIL);
5230 }
5231 }
5232 }
5233 /* Write fill values for odd size piece */
5234 if (Hwrite(Writesdg.aid, odd_size, fill_buf) == FAIL)
5235 {
5236 Hendaccess(Writesdg.aid);
5237 HDfree((VOIDP) fill_buf);
5238 HCLOSE_GOTO_ERROR(Sfile_id,DFE_WRITEERROR, FAIL);
5239 }
5240
5241 Writesdg.fill_fixed = TRUE; /* fill value cannot be changed */
5242 /* Free up space */
5243 HDfree((VOIDP) fill_buf);
5244 }
5245
5246 done:
5247 if(ret_value == FAIL)
5248 { /* Error condition cleanup */
5249
5250 } /* end if */
5251
5252 /* Normal function cleanup */
5253 return ret_value;
5254 }
5255
5256 /*----------------------------------------------------------------------------
5257 NAME
5258 DFSDwriteslab
5259 USAGE
5260 int DFSDwriteslab(start, stride, count, data)
5261 int32 start[]; IN: array containing the coordinates of the start
5262 of the slab in the HDF file
5263 int32 stride[]; IN: array containing the dimensions of data[]
5264 int32 count[]; IN: array containing the size of the slab
5265 VOID *data; IN: array to hold the floating point data to write
5266 RETURNS
5267 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
5268 DESCRIPTION
5269 Writes a slab of data to a scientific data set. The "start" indices
5270 are relative to 1. The rank of "start" must be the same as the
5271 number of dimensions of the specified variable. The elements of "start"
5272 must be no larger than the scientific data set's dimensions in order.
5273 The stride feature is not currently implemented. For now just pass the
5274 "start" array as the argument for "stride" where it will be ignored.
5275 The rank of "count" must be the same as the number of dimensions of the
5276 specified variable. The elements of "count" must be no larger that
5277 the scientific data sets's dimensions in order. The order in which
5278 the data will be written into the specified hyperslab is with the
5279 last dimension varying the fastest. The array "data" should be of
5280 appropriate number type for the data set. Note that neither the
5281 compilier nor the HDF sotfware can detect if the wrong type of data
5282 is written.
5283 ----------------------------------------------------------------------------*/
5284 intn
DFSDwriteslab(int32 start[],int32 stride[],int32 count[],VOIDP data)5285 DFSDwriteslab(int32 start[], int32 stride[],
5286 int32 count[], VOIDP data)
5287 {
5288 intn rank; /* number of dimensions in data[] */
5289 int32 i; /* temporary loop index */
5290
5291 int32 leastsig; /* fastest varying subscript in the array */
5292 int32 convert; /* true if machine NT != NT to be read */
5293 int32 done; /* true if we are at the end of the slab */
5294 int32 numtype; /* current number type */
5295 int32 fileNTsize; /* size of this NT in the file */
5296 int32 localNTsize; /* size of this NT as it occurs in this machine */
5297 int32 numelements; /* number of floats to read at once */
5298 int32 sdgsize; /* number of bytes to be written in the SDG */
5299 int32 rowsize; /* number of bytes to be written at once */
5300 /* in the hyperslab */
5301 int32 fileoffset; /* offset into the current dataset in the file */
5302 int32 *doffset; /* array for accessing the next element in data[] */
5303 int32 *foffset; /* array for accessing next element in the file */
5304 int32 *dimsleft; /* array for tracking current position in data[] */
5305 int32 *startdims; /* tmp array containing starting slab dims */
5306 int32 *sizedims; /* tmp array containing the slab size */
5307 int32 *filedims; /* tmp array containing the dimensions */
5308 /* of the dataset in the file */
5309 int32 r_error; /* flag if an error occurred, */
5310 /* used by DFconvert macro */
5311 int32 aid;
5312
5313 uint8 platnumsubclass; /* class of this NT for this platform */
5314 uint8 fileNT; /* file number subclass */
5315 uint8 *buf; /* buffer containing the converted current row */
5316 uint8 *datap; /* ptr into data[] at starting offset */
5317 /* of current block */
5318 intn ret_value = SUCCEED;
5319 CONSTR(FUNC, "DFSDwriteslab");
5320
5321 /* shut compiler up */
5322 stride = stride;
5323
5324 /* Clear error stack */
5325 HEclear();
5326
5327 /* Perform global, one-time initialization */
5328 if (library_terminate == FALSE)
5329 if(DFSDIstart()==FAIL)
5330 HGOTO_ERROR(DFE_CANTINIT, FAIL);
5331
5332 /* Sanity checking of input data */
5333 if (!data)
5334 HGOTO_ERROR(DFE_BADPTR, FAIL);
5335
5336 /* Set rank */
5337 rank = Writesdg.rank;
5338
5339 /* Do sanity checking of starting and size dimension arrays */
5340 for (i = 0; i < (int32) rank; i++)
5341 {
5342 /*
5343 ** Check validity for the dimension ranges by
5344 ** checking lower bound of slab sizes
5345 ** checking lower bound of starting dimensions
5346 ** checking upper bound on writing dimensions
5347 */
5348 if ((count[i] < 1) || (start[i] < 1)
5349 || (start[i] + count[i] - 1 > Writesdg.dimsizes[i]))
5350 HCLOSE_GOTO_ERROR(Sfile_id,DFE_BADDIM, FAIL);
5351 }
5352
5353 /* Intialize a few local variables */
5354 numtype = Writesdg.numbertype;
5355 platnumsubclass = (uint8)DFKgetPNSC(numtype & (~DFNT_LITEND), DF_MT);
5356 localNTsize = DFKNTsize((numtype | DFNT_NATIVE) & (~DFNT_LITEND));
5357 fileNTsize = DFKNTsize(numtype);
5358 fileNT = Writesdg.filenumsubclass;
5359
5360 /* Calculate total bytes in SDS that can be written */
5361 sdgsize = fileNTsize;
5362 for (i = 0; i < Writesdg.rank; i++)
5363 sdgsize *= Writesdg.dimsizes[i];
5364
5365 /* Set Access Id */
5366 aid = Writesdg.aid;
5367
5368 /*
5369 ** Get dimensions of hyperslab to write out
5370 ** Allocate temporary buffers(3) to hold starting, size,
5371 ** and file(SDG in file) dimensions
5372 */
5373 startdims = (int32 *) HDmalloc((size_t) (3 * rank) * sizeof(int32));
5374 if (startdims == NULL)
5375 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
5376 sizedims = startdims + rank;
5377 filedims = sizedims + rank;
5378
5379 /* Copy arrays to private workspace (row major order) */
5380 for (i = 0; i < (int32) rank; i++)
5381 {
5382 startdims[i] = start[i] - 1;
5383 sizedims[i] = count[i]; /* dimensions of just slab */
5384 filedims[i] = Writesdg.dimsizes[i]; /* dimensions of whole SDG */
5385 }
5386
5387 /* Is conversion necessary */
5388 convert = (fileNT != platnumsubclass);
5389
5390 /* Collapse dimensions if contiguous both in the file and in memory */
5391 for (i = (int32) rank - 1; i > 0; i--) /* stop before most sig dim */
5392 {
5393 /* read only part of dataset */
5394 if (startdims[i] != 0 || sizedims[i] < filedims[i])
5395 break;
5396 startdims[i - 1] *= filedims[i];
5397 sizedims[i - 1] *= sizedims[i];
5398 filedims[i - 1] *= filedims[i];
5399 rank--;
5400 }
5401
5402 /*
5403 ** Which is least sig dim i.e fastest varying.
5404 ** In C usually the last.
5405 */
5406 leastsig = (int32) rank - 1;
5407
5408 r_error = 0;
5409 if (rank == 1 && !convert)
5410 {
5411 /* all data is contiguous with no conversions */
5412 rowsize = sizedims[0] * fileNTsize;
5413 if ((Hseek(aid, startdims[0] * fileNTsize, 0) == FAIL)
5414 || (rowsize != Hwrite(aid, rowsize, (uint8 *) data)))
5415 {
5416 r_error = 1;
5417 }
5418 }
5419 else
5420 {
5421 /*
5422 * The data must be further manipulated.
5423 * It may need conversion, may not be contiguous, or
5424 * any combination of these.
5425 */
5426 numelements = sizedims[leastsig]; /* # of elmenents in a row */
5427 rowsize = numelements * fileNTsize; /* # of bytes in a row */
5428
5429 /* If conversion, allocate 1 row buffers */
5430 if (convert)
5431 {
5432 if ((buf = (uint8 *) HDmalloc((uint32) rowsize)) == NULL)
5433 {
5434 HDfree((VOIDP) startdims);
5435 Hendaccess(aid);
5436 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
5437 }
5438 }
5439 else
5440 buf = NULL;
5441
5442 /* Allocate space for file and data offsets and dimsleft */
5443 foffset = (int32 *) HDmalloc((size_t) (3 * rank) * sizeof(int32));
5444 if (foffset == NULL)
5445 {
5446 HDfree((VOIDP) startdims);
5447 HDfree((VOIDP) buf);
5448 Hendaccess(aid);
5449 HCLOSE_GOTO_ERROR(Sfile_id,DFE_NOSPACE, FAIL);
5450 }
5451 dimsleft = foffset + rank;
5452 doffset = dimsleft + rank;
5453
5454 /* Set number of dimensions left */
5455 for (i = leastsig; i >= 0; i--)
5456 dimsleft[i] = sizedims[i];
5457
5458 /* compute offsets in the source array */
5459 doffset[leastsig] = 1 * localNTsize;
5460 for (i = leastsig; i > 0; i--)
5461 doffset[i - 1] = doffset[i] * sizedims[i];
5462
5463 /*
5464 ** Compute offsets in the file for dimension, according to the
5465 ** possible length for each dimension. Depends on numbertype.
5466 */
5467 for (i = leastsig, foffset[i] = 1 * fileNTsize; i > 0; i--)
5468 foffset[i - 1] = foffset[i] * filedims[i];
5469
5470 /*
5471 ** Compute starting position in file
5472 ** All file writes are done relative to this starting offset.
5473 ** Cumulative offset is from most sig to next to least sig dim.
5474 */
5475 for (i = 0, fileoffset = 0; i < leastsig; i++)
5476 fileoffset = fileoffset + (startdims[i] * foffset[i]);
5477
5478 /* Dont forget about last dimension */
5479 fileoffset = fileoffset + startdims[leastsig] * fileNTsize;
5480
5481 datap = (uint8 *) data;
5482 done = 0;
5483
5484 /* -- now write the data */
5485 do
5486 {
5487 /* move to the next data element in the file */
5488 if (Hseek(aid, fileoffset, 0) == FAIL)
5489 {
5490 r_error = 1;
5491 break;
5492 }
5493
5494 /* If convert and write one contiguous block of data */
5495 /* Else write one contiguous block of data */
5496 if (convert)
5497 {
5498 DFKconvert((VOIDP) datap, (VOIDP) buf, numtype,
5499 numelements, DFACC_WRITE, 0, 0);
5500 if (rowsize != Hwrite(aid, rowsize, buf))
5501 {
5502 r_error = 1;
5503 break;
5504 }
5505 }
5506 else
5507 {
5508 if (rowsize != Hwrite(aid, rowsize, datap))
5509 {
5510 r_error = 1;
5511 break;
5512 }
5513 }
5514
5515 /*
5516 * Find starting place of the next row/block.
5517 * Note that all moves are relative:
5518 * this preserves the starting offsets of each dimension
5519 */
5520 for (i = leastsig - 1; i >= 0; i--)
5521 {
5522 if (--dimsleft[i] > 0)
5523 {
5524 /* Move to next element in the current dimension */
5525 datap += doffset[i];
5526 fileoffset += foffset[i];
5527 break;
5528 }
5529 else
5530 {
5531 dimsleft[i] = sizedims[i];
5532 /*
5533 * Note that we are still positioned at the beginning of
5534 * the last element in the current dimension
5535 */
5536 /* move back to the beginning of dimension i */
5537 datap -= doffset[i] * (sizedims[i] - 1);
5538
5539 /* move back to beginning read position of dimension i */
5540 fileoffset -= foffset[i] * (sizedims[i] - 1);
5541 if (i == 0)
5542 done = 1;
5543 }
5544 }
5545 }
5546 while (!done && leastsig > 0);
5547
5548 if (buf != NULL)
5549 HDfree((VOIDP) buf);
5550 if (foffset != NULL)
5551 HDfree((VOIDP) foffset);
5552 }
5553
5554 /* Clean up time.... */
5555 HDfree((VOIDP) startdims);
5556
5557 if (r_error)
5558 ret_value = FAIL;
5559 else
5560 ret_value = SUCCEED;
5561
5562 done:
5563 if(ret_value == FAIL)
5564 { /* Error condition cleanup */
5565
5566 } /* end if */
5567
5568 /* Normal function cleanup */
5569 return ret_value;
5570 }
5571
5572 /*-----------------------------------------------------------------------------
5573 NAME
5574 DFSDendslab
5575 USAGE
5576 int DFSDendslab()
5577
5578 RETURNS
5579 Returns SUCCEED(0) if successful and FAIL(-1) otherwise.
5580 DESCRIPTION
5581 Ends a sequence of slab calls started by "DFSDstartslab" by closing
5582 the file. Writes the NDG information to the file if this call follows
5583 a "DFSDstartslab" that created a new SDG.
5584
5585 ----------------------------------------------------------------------------*/
5586 intn
DFSDendslab(void)5587 DFSDendslab(void)
5588 {
5589 intn ret_value = SUCCEED;
5590 CONSTR(FUNC, "DFSDendslab");
5591
5592 /* Clear error stack */
5593 HEclear();
5594
5595 /* Perform global, one-time initialization */
5596 if (library_terminate == FALSE)
5597 if(DFSDIstart()==FAIL)
5598 HGOTO_ERROR(DFE_CANTINIT, FAIL);
5599
5600 /* Valid file id */
5601 if (Sfile_id == DF_NOFILE)
5602 HGOTO_ERROR(DFE_BADCALL, FAIL);
5603
5604 /* Check to see if we have written out the SDG info */
5605 if (!Ref.new_ndg)
5606 {
5607 if (DFSDIputndg(Sfile_id, Writeref, &Writesdg) < 0)
5608 HCLOSE_GOTO_ERROR(Sfile_id,DFE_INTERNAL, FAIL);
5609
5610 /* old nsdg table should be reset next time */
5611 if (nsdghdr != NULL)
5612 {
5613 if (nsdghdr->nsdg_t != NULL)
5614 {
5615 DFnsdgle *rear, *front;
5616
5617 rear = nsdghdr->nsdg_t;
5618 front = rear->next;
5619 while (rear != NULL)
5620 {
5621 HDfreenclear(rear);
5622 rear = front;
5623 if (rear != NULL)
5624 front = rear->next;
5625 }
5626 nsdghdr->size = 0;
5627 nsdghdr->nsdg_t = NULL;
5628 lastnsdg.tag = DFTAG_NULL;
5629 lastnsdg.ref = 0;
5630 }
5631
5632 HDfreenclear(nsdghdr);
5633 }
5634
5635 Ref.new_ndg = -1;
5636 }
5637
5638 /* Slab clean up */
5639 Hendaccess(Writesdg.aid);
5640 ret_value = Hclose(Sfile_id);
5641 Sfile_id = 0;
5642 Lastref = (uint16) Writeref; /* remember ref written */
5643 Writeref = 0; /* Reset Write ref */
5644
5645 done:
5646 if(ret_value == FAIL)
5647 { /* Error condition cleanup */
5648
5649 } /* end if */
5650
5651 /* Normal function cleanup */
5652 return ret_value;
5653 }
5654
5655 /*--------------------------------------------------------------------------
5656 NAME
5657 DFSDIstart
5658 PURPOSE
5659 DFSD-level initialization routine
5660 USAGE
5661 intn DFSDIstart()
5662 RETURNS
5663 Returns SUCCEED/FAIL
5664 DESCRIPTION
5665 Register the shut-down routine (DFSDPshutdown) for call with atexit
5666 GLOBAL VARIABLES
5667 COMMENTS, BUGS, ASSUMPTIONS
5668 EXAMPLES
5669 REVISION LOG
5670 --------------------------------------------------------------------------*/
DFSDIstart(void)5671 PRIVATE intn DFSDIstart(void)
5672 {
5673 CONSTR(FUNC, "DFSDIstart"); /* for HERROR */
5674 intn ret_value = SUCCEED;
5675
5676 /* Don't call this routine again... */
5677 library_terminate = TRUE;
5678
5679 /* Install atexit() library cleanup routine */
5680 if (HPregister_term_func(&DFSDPshutdown) != 0)
5681 HGOTO_ERROR(DFE_CANTINIT, FAIL);
5682
5683 done:
5684 if(ret_value == FAIL)
5685 { /* Error condition cleanup */
5686
5687 } /* end if */
5688
5689 /* Normal function cleanup */
5690
5691 return(ret_value);
5692 } /* end DFSDIstart() */
5693
5694 /*--------------------------------------------------------------------------
5695 NAME
5696 DFSDPshutdown
5697 PURPOSE
5698 Terminate various static buffers.
5699 USAGE
5700 intn DFSDshutdown()
5701 RETURNS
5702 Returns SUCCEED/FAIL
5703 DESCRIPTION
5704 Free various buffers allocated in the DFSD routines.
5705 GLOBAL VARIABLES
5706 COMMENTS, BUGS, ASSUMPTIONS
5707 Should only ever be called by the "atexit" function HDFend
5708 EXAMPLES
5709 REVISION LOG
5710 --------------------------------------------------------------------------*/
DFSDPshutdown(void)5711 intn DFSDPshutdown(void)
5712 {
5713 DFSDIclear(&Readsdg);
5714 DFSDIclear(&Writesdg);
5715
5716 /* old nsdg table should be reset next time */
5717 if (nsdghdr != NULL)
5718 {
5719 if (nsdghdr->nsdg_t != NULL)
5720 {
5721 DFnsdgle *rear, *front;
5722
5723 rear = nsdghdr->nsdg_t;
5724 front = rear->next;
5725 while (rear != NULL)
5726 {
5727 HDfree(rear);
5728 rear = front;
5729 if (rear != NULL)
5730 front = rear->next;
5731 }
5732 lastnsdg.tag = DFTAG_NULL;
5733 lastnsdg.ref = 0;
5734 }
5735 HDfreenclear(nsdghdr);
5736 }
5737
5738 if(ptbuf!=NULL)
5739 {
5740 HDfree(ptbuf);
5741 ptbuf=NULL;
5742 } /* end if */
5743
5744 if(Lastfile!=NULL)
5745 {
5746 HDfree(Lastfile);
5747 Lastfile=NULL;
5748 } /* end if */
5749 return(SUCCEED);
5750 } /* end DFSDPshutdown() */
5751
5752