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