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 - mfsd.c
18 
19   This file contains the HDF/netCDF based multi-file interface for SDSs
20 
21   All of the routines that make up this interface have names beginning
22   with SD.  Routines beginning with SDI are internal routines and
23   should not be used outside of this module.
24 
25   Defining SDDEBUG will print status messages to stderr
26 
27 SD interface:
28 ------------------
29 
30     --- open a file ---
31 fid    = SDstart(file name, access);
32 
33         --- get number of data sets and number of attributes in the file ---
34 status = SDfileinfo(fid, *n_datasets, *n_attrs);
35 
36     --- select a data set for access ---
37 sdsid  = SDselect(fid, i, ...);   0 <= i < n_datasets
38 
39         --- return the name, rank, dimsizes, #of attr, datatype ---
40 status = SDgetinfo(sdsid, ...);
41 
42 status = SDreaddata(sdsid, ...);
43 
44 status = SDgetrange(sdsid, ...);
45 
46 status = SDend(fid);
47 
48 status = SDisdimval_bwcomp(dimid);
49 
50     --- check whether a data set is empty
51 status = SDcheckempty(sdsid, ...);
52 
53         --- retrieve the compression information of an SDS
54 status = SDgetcompinfo(sdsid, ...);
55 
56         --- retrieve the compression method of an SDS
57 status = SDgetcomptype(sdsid, ...);
58 
59         --- retrieve the compressed and uncompressed sizes of an SDS' data
60 status = SDgetdatasize(sdsid, ...);
61 
62         --- take an id and determine if it is an SD id, SDS id, dim id, ---
63         --- or none of the above ---
64 id_type = SDidtype(an_id);
65 
66     --- reset the maximum number of files can be opened at a time.
67 max_files = SDreset_maxopenfiles(req_max);
68 
69     --- retrieve the current number of opened files allowed in HDF and
70     --- the maximum number of opened files allowed on a system.
71 status = SDget_maxopenfiles(&curr_max, &sys_limit);
72 
73     --- return the number of files currently being opened.
74 num_files = SDget_numopenfiles();
75 
76     --- get the number of variables in the file having the given name.
77 status = SDgetnumvars_byname(fid,...);
78 
79     --- map a dataset name to an index.
80 index = SDnametoindex(int32 fid,...);
81 
82     --- retrieve a list of variables having the given name.
83 status = SDnametoindices(fid,...);
84 
85 NOTE: This file needs to have the comments cleaned up for most of the
86        functions here. -GV 9/10/97
87 
88 ******************************************************************************/
89 
90 #include "local_nc.h"
91 
92 #ifdef HDF
93 #include "mfhdf.h"
94 #include "hfile.h"
95 
96 #ifdef H4_HAVE_LIBSZ          /* we have the szip library */
97 #include "szlib.h"
98 #ifndef MIN
99 #define MIN(a,b)    (((a)<(b)) ? (a) : (b))
100 #endif
101 #endif
102 /* for Chunk debugging */
103 /*
104 #define CHK_DEBUG
105 */
106 
107 #ifndef MFSD_INTERNAL
108 #define MFSD_INTERNAL
109 #endif
110 
111 #ifdef MFSD_INTERNAL
112 /* Private function prototypes */
113 #include "mfprivate.h"
114 #endif
115 
116 /* Whether we've installed the library termination function yet for this interface */
117 PRIVATE intn library_terminate = FALSE;
118 
119 #ifdef MFSD_INTERNAL
120 /******************************************************************************
121  NAME
122     SDIhandle_from_id -- get the handle from this object
123 
124  DESCRIPTION
125     Map an ID to the handle for this file
126 
127  RETURNS
128     NULL or the handle
129 
130 ******************************************************************************/
131 NC *
SDIhandle_from_id(int32 id,intn typ)132 SDIhandle_from_id(int32 id, /* IN: an object (file, dim, dataset) ID */
133                   intn  typ /* IN: IN: the type of ID this is */)
134 {
135     CONSTR(FUNC, "SDIhandle_from_id");    /* for HGOTO_ERROR */
136     int32 tmp;
137     NC   *ret_value = NULL;
138 
139     /* check that it is the proper type of id */
140     tmp = (id >> 16) & 0x0f;
141     if(tmp != typ)
142     HGOTO_ERROR(DFE_ARGS, NULL);
143 
144     /* get the file from top 12 bits*/
145     tmp = (id >> 20) & 0xfff;
146     ret_value = NC_check_id((int)tmp);
147 
148 done:
149     if (ret_value == NULL)
150       { /* Failure cleanup */
151 
152       }
153     /* Normal cleanup */
154 
155     return ret_value;
156 } /* SDIhandle_from_id */
157 
158 
159 /******************************************************************************
160  NAME
161     SDIget_var -- get the variable record
162 
163  DESCRIPTION
164     Map an ID and a handle to the NC_var object for this dataset
165 
166  RETURNS
167     NULL or the variable object
168 
169 ******************************************************************************/
170 NC_var *
SDIget_var(NC * handle,int32 sdsid)171 SDIget_var(NC   *handle, /* IN: the handle for this file */
172            int32 sdsid   /* IN: a dataset ID */)
173 {
174     CONSTR(FUNC, "SDIget_var");    /* for HGOTO_ERROR */
175     int32      varid;
176     NC_array **ap = NULL;
177     NC_var    *ret_value = NULL;
178 
179     /* varid is low 16bits of sdsid */
180     varid = sdsid & 0xffff;
181 
182     if(handle->vars != NULL
183        && varid >= 0
184        && varid < handle->vars->count)
185       {
186         ap = (NC_array **)handle->vars->values;
187         ap += varid;
188       }
189     else
190     HGOTO_ERROR(DFE_ARGS, NULL);
191 
192     ret_value = ((NC_var *)*ap);
193 
194 done:
195     if (ret_value == NULL)
196       { /* Failure cleanup */
197 
198       }
199     /* Normal cleanup */
200 
201     return ret_value;
202 } /* SDIget_var */
203 
204 
205 /******************************************************************************
206  NAME
207     SDIget_dim -- get the dimension record
208 
209  DESCRIPTION
210     Map an ID and a handle to the NC_dim object for this dimension
211 
212  RETURNS
213     NULL or the variable object
214 
215 ******************************************************************************/
216 NC_dim *
SDIget_dim(NC * handle,int32 id)217 SDIget_dim(NC   *handle,/* IN: the handle for this file */
218            int32 id     /* IN: a dimension ID */)
219 {
220     CONSTR(FUNC, "SDIget_dim");    /* for HGOTO_ERROR */
221     int32      dimindex;
222     NC_array **ap = NULL;
223     NC_dim    *ret_value = NULL;
224 
225     /* dimindex is low 16bits of id */
226     dimindex = id & 0xffff;
227 
228     if(handle->dims != NULL
229        && dimindex >= 0
230        && dimindex < handle->dims->count)
231       {
232         ap = (NC_array **)handle->dims->values;
233         ap += dimindex;
234       }
235     else
236     HGOTO_ERROR(DFE_ARGS, NULL);
237 
238     ret_value = ((NC_dim *)*ap);
239 
240 done:
241     if (ret_value == NULL)
242       { /* Failure cleanup */
243 
244       }
245     /* Normal cleanup */
246 
247     return ret_value;
248 } /* SDIget_dim */
249 #endif /* MFSD_INTERNAL */
250 
251 /******************************************************************************
252  NAME
253     SDIstart -- initialize the SD interface
254 
255  DESCRIPTION
256     Register the atexit callback function, etc.
257 
258  RETURNS
259     SUCCEED/FAIL
260 ******************************************************************************/
261 static intn
SDIstart(void)262 SDIstart(void)
263 {
264     CONSTR(FUNC, "SDIstart");    /* for HGOTO_ERROR */
265     intn ret_value = SUCCEED;
266 
267     /* Don't call this routine again... */
268     library_terminate = TRUE;
269 
270     /* Install atexit() library cleanup routine */
271     if (HPregister_term_func(&SDPfreebuf) != 0)
272           HGOTO_ERROR(DFE_CANTINIT, FAIL);
273 
274 done:
275     if(ret_value == FAIL)
276     { /* Error condition cleanup */
277 
278     } /* end if */
279 
280     /* Normal function cleanup */
281     return(ret_value);
282 } /* end SDIstart() */
283 
284 #ifdef MFSD_INTERNAL
285 
286 /******************************************************************************
287  NAME
288     SDI_can_clobber -- check permission on the file
289 
290  DESCRIPTION
291     Check the file permissions.  If OK to clobber the file, return 1,
292     else return 0.
293     Called by SDstart.
294 
295  RETURNS
296     1 if OK to clobber
297     0 if not OK to overwrite
298 
299 ******************************************************************************/
SDI_can_clobber(const char * name)300 int SDI_can_clobber(const char *name)
301 {
302     int res;
303     struct stat buf;
304     FILE *ff;
305 
306     res = stat(name, &buf);
307 
308     if (res < 0) {
309         /* no such file, OK to try to create it */
310     return(1);
311     }
312 
313     ff = HI_OPEN(name, DFACC_RDWR);
314 
315     if (ff != NULL) {
316         /* OK to open for write, so OK to clobber it */
317         HI_CLOSE(ff);
318     return(1);
319     }
320 
321     /* no permission to write, don't do the create */
322     return(0);
323 }
324 #endif /* MFSD_INTERNAL */
325 
326 /******************************************************************************
327  NAME
328     SDstart -- open a file
329 
330  DESCRIPTION
331     Open a file by calling ncopen() or nccreate() and return a
332     file ID to the file.
333 
334  RETURNS
335     A file ID or FAIL
336 
337 ******************************************************************************/
338 int32
SDstart(const char * name,int32 HDFmode)339 SDstart(const char *name,   /* IN: file name to open */
340         int32       HDFmode /* IN: access mode to open file with */)
341 {
342     CONSTR(FUNC, "SDstart");    /* for HGOTO_ERROR */
343     intn    cdfid;
344     int32   fid;
345     intn    NCmode;
346     NC     *handle = NULL;
347     int32   ret_value = SUCCEED;
348 
349 #ifdef SDDEBUG
350     fprintf(stderr, "SDstart: I've been called\n");
351 #endif
352 
353     /* clear error stack */
354     HEclear();
355 
356     /* turn off annoying crash on error stuff */
357     ncopts = 0;
358 
359     /* Perform global, one-time initialization */
360     if (library_terminate == FALSE)
361         if(SDIstart()==FAIL)
362             HGOTO_ERROR(DFE_CANTINIT, FAIL);
363 
364     /* check access mode */
365     if(HDFmode & DFACC_WRITE)
366         NCmode = NC_RDWR;
367     else
368         NCmode = NC_NOWRITE;
369 
370     if(HDFmode & DFACC_CREATE)
371       { /* create file */
372         if(!SDI_can_clobber(name))
373             HGOTO_ERROR(DFE_DENIED, FAIL);
374         cdfid = nccreate(name, NC_CLOBBER);
375       }
376     else
377       { /* open the file */
378         cdfid = ncopen(name, NCmode);
379       }
380 
381     /* check if bad create/open */
382     if(cdfid == -1)
383     {
384         /* catch what's on the stack; this is to catch specific error code,
385            when the failure was due to "too many open files" -BMR- 2006/11/1 */
386         int16 err = HEvalue(1);
387         HGOTO_ERROR(err, FAIL);
388     }
389 
390     /* hmm.....*/
391     handle = NC_check_id(cdfid);
392     if(handle == NULL)
393         HGOTO_ERROR(DFE_ARGS, FAIL);
394 
395     /* set in 'define' mode? */
396     handle->flags &= ~(NC_INDEF);
397 
398     /* create file id to return */
399     fid = (((int32) cdfid) << 20) + (((int32) CDFTYPE) << 16) + cdfid;
400 
401     ret_value = fid;
402 
403 done:
404     if (ret_value == FAIL)
405       { /* Failure cleanup */
406 
407       }
408     /* Normal cleanup */
409 
410 
411     return ret_value;
412 } /* SDstart */
413 
414 
415 /******************************************************************************
416  NAME
417     SDend -- close a file
418 
419  DESCRIPTION
420     Close the file
421 
422  RETURNS
423     SUCCEED / FAIL
424 
425 ******************************************************************************/
426 intn
SDend(int32 id)427 SDend(int32 id /* IN: file ID of file to close */)
428 {
429     CONSTR(FUNC, "SDend");    /* for HGOTO_ERROR */
430     intn  cdfid;
431     NC   *handle = NULL;
432     intn  ret_value = SUCCEED;
433 
434 #ifdef SDDEBUG
435     fprintf(stderr, "SDend: I've been called\n");
436 #endif
437 
438     /* clear error stack */
439     HEclear();
440 
441     /* get id? */
442     cdfid = (intn)id & 0xffff;
443 
444 #ifndef SYNC_ON_EACC
445 
446     /* get the handle */
447     handle = SDIhandle_from_id(id, CDFTYPE);
448     if(handle == NULL)
449     HGOTO_ERROR(DFE_ARGS, FAIL);
450 
451     /* make sure we can write to the file */
452     if(handle->flags & NC_RDWR)
453       {
454 
455         handle->xdrs->x_op = XDR_ENCODE;
456 
457         /* see if the meta-data needs to be updated */
458         if(handle->flags & NC_HDIRTY)
459           {
460             if(!xdr_cdf(handle->xdrs, &handle))
461             HGOTO_ERROR(DFE_XDRERROR, FAIL);
462 
463             handle->flags &= ~(NC_NDIRTY | NC_HDIRTY);
464           }
465         else
466           {
467 
468             /* see if the numrecs info needs updating */
469               if(handle->flags & NC_NDIRTY)
470                 {
471                     if(!xdr_numrecs(handle->xdrs, handle))
472                       {
473                          HGOTO_ERROR(DFE_XDRERROR, FAIL);
474                       }
475 
476                     if (handle->file_type != HDF_FILE)
477                         handle->flags &= ~(NC_NDIRTY);
478                 }
479           }
480       }
481 
482 #endif /* SYNC_ON_EACC */
483 
484     /* call netCDF close */
485     ret_value = ncclose(cdfid);
486 
487 done:
488     if (ret_value == FAIL)
489       { /* Failure cleanup */
490 
491       }
492     /* Normal cleanup */
493 
494 
495     return ret_value;
496 } /* SDend */
497 
498 
499 /******************************************************************************
500  NAME
501     SDfileinfo -- get info about an open file
502 
503  DESCRIPTION
504     Return the number of datasets and global attributes in the file.
505     NOTE:  the number of datasets includes coordinate variable
506     datasets.  The routine SDiscoordvar() should be used if the
507     distinction is important.
508 
509  RETURNS
510     SUCCEED / FAIL
511 
512 ******************************************************************************/
513 intn
SDfileinfo(int32 fid,int32 * datasets,int32 * attrs)514 SDfileinfo(int32  fid,     /* IN:  file ID */
515            int32 *datasets,/* OUT: number of datasets in the file */
516            int32 *attrs    /* OUT: number of global attributes */)
517 {
518     CONSTR(FUNC, "SDfileinfo");    /* for HGOTO_ERROR */
519     NC   *handle = NULL;
520     intn  ret_value = SUCCEED;
521 
522 #ifdef SDDEBUG
523     fprintf(stderr, "SDnumber: I've been called\n");
524 #endif
525 
526     /* clear error stack */
527     HEclear();
528 
529     /* check that fid is valid and get file structure */
530     handle = SDIhandle_from_id(fid, CDFTYPE);
531     if(handle == NULL)
532       {
533     HGOTO_ERROR(DFE_ARGS, FAIL);
534       }
535 
536 #ifdef SDDEBUG
537     fprintf(stderr, "SDnumber: looked up handle as %d\n", handle);
538 #endif
539 
540     /* get number of data sets and global attributes */
541     *(int32 *)datasets = ((handle->vars != NULL) ? handle->vars->count : 0);
542     *(int32 *)attrs    = ((handle->attrs != NULL) ? handle->attrs->count : 0);
543 
544 
545 done:
546     if (ret_value == FAIL)
547       { /* Failure cleanup */
548 
549       }
550     /* Normal cleanup */
551 
552 
553     return ret_value;
554 } /* SDfileinfo */
555 
556 
557 /******************************************************************************
558  NAME
559     SDselect -- get a dataset ID
560 
561  DESCRIPTION
562     Return an id for the index-th data set in the file
563 
564     We've got 32bits, the current ID looks like:
565 
566     sdsID:
567 
568         32           20       16               0
569         ----------------------------------------
570         |  fid       | id-type| position index |
571         ----------------------------------------
572 
573     fid is the netCDF based file ID (i.e. from ncopen).  ID type
574     is SDSTYPE defined in mfhdf.h and position index is the
575     position in the file of this dataset.
576 
577     The position index is zero based
578 
579  RETURNS
580    An ID to a dataset else FAIL
581 
582 ******************************************************************************/
583 int32
SDselect(int32 fid,int32 index)584 SDselect(int32 fid,  /* IN: file ID */
585          int32 index /* IN: index of dataset to get ID for */)
586 {
587     CONSTR(FUNC, "SDselect");    /* for HGOTO_ERROR */
588     NC    *handle = NULL;
589     int32  sdsid;         /* the id we're gonna build */
590     int32  ret_value = FAIL;
591 
592 #ifdef SDDEBUG
593     fprintf(stderr, "SDselect: I've been called (index: %d) \n", index);
594 #endif
595 
596     /* clear error stack */
597     HEclear();
598 
599     /* check that fid is valid */
600     handle = SDIhandle_from_id(fid, CDFTYPE);
601     if(handle == NULL)
602       {
603     HGOTO_ERROR(DFE_ARGS, FAIL);
604       }
605 
606     /* check that a data set with this index exists */
607     if(handle->vars == NULL)
608       {
609     HGOTO_ERROR(DFE_ARGS, FAIL);
610       }
611 
612     if((unsigned)index >= handle->vars->count)
613       {
614     HGOTO_ERROR(DFE_ARGS, FAIL);
615       }
616 
617     /* create SDS id to return */
618     sdsid  = (((int32) fid & 0xffff) << 20) + (((int32) SDSTYPE) << 16) + index;
619 
620     ret_value = sdsid;
621 
622 done:
623     if (ret_value == FAIL)
624       { /* Failure cleanup */
625 
626       }
627     /* Normal cleanup */
628 
629 
630     return ret_value;
631 } /* SDselect */
632 
633 /******************************************************************************
634  NAME
635     SDgetinfo -- get info about a dataset
636 
637  DESCRIPTION
638     The user is repsonsible for allocating space to hold
639     the dataset name.  It can be at most H4_MAX_NC_NAME
640     characters in length.  NULL can be passed for any of
641     of the parameters if it is not required.
642 
643     dimsizes should be an array to hold the dimension sizes
644     a dataset can have at most H4_MAX_VAR_DIMS dimensions.
645 
646  RETURNS
647         SUCCEED / FAIL
648 
649 ******************************************************************************/
650 intn
SDgetinfo(int32 sdsid,char * name,int32 * rank,int32 * dimsizes,int32 * nt,int32 * nattrs)651 SDgetinfo(int32  sdsid,   /* IN:  dataset ID */
652           char  *name,    /* OUT: name of the dataset */
653           int32 *rank,    /* OUT: rank of the dataset */
654           int32 *dimsizes,/* OUT: array of dimension siszes */
655           int32 *nt,      /* OUT: number type of data */
656           int32 *nattrs   /* OUT: the number of local attributes */)
657 {
658     CONSTR(FUNC, "SDgetinfo");    /* for HGOTO_ERROR */
659     intn    i;
660     NC     *handle = NULL;
661     NC_var *var = NULL;
662     intn    ret_value = SUCCEED;
663 
664 #ifdef SDDEBUG
665     fprintf(stderr, "SDgetinfo: I've been called\n");
666 #endif
667 
668     /* clear error stack */
669     HEclear();
670 
671     /* obtain the variable structure */
672     handle = SDIhandle_from_id(sdsid, SDSTYPE);
673     if(handle == NULL)
674     HGOTO_ERROR(DFE_ARGS, FAIL);
675 
676     if(handle->vars == NULL)
677     HGOTO_ERROR(DFE_ARGS, FAIL);
678 
679     var = SDIget_var(handle, sdsid);
680     if(var == NULL)
681     HGOTO_ERROR(DFE_ARGS, FAIL);
682 
683     /* get sds name if it's requested */
684     if(name != NULL)
685       {
686           HDmemcpy(name, var->name->values, var->name->len);
687           name[var->name->len] = '\0';
688       }
689 
690     /* get sds' rank if it is requested */
691     if(rank != NULL)
692     *rank = var->assoc->count;
693 
694     /* get sds' number type if it is requested */
695     if(nt != NULL)
696     {
697     if(!var->HDFtype)
698         *nt    = hdf_map_type(var->type);
699     else
700         *nt    = var->HDFtype;
701     }
702 
703     /* get sds' number of attributes if it is requested */
704     if(nattrs != NULL)
705     *nattrs = (var->attrs ? var->attrs->count : 0);
706 
707     /* get sds' dimension sizes if they are requested */
708     if(dimsizes != NULL)
709     {
710     for(i = 0; i < var->assoc->count; i++)
711         dimsizes[i] = (int32) var->shape[i];
712 
713     if(dimsizes[0] == NC_UNLIMITED)
714     {
715         if(handle->file_type == HDF_FILE)
716         dimsizes[0] = var->numrecs;
717         else
718         dimsizes[0] = handle->numrecs;
719     }
720     }
721 
722 done:
723     if (ret_value == FAIL)
724       { /* Failure cleanup */
725 
726       }
727     /* Normal cleanup */
728 
729     return ret_value;
730 } /* SDgetinfo */
731 
732 
733 /******************************************************************************
734  NAME
735     SDreaddata -- read a hyperslab of data
736 
737  DESCRIPTION
738     Read a hyperslab of data from the given variable.
739 
740  RETURNS
741      SUCCEED / FAIL
742 
743 ******************************************************************************/
744 intn
SDreaddata(int32 sdsid,int32 * start,int32 * stride,int32 * end,void * data)745 SDreaddata(int32  sdsid,  /* IN:  dataset ID */
746            int32 *start,  /* IN:  coords of starting point */
747            int32 *stride, /* IN:  stride along each dimension */
748            int32 *end,    /* IN:  number of values to read per dimension */
749            void  *data    /* OUT: data buffer */)
750 {
751     CONSTR(FUNC, "SDreaddata");    /* for HGOTO_ERROR */
752     NC     *handle = NULL;
753     NC_dim *dim = NULL;
754     intn    varid;
755     int32   status;
756     comp_coder_t comp_type=COMP_CODE_INVALID;
757     uint32  comp_config;
758     NC_var * var;
759 #ifdef H4_BIG_LONGS
760     long    Start[H4_MAX_VAR_DIMS];
761     long    End[H4_MAX_VAR_DIMS];
762     long    Stride[H4_MAX_VAR_DIMS];
763 #else
764     long    *Start = NULL;
765     long    *End   = NULL;
766     long    *Stride = NULL;
767 #endif
768     intn    ret_value = SUCCEED;
769 
770     /* This decides how a dataset with unlimited dimension is read along the
771        unlimited dimension; the behavior is different between SD and nc APIs */
772     cdf_routine_name = "SDreaddata";
773 
774     /* Clear error stack */
775     HEclear();
776 
777     /* Validate arguments */
778     if((start == NULL) || (end == NULL) || (data == NULL))
779     HGOTO_ERROR(DFE_ARGS, FAIL);
780 
781     /* Get the NC_dim or NC_var depending on which id is given */
782     handle = SDIhandle_from_id(sdsid, SDSTYPE);
783     if(handle == NULL)
784       {
785           handle = SDIhandle_from_id(sdsid, DIMTYPE);
786           if(handle == NULL)
787         HGOTO_ERROR(DFE_ARGS, FAIL);
788 
789           dim = SDIget_dim(handle, sdsid);
790       }
791 
792     if(handle->vars == NULL)
793     HGOTO_ERROR(DFE_ARGS, FAIL);
794 
795     var = SDIget_var(handle, sdsid);
796     if(var == NULL)
797     HGOTO_ERROR(DFE_ARGS, FAIL);
798 
799     /* Dev note: empty SDS should have been checked here and SDreaddata would
800        have failed, but since it wasn't, for backward compatibility, we won't
801        do it now either. -BMR 2011 */
802 
803     /* Check if compression method is enabled */
804 
805     /* Make sure that the file is an HDF file before checking about compression */
806     if(handle->file_type == HDF_FILE) /* bug HDFFR-473 */
807     {
808     status = HCPgetcomptype(handle->hdf_file, var->data_tag, var->data_ref,
809                 &comp_type);
810 
811     if (status != FAIL)
812         if (comp_type != COMP_CODE_NONE && comp_type != COMP_CODE_INVALID)
813         {
814         /* Must have decoder to read data */
815         HCget_config_info( comp_type , &comp_config);
816         if ((comp_config & COMP_DECODER_ENABLED) == 0)
817         { /* decoder not present?? */
818             HGOTO_ERROR(DFE_BADCODER, FAIL);
819         }
820         }
821     /* The case status=FAIL is not handled, not sure if it's intentional. -BMR */
822     } /* file is HDF */
823 
824     /* Get ready to read */
825     handle->xdrs->x_op = XDR_DECODE ;
826 
827     /*
828      * Figure out the index of the variable to read from,
829      * the user might have passed us a dimension, in which
830      * case we want to reade from its coordinate variable
831      */
832     if(dim)
833       {
834           varid = SDIgetcoordvar(handle, dim, (int32)(sdsid & 0xffff), (int32) 0);
835       }
836     else
837       {
838           /* Derive the variable index from the SDS id, using the formula
839              described in SDselect */
840           varid = (intn)sdsid & 0xffff;
841       }
842 
843     /*
844      * In general, (long) == int32
845      * In cases where it doesn't we need to convert
846      */
847 #ifdef H4_BIG_LONGS
848     {
849         int i;
850         for(i = 0; i < var->assoc->count; i++)
851           {
852             Start[i]  = (long) start[i];
853             End[i]    = (long) end[i];
854             if(stride)
855                 Stride[i] = (long) stride[i];
856           }
857     }
858 
859 #else
860 
861     Start  = (long *)start;
862     End    = (long *)end;
863     Stride = (long *)stride;
864 
865 #endif
866 
867     /* Validate stride value if given - make sure we don't try to "stride" */
868     /* beyond the dimension's end */
869     if(stride != NULL)
870     {
871         int i;
872     int32 dimsize = (int32) var->shape[0];
873 
874     /* Validate stride value of first dimension separately to catch */
875     /* unlimited dimension situation */
876     if (var->shape[0] == NC_UNLIMITED)
877     {
878         /* get the actual size */
879         if(handle->file_type == HDF_FILE)
880         dimsize = var->numrecs;
881         else
882         dimsize = handle->numrecs;
883     }
884     if ((Stride[0]*(End[0]-1)) >= (dimsize-Start[0]))
885         HGOTO_ERROR(DFE_ARGS, FAIL);
886 
887     /* Validate subsequent dimensions if dataset is multi-dim */
888     for(i = 1; i < var->assoc->count; i++)
889         if ((Stride[i]*(End[i]-1)) >= ((int32)var->shape[i]-Start[i]))
890         HGOTO_ERROR(DFE_ARGS, FAIL);
891     }
892 
893     /* Call the readg routines if a stride is given */
894     if(stride == NULL)
895         status = NCvario(handle, varid, Start, End, (Void *)data);
896     else
897         status = NCgenio(handle, varid, Start, End, Stride, NULL, (Void *)data);
898 
899     if(status == -1)
900         ret_value = FAIL;
901     else
902         ret_value = SUCCEED;
903 
904 done:
905     if (ret_value == FAIL)
906       { /* Failure cleanup */
907       }
908     /* Normal cleanup */
909 
910     return ret_value;
911 } /* SDreaddata */
912 
913 
914 /******************************************************************************
915  NAME
916     SDnametoindex -- map a dataset name to an index
917 
918  DESCRIPTION
919     Given a data set name return the index (not ID) of the
920     first data set whose name matches.
921 
922     There can be multiple data sets with the same name.  In
923     such a case, we only ever return the index of the first
924     such dataset.
925     Wildcards are not supported
926 
927  RETURNS
928         Index of a dataset or FAIL
929 
930 ******************************************************************************/
931 int32
SDnametoindex(int32 fid,const char * name)932 SDnametoindex(int32 fid,  /* IN: file ID */
933               const char *name  /* IN: name of dataset to search for */)
934 {
935     CONSTR(FUNC, "SDnametoindex");    /* for HGOTO_ERROR */
936     unsigned ii;
937     intn     len;
938     NC      *handle = NULL;
939     NC_var **dp = NULL;
940     int32    ret_value = FAIL;
941 
942 #ifdef SDDEBUG
943     fprintf(stderr, "SDnametoindex: I've been called\n");
944 #endif
945 
946 
947     /* check that fid is valid */
948     handle = SDIhandle_from_id(fid, CDFTYPE);
949     if(handle == NULL)
950       {
951     HGOTO_ERROR(DFE_ARGS, FAIL);
952       }
953 
954     if(handle->vars == NULL)
955       {
956     HGOTO_ERROR(DFE_ARGS, FAIL);
957       }
958 
959     len = HDstrlen(name) ;
960     dp = (NC_var**)handle->vars->values ;
961     for(ii = 0 ; ii < handle->vars->count ; ii++, dp++)
962       {
963         if( len == (*dp)->name->len
964             && HDstrncmp(name, (*dp)->name->values, HDstrlen(name)) == 0)
965           {
966             HGOTO_DONE((int32)ii);
967           }
968       }
969 
970     ret_value = FAIL;
971 
972 done:
973     if (ret_value == FAIL)
974       { /* Failure cleanup */
975 
976       }
977     /* Normal cleanup */
978 
979     return ret_value;
980 } /* SDnametoindex */
981 
982 
983 /******************************************************************************
984  NAME
985     SDgetnumvars_byname -- get the number of variables in the file having
986             the given name.
987 
988  DESCRIPTION
989     Given a data set name, retrieve the number of variables in the file having
990     the same name.  Sometime, more than one SDS are named 'name' or a
991     dimension of the SDS 'name' is also named 'name.'  The user can use
992     this function to find out how many of those having the same name.
993 
994  RETURNS
995         SUCCEED / FAIL
996 
997  MODIFICATION
998 
999 ******************************************************************************/
1000 intn
SDgetnumvars_byname(int32 fid,const char * name,int32 * n_vars)1001 SDgetnumvars_byname(int32 fid,  /* IN: file ID */
1002               const char *name,  /* IN: name of dataset to search for */
1003         int32* n_vars)
1004 {
1005     CONSTR(FUNC, "SDgetnumvars_byname");    /* for HGOTO_ERROR */
1006     unsigned ii;
1007     intn     len;
1008     int32    count = 0;
1009     NC      *handle = NULL;
1010     NC_var **dp = NULL;
1011     intn     ret_value = SUCCEED;
1012 
1013 #ifdef SDDEBUG
1014     fprintf(stderr, "SDgetnumvars_byname: I've been called\n");
1015 #endif
1016 
1017     /* clear error stack */
1018     HEclear();
1019 
1020     /* check that fid is valid */
1021     handle = SDIhandle_from_id(fid, CDFTYPE);
1022     if(handle == NULL)
1023       {
1024     HGOTO_ERROR(DFE_ARGS, FAIL);
1025       }
1026 
1027     if(handle->vars == NULL)
1028       {
1029     HGOTO_ERROR(DFE_ARGS, FAIL);
1030       }
1031 
1032     len = HDstrlen(name) ;
1033     dp = (NC_var**)handle->vars->values ;
1034     for(ii = 0 ; ii < handle->vars->count; ii++, dp++)
1035       {
1036         if( len == (*dp)->name->len
1037             && HDstrncmp(name, (*dp)->name->values, HDstrlen(name)) == 0)
1038         count++;
1039       }
1040     *n_vars = count;
1041 
1042 done:
1043     if (ret_value == FAIL)
1044       { /* Failure cleanup */
1045 
1046       }
1047     /* Normal cleanup */
1048 
1049     return ret_value;
1050 } /* SDgetnumvars_byname */
1051 
1052 
1053 /******************************************************************************
1054  NAME
1055     SDnametoindices -- retrieves a list of variables having the given name.
1056 
1057  DESCRIPTION
1058     Given a data set name, retrieve a list of structures, each of which
1059     contains the index of a variable whose name matches the given name, and
1060     the type of the variable, which is either data set (IS_SDSVAR) or
1061     coordinate variable (IS_CRDVAR,) or (UNKNOWN.)  UNKNOW is for data
1062     created before the fix of a data corruption bug due to the library's
1063     inability to distinguish between those two types of variables.  The
1064     fix was available starting in HDF4.2r2.
1065 
1066     This API is added to allow the user to examine all the variables having
1067     the given name and decide the correct one to gain access on.
1068 
1069  RETURNS
1070         SUCCEED / FAIL
1071 
1072  MODIFICATION
1073 
1074 ******************************************************************************/
1075 intn
SDnametoindices(int32 fid,const char * name,hdf_varlist_t * var_list)1076 SDnametoindices(int32 fid,  /* IN: file ID */
1077         const char *name,  /* IN: name of dataset to search for */
1078         hdf_varlist_t* var_list)
1079 {
1080     CONSTR(FUNC, "SDnametoindices");    /* for HGOTO_ERROR */
1081     unsigned ii;
1082     intn     len;
1083     NC      *handle = NULL;
1084     NC_var **dp = NULL;
1085     hdf_varlist_t* varlistp;
1086     int32    ret_value = SUCCEED;
1087 
1088 #ifdef SDDEBUG
1089     fprintf(stderr, "SDnametoindices: I've been called\n");
1090 #endif
1091 
1092     /* clear error stack */
1093     HEclear();
1094 
1095     /* check that fid is valid */
1096     handle = SDIhandle_from_id(fid, CDFTYPE);
1097     if(handle == NULL)
1098       {
1099     HGOTO_ERROR(DFE_ARGS, FAIL);
1100       }
1101 
1102     if(handle->vars == NULL)
1103       {
1104     HGOTO_ERROR(DFE_ARGS, FAIL);
1105       }
1106 
1107     len = HDstrlen(name) ;
1108     dp = (NC_var**)handle->vars->values ;
1109     varlistp = var_list;
1110     for(ii = 0 ; ii < handle->vars->count; ii++, dp++)
1111       {
1112         if( len == (*dp)->name->len
1113             && HDstrncmp(name, (*dp)->name->values, HDstrlen(name)) == 0)
1114     {
1115         varlistp->var_index = (int32)ii;
1116         varlistp->var_type = (*dp)->var_type;
1117         varlistp++;
1118     }
1119       }
1120 
1121 done:
1122     if (ret_value == FAIL)
1123       { /* Failure cleanup */
1124 
1125       }
1126     /* Normal cleanup */
1127 
1128     return ret_value;
1129 } /* SDnametoindices */
1130 
1131 
1132 /******************************************************************************
1133  NAME
1134     SDgetrange -- simulate a call to DFSDgetrange
1135 
1136  DESCRIPTION
1137     If a "valid_range" attribute is provided return its
1138     values in pmax and pmin.  Else if both a "valid max"
1139     AND a "vaild min" exist return their values in pmax and pmin.
1140 
1141     Arrgghh, in HDF it was assumed that the max and min values
1142     were of the same data type as the rest of the data.  So
1143     the user would know the amount of storage to send to get
1144     back the max and min values.  This is not the case with
1145     netCDF.  This routine will only work if they are already
1146     the same number types.
1147 
1148  RETURNS
1149     On error or missing attributes return FAIL else SUCCEED.
1150 
1151 ******************************************************************************/
1152 intn
SDgetrange(int32 sdsid,void * pmax,void * pmin)1153 SDgetrange(int32 sdsid, /* IN:  dataset ID */
1154            void * pmax,  /* OUT: valid max */
1155            void * pmin   /* OUT: valid min */)
1156 {
1157     CONSTR(FUNC, "SDgetrange");    /* for HGOTO_ERROR */
1158     NC       *handle = NULL;
1159     NC_var   *var = NULL;
1160     NC_attr **attr = NULL;
1161     NC_attr **attr1 = NULL;
1162     NC_attr **attr2 = NULL;
1163     NC_array *array = NULL;
1164     intn      ret_value = SUCCEED;
1165 
1166 #ifdef SDDEBUG
1167     fprintf(stderr, "SDgetrange: I've been called\n");
1168 #endif
1169 
1170     /* clear error stack */
1171     HEclear();
1172 
1173     handle = SDIhandle_from_id(sdsid, SDSTYPE);
1174     if(handle == NULL)
1175       {
1176     HGOTO_ERROR(DFE_ARGS, FAIL);
1177       }
1178 
1179     var = SDIget_var(handle, sdsid);
1180     if(var == NULL)
1181       {
1182     HGOTO_ERROR(DFE_ARGS, FAIL);
1183       }
1184 
1185     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_ValidRange);
1186     if((attr != NULL) && ((*attr)->data->type == var->type))
1187       {
1188         /* BUG: this may be a pointer to a pointer */
1189         array = (NC_array *) (*attr)->data;
1190         HDmemcpy(pmin, array->values, array->szof);
1191         HDmemcpy(pmax, array->values + array->szof, array->szof);
1192       }
1193     else
1194       {
1195         attr1 = (NC_attr **) NC_findattr(&(var->attrs), "valid_max");
1196         attr2 = (NC_attr **) NC_findattr(&(var->attrs), "valid_min");
1197 
1198         if((attr1 == NULL) || (attr2 == NULL))
1199           {
1200 #ifdef SDDEBUG
1201             fprintf(stderr, "No dice on range info (missing at least one)\n");
1202 #endif
1203             HGOTO_ERROR(DFE_RANGE, FAIL);
1204           }
1205 
1206         if(((*attr1)->HDFtype != var->HDFtype)
1207            || ((*attr2)->HDFtype != var->HDFtype))
1208           {
1209 #ifdef SDDEBUG
1210             fprintf(stderr, "No dice on range info (wrong types)\n");
1211 #endif
1212             HGOTO_ERROR(DFE_RANGE, FAIL);
1213           }
1214 
1215         NC_copy_arrayvals((char *)pmax, (*attr1)->data) ;
1216         NC_copy_arrayvals((char *)pmin, (*attr2)->data) ;
1217       }
1218 
1219 done:
1220     if (ret_value == FAIL)
1221       { /* Failure cleanup */
1222 
1223       }
1224     /* Normal cleanup */
1225 
1226 
1227     return ret_value;
1228 } /* SDgetrange */
1229 
1230 
1231 /* -------------------------- CREATION INTERFACE -------------------------- */
1232 /*
1233 
1234         --- create a new data set ---
1235 sdsid   = SDcreate(fid, name, numbertype, rank, dimsizes);
1236 
1237         --- associate a name with a dimension.  If a prev sdsid is ---
1238         --- provided then it is assumed that the current dimension is the ---
1239         --- same as the dimension with the same name of the previous sds ---
1240 status  = SDsetdim(sdsid, dimnumber, dimname, [prev sdsid] );
1241 
1242         --- note that it will be possible to store values for a ---
1243         --- dimension without having to name it ---
1244 status  = SDsetdimvalues(sdsid, dimnumber, numbertype, count, data);
1245 
1246         --- set the units and format strings ---
1247 status  = SDsetdimstrs(sdsid, dimnumber, unitstr, formatstr);
1248 
1249         --- we will need an SDendaccess() so that we know when it ---
1250         --- is safe to write the information out in this case ---
1251 status  = SDendaccess(sdsid);
1252 
1253         --- set fill mode for a file open for write
1254 cur_mode = SDsetfillmode(fid, fillmode);
1255 
1256         --- set dimval backward compatible  for write
1257 status  = SDsetdimval_comp(dimid, compt_mode);
1258 
1259 */
1260 
1261 /******************************************************************************
1262  NAME
1263     SDcreate -- create a new dataset
1264 
1265  DESCRIPTION
1266     Simulate a call to ncvardef without having to be in
1267     define mode.  name can be at most H4_MAX_NC_NAME
1268     characters.  Rank can be at most H4_MAX_VAR_DIMS
1269 
1270     It looks like for the call to NC_new_var() we need to
1271     have dimension IDs already.  So I guess we should just
1272     create the fake dimensions now and when optional
1273     information comes in (i.e.  name, tying to other
1274     dimensions) we'll go in and modify the structure in place.
1275     This is gonna be heinous.  Please do not attempt this at home
1276     See SDselect() for a discussion on how SDS IDs are set up.
1277 
1278  RETURNS
1279     An ID to the new dataset else FAIL
1280 
1281 ******************************************************************************/
1282 int32
SDcreate(int32 fid,const char * name,int32 nt,int32 rank,int32 * dimsizes)1283 SDcreate(int32  fid,      /* IN: file ID */
1284          const char  *name, /* IN: dataset name */
1285          int32  nt,       /* IN: dataset number type */
1286          int32  rank,     /* IN: rank of dataset */
1287          int32 *dimsizes  /* IN: array of dimension sizes */)
1288 {
1289     CONSTR(FUNC, "SDcreate");    /* for HGOTO_ERROR */
1290     intn     i;
1291     NC      *handle = NULL;
1292     NC_var  *var = NULL;
1293     NC_dim  *newdim = NULL;
1294     int32    sdsid;
1295     nc_type  nctype;
1296     char     dimname[H4_MAX_NC_NAME];
1297     intn     num;
1298     intn    *dims = NULL;
1299     intn     is_ragged;
1300     int32    ret_value = FAIL;
1301 
1302 #ifdef SDDEBUG
1303     fprintf(stderr, "SDcreate: I've been called\n");
1304 #endif
1305 
1306     /* clear error stack */
1307     HEclear();
1308 
1309     /* check that fid is valid */
1310     handle = SDIhandle_from_id(fid, CDFTYPE);
1311     if(handle == NULL)
1312       {
1313     HGOTO_ERROR(DFE_ARGS, FAIL);
1314       }
1315 
1316     /* fudge the name since its optional */
1317     if((name == NULL) || (name[0] == ' ') || (name[0] == '\0'))
1318         name = "DataSet";
1319 
1320     /* check if its a ragged array.
1321        Why is this code still here? -GV */
1322     if((rank > 1) && dimsizes[rank - 1] == SD_RAGGED)
1323       {
1324 #ifdef DEBUG
1325         printf("YOW!  We have a ragged array kids: %s\n", name);
1326 #endif
1327         rank--;
1328         is_ragged = TRUE;
1329       }
1330     else
1331       {
1332         is_ragged = FALSE;
1333       }
1334 
1335     /* make fake dimensions which may or may not be over-ridden later */
1336     dims = (intn *) HDmalloc(rank * sizeof(intn));
1337     if(dims == NULL)
1338       {
1339     HGOTO_ERROR(DFE_NOSPACE, FAIL);
1340       }
1341 
1342     if(rank > H4_MAX_VAR_DIMS)
1343       {
1344     HGOTO_ERROR(DFE_ARGS, FAIL);
1345       }
1346 
1347     for(i = 0; i < rank; i++)
1348       {
1349           num = (handle->dims ? handle->dims->count : 0);
1350           sprintf(dimname, "fakeDim%d", num);
1351           newdim = (NC_dim *) NC_new_dim(dimname, dimsizes[i]);
1352           if(newdim == NULL)
1353             {
1354                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1355             }
1356 
1357           if(handle->dims == NULL)
1358             { /* first time */
1359                 handle->dims = NC_new_array(NC_DIMENSION,(unsigned)1, (Void *)&newdim);
1360                 if(handle->dims == NULL)
1361                   {
1362                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1363                   }
1364             }
1365           else
1366             {
1367                 if( NC_incr_array(handle->dims, (Void *)&newdim) == NULL)
1368                   {
1369                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1370                   }
1371             }
1372 
1373           dims[i] = (intn) handle->dims->count -1;
1374 
1375       } /* end for 'i < rank' */
1376 
1377     /* create the actual variable */
1378     if ((nctype = hdf_unmap_type((int)nt)) == FAIL)
1379       {
1380     HGOTO_ERROR(DFE_INTERNAL, FAIL);
1381       }
1382 
1383     var = (NC_var *) NC_new_var(name, nctype, (int)rank, dims);
1384     if(var == NULL)
1385       {
1386     HGOTO_ERROR(DFE_INTERNAL, FAIL);
1387       }
1388 
1389     /* Set the "newly created" & "set length" flags for use in SDwritedata */
1390     var->created=TRUE;
1391     var->set_length=FALSE;
1392 
1393     /* Indicate that this variable is an actual sds, not a coordinate
1394     variable (bugzilla 624) - BMR - 05/14/2007 */
1395     var->var_type=IS_SDSVAR;
1396 
1397     /* NC_new_var strips off "nativeness" add it back in if appropriate */
1398     var->HDFtype = nt;
1399     if (FAIL == (var->HDFsize = DFKNTsize(nt)))
1400       {
1401     HGOTO_ERROR(DFE_INTERNAL, FAIL);
1402       }
1403 
1404     var->cdf     = handle; /* set cdf before calling NC_var_shape */
1405     /* get a new NDG ref for this sucker */
1406 #ifdef NOT_YET
1407     var->ndg_ref = Htagnewref(handle->hdf_file,DFTAG_NDG);
1408 #else /* NOT_YET */
1409     var->ndg_ref = Hnewref(handle->hdf_file);
1410 #endif /* NOT_YET */
1411 
1412     /* set ragged status. Why is this still here -GV */
1413     var->is_ragged = is_ragged;
1414 
1415     /* no ragged array info stored yet */
1416     if(var->is_ragged)
1417       {
1418         var->rag_list = NULL;
1419         var->rag_fill = 0;
1420       }
1421 
1422     /* add it to the handle */
1423     if(handle->vars == NULL)
1424       { /* first time */
1425           handle->vars = NC_new_array(NC_VARIABLE,(unsigned)1, (Void *)&var);
1426           if(handle->vars == NULL)
1427             {
1428                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1429             }
1430       }
1431     else
1432       {
1433           if(handle->vars->count >= H4_MAX_NC_VARS)
1434             {
1435                 HGOTO_ERROR(DFE_EXCEEDMAX, FAIL);
1436             }
1437           else
1438             {
1439                 if( NC_incr_array(handle->vars, (Void *)&var) == NULL)
1440                   {
1441                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1442                   }
1443             }
1444       }
1445 
1446     /* compute all of the shape information */
1447     if(NC_var_shape(var, handle->dims) == -1)
1448       {
1449     HGOTO_ERROR(DFE_INTERNAL, FAIL);
1450       }
1451 
1452     /* create a handle we can give back to the user */
1453     sdsid  = (((int32) fid) << 20) + (((int32) SDSTYPE) << 16);
1454     sdsid += handle->vars->count -1;
1455 
1456     /* make sure it gets reflected in the file */
1457     handle->flags |= NC_HDIRTY;
1458 
1459     /* free dims */
1460     HDfree(dims);
1461 
1462     ret_value = sdsid;
1463 
1464 
1465 done:
1466     if (ret_value == FAIL)
1467       { /* Failure cleanup */
1468 
1469       }
1470     /* Normal cleanup */
1471 
1472     return ret_value;
1473 } /* SDcreate */
1474 
1475 
1476 /******************************************************************************
1477  NAME
1478     SDgetdimid -- get a dimension ID
1479 
1480  DESCRIPTION
1481     Given an sdsid and a dimension number return a
1482     dimid.  Index is a ZERO based quantity
1483 
1484     The dimID looks similar to the sdsID except DIMTYPE
1485     is substituted for SDSTYPE as the id-type:
1486 
1487     dimID:
1488 
1489         32           20       16               0
1490         ----------------------------------------
1491         |  fid       | id-type| position index |
1492         ----------------------------------------
1493 
1494  RETURNS
1495         An ID to the dimension else FAIL
1496 
1497 ******************************************************************************/
1498 int32
SDgetdimid(int32 sdsid,intn number)1499 SDgetdimid(int32 sdsid,  /* IN: dataset ID */
1500            intn  number  /* IN: index of dimension, in the SDS, ie. <= rank-1 */)
1501 {
1502     CONSTR(FUNC, "SDgetdimid");    /* for HGOTO_ERROR */
1503     NC     *handle = NULL;
1504     NC_var *var = NULL;
1505     int32   id;
1506     int32   dimindex; /* index of dim in the file, ie. dims of all SDSs */
1507     int32   ret_value = FAIL;
1508 
1509 #ifdef SDDEBUG
1510     fprintf(stderr, "SDgetdimid: I've been called\n");
1511 #endif
1512 
1513     /* clear error stack */
1514     HEclear();
1515 
1516     /* sanity check args */
1517     if(number < 0)
1518         HGOTO_ERROR(DFE_ARGS, FAIL);
1519 
1520     /* get the handle */
1521     handle = SDIhandle_from_id(sdsid, SDSTYPE);
1522     if(handle == NULL)
1523       {
1524     HGOTO_ERROR(DFE_ARGS, FAIL);
1525       }
1526 
1527     /* get the variable */
1528     var = SDIget_var(handle, sdsid);
1529     if(var == NULL)
1530       {
1531     HGOTO_ERROR(DFE_ARGS, FAIL);
1532       }
1533 
1534     /* check if enough / too many dims */
1535     if((var->assoc == NULL) || (var->assoc->count < (unsigned)number))
1536       {
1537     HGOTO_ERROR(DFE_ARGS, FAIL);
1538       }
1539 
1540     /* get the dim number out of the assoc array */
1541     if (var->assoc->values == NULL)
1542       {
1543     HGOTO_ERROR(DFE_ARGS, FAIL);
1544       }
1545     dimindex = var->assoc->values[number];
1546 
1547     /* build the dim id */
1548     id  = (sdsid & 0xfff00000) + (((int32) DIMTYPE) << 16) + dimindex;
1549 
1550     ret_value = id;
1551 
1552 done:
1553     if (ret_value == FAIL)
1554       { /* Failure cleanup */
1555 
1556       }
1557     /* Normal cleanup */
1558 
1559     return ret_value;
1560 } /* SDgetdimid */
1561 
1562 
1563 /******************************************************************************
1564  NAME
1565     SDsetdimname -- give a name to a dimension
1566 
1567  DESCRIPTION
1568     Set the name of a dimension -- at most H4_MAX_NC_NAME characters.
1569     If this name is already in use we should point to the
1570     existing dimension with that name.  If the sizes are
1571     different return an error.  If this dimension already has
1572     a name throw it out and use the new one.
1573 
1574  RETURNS
1575     SUCCEED / FAIL
1576 
1577 ******************************************************************************/
1578 intn
SDsetdimname(int32 id,const char * name)1579 SDsetdimname(int32  id,   /* IN: dataset ID */
1580              const char  *name  /* IN: dimension name */)
1581 {
1582     CONSTR(FUNC, "SDsetdimname");    /* for HGOTO_ERROR */
1583     NC         *handle = NULL;
1584     NC_dim     *dim = NULL;
1585     NC_dim    **dp = NULL;
1586     NC_string  *old = NULL;
1587     NC_string  *new = NULL;
1588     NC_array  **ap = NULL;
1589     size_t      len;
1590     unsigned    ii;
1591     intn        ret_value = SUCCEED;
1592 
1593 #ifdef SDDEBUG
1594     fprintf(stderr, "SDsetdimname: I've been called\n");
1595 #endif
1596 
1597     /* clear error stack */
1598     HEclear();
1599 
1600     /* get the handle */
1601     handle = SDIhandle_from_id(id, DIMTYPE);
1602     if(handle == NULL)
1603       {
1604     HGOTO_ERROR(DFE_ARGS, FAIL);
1605       }
1606 
1607     /* get the dimension structure */
1608     dim = SDIget_dim(handle, id);
1609     if(dim == NULL)
1610       {
1611     HGOTO_ERROR(DFE_ARGS, FAIL);
1612       }
1613 
1614     /* check for name in use */
1615     len = HDstrlen(name) ;
1616     dp = (NC_dim**)handle->dims->values ;
1617     for(ii = 0 ; ii < handle->dims->count ; ii++, dp++)
1618       {
1619           if( len == (*dp)->name->len
1620               && HDstrncmp(name, (*dp)->name->values, HDstrlen(name)) == 0)
1621             {
1622                 if(dim != (*dp))
1623                   {
1624                       /* a dimension with this name already exists */
1625                       /* so change to point to it */
1626                       if(dim->size != (*dp)->size)
1627                         {
1628                             HGOTO_ERROR(DFE_BADDIMNAME, FAIL);
1629                         }
1630 
1631                       ap = (NC_array **) handle->dims->values;
1632                       ap += id & 0xffff;
1633                       NC_free_dim(dim);
1634                       (*dp)->count += 1;
1635                       (*ap) = (NC_array *) (*dp);
1636                       HGOTO_DONE(SUCCEED);
1637                   }
1638             }
1639       }
1640 
1641     /* throw out the old name if it exists and create a new one */
1642     old = dim->name;
1643     new = NC_new_string((unsigned)HDstrlen(name),name);
1644     if(new == NULL)
1645       {
1646     HGOTO_ERROR(DFE_ARGS, FAIL);
1647       }
1648 
1649     dim->name = new;
1650     NC_free_string(old);
1651 
1652     /* make sure it gets reflected in the file */
1653     handle->flags |= NC_HDIRTY;
1654 
1655 done:
1656     if (ret_value == FAIL)
1657       { /* Failure cleanup */
1658 
1659       }
1660     /* Normal cleanup */
1661 
1662     return ret_value;
1663 } /* SDsetdimname */
1664 
1665 
1666 /******************************************************************************
1667  NAME
1668     SDendaccess -- close a sds ID
1669 
1670  DESCRIPTION
1671     Close down this access ID to a data object
1672 
1673     Usually, this will do nothing.  However, if the meta-data
1674     has changed and SYNC_ON_EACC is defiend flush it all out
1675     to disk.
1676 
1677  RETURNS
1678         SUCCEED / FAIL
1679 
1680 ******************************************************************************/
1681 intn
SDendaccess(int32 id)1682 SDendaccess(int32 id /* IN: dataset ID */)
1683 {
1684     CONSTR(FUNC, "SDendaccess");    /* for HGOTO_ERROR */
1685     NC     *handle;
1686     int32   ret_value = SUCCEED;
1687 
1688 #ifdef SDDEBUG
1689     fprintf(stderr, "SDendaccess: I've been called\n");
1690 #endif
1691 
1692     /* clear error stack */
1693     HEclear();
1694 
1695     /* get the handle */
1696     handle = SDIhandle_from_id(id, SDSTYPE);
1697     if(handle == NULL)
1698       {
1699     HGOTO_ERROR(DFE_ARGS, FAIL);
1700       }
1701 
1702 #ifdef SYNC_ON_EACC
1703 
1704     /* make sure we can write to the file */
1705     if(handle->flags & NC_RDWR)
1706       {
1707           handle->xdrs->x_op = XDR_ENCODE;
1708 
1709           /* see if the meta-data needs to be updated */
1710           if(handle->flags & NC_HDIRTY)
1711             {
1712                 if(!xdr_cdf(handle->xdrs, &handle) )
1713                   {
1714                       HGOTO_ERROR(DFE_XDRERROR, FAIL);
1715                   }
1716 
1717                 handle->flags &= ~(NC_NDIRTY | NC_HDIRTY);
1718             }
1719           else
1720             {
1721                 /* see if the numrecs info needs updating */
1722                 if(handle->flags & NC_NDIRTY)
1723                   {
1724                       if(!xdr_numrecs(handle->xdrs, handle) )
1725                         {
1726                             HGOTO_ERROR(DFE_XDRERROR, FAIL);
1727                         }
1728 
1729                       handle->flags &= ~(NC_NDIRTY);
1730                   }
1731             }
1732       }
1733 
1734 #else
1735 
1736     /* free the AID */
1737     ret_value = SDIfreevarAID(handle, id & 0xffff);
1738 
1739 #endif /* SYNC_ON_EACC */
1740 
1741 done:
1742     if (ret_value == FAIL)
1743       { /* Failure cleanup */
1744 
1745       }
1746     /* Normal cleanup */
1747 
1748 
1749     return ret_value;
1750 } /* SDendaccess */
1751 
1752 #ifdef MFSD_INTERNAL
1753 
1754 /******************************************************************************
1755  NAME
1756     SDIputattr -- put an attribute in an attribute list
1757 
1758  DESCRIPTION
1759     Common code for adding an attribute to an attribute list.
1760     The list gets created if it had previously been empty
1761 
1762  RETURNS
1763      SUCCEED / FAIL
1764 
1765 ******************************************************************************/
1766 intn
SDIputattr(NC_array ** ap,const char * name,int32 nt,intn count,const void * data)1767 SDIputattr(NC_array **ap,   /* IN/OUT: attribute list */
1768            const char *name, /* IN:     attribute name */
1769            int32      nt,   /* IN:     attribute number type */
1770            intn       count,/* IN:     number of attribute values */
1771            const void *      data  /* IN:     attribute values */)
1772 {
1773     CONSTR(FUNC, "SDIputattr");    /* for HGOTO_ERROR */
1774     NC_attr *attr = NULL;
1775     NC_attr **atp = NULL;
1776     NC_attr *old = NULL;
1777     nc_type  type;   /* unmap -- HDF type to NC type */
1778     intn     ret_value = SUCCEED;
1779 
1780 #ifdef SDDEBUG
1781     fprintf(stderr, "SDIputattr: I've been called\n");
1782 #endif
1783 
1784     if ((type = hdf_unmap_type((int)nt)) == FAIL)
1785       {
1786     HGOTO_ERROR(DFE_ARGS, FAIL);
1787       }
1788 
1789     if(*ap == NULL)
1790       { /* first time */
1791           attr = (NC_attr *) NC_new_attr(name,type,(unsigned)count,data) ;
1792           if(attr == NULL)
1793             {
1794                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1795             }
1796 
1797           attr->HDFtype = nt; /* Add HDFtype  */
1798           *ap = NC_new_array(NC_ATTRIBUTE,(unsigned)1, (Void*)&attr) ;
1799           if(*ap == NULL)
1800             {
1801                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1802             }
1803       }
1804     else
1805       {
1806           if((atp = NC_findattr(ap, name)) != NULL)
1807             { /* name in use */
1808                 old = *atp ;
1809                 *atp = (NC_attr *) NC_new_attr(name,type,(unsigned)count,data);
1810                 if(*atp == NULL)
1811                   {
1812                       *atp = old;
1813                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1814                   }
1815                 (*atp)->HDFtype = nt; /* Add HDFtype  */
1816                 NC_free_attr(old);
1817             }
1818           else
1819             {
1820                 if((*ap)->count >= H4_MAX_NC_ATTRS)
1821                   {  /* Too many */
1822                       HGOTO_ERROR(DFE_EXCEEDMAX, FAIL);
1823                   }
1824 
1825                 /* just add it */
1826                 attr = (NC_attr *) NC_new_attr(name,type,(unsigned)count,data);
1827                 attr->HDFtype = nt; /* Add HDFtype  */
1828                 if(attr == NULL)
1829                   {
1830                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1831                   }
1832 
1833                 if(NC_incr_array((*ap), (Void *)&attr) == NULL)
1834                   {
1835                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
1836                   }
1837             }
1838       }
1839 
1840 done:
1841     if (ret_value == FAIL)
1842       { /* Failure cleanup */
1843 
1844       }
1845     /* Normal cleanup */
1846 
1847     return ret_value;
1848 } /* SDIputattr */
1849 
1850 #endif /* MFSD_INTERNAL */
1851 
1852 /******************************************************************************
1853  NAME
1854     SDsetrange -- simulate a call to DFSDsetrange
1855 
1856  DESCRIPTION
1857     Store range info for this variable in the valid_range
1858     attribute.  If that attribute already exists overwrite
1859     the current values.  It is assumed that the values are
1860     the same type as the data set.
1861 
1862     It is up to the user to decide what is meant by the
1863     "valid" max and min.
1864 
1865  RETURNS
1866     On error FAIL else SUCCEED.
1867 
1868 ******************************************************************************/
1869 intn
SDsetrange(int32 sdsid,void * pmax,void * pmin)1870 SDsetrange(int32 sdsid, /* IN: dataset ID */
1871            void * pmax,  /* IN: valid max */
1872            void * pmin   /* IN: valid min */)
1873 {
1874     CONSTR(FUNC, "SDsetrange");    /* for HGOTO_ERROR */
1875     NC      *handle = NULL;
1876     NC_var  *var = NULL;
1877     uint8    data[80];
1878     intn     sz;
1879     intn     ret_value = SUCCEED;
1880 
1881 #ifdef SDDEBUG
1882     fprintf(stderr, "SDsetrange: I've been called\n");
1883 #endif
1884 
1885     /* clear error stack */
1886     HEclear();
1887 
1888     handle = SDIhandle_from_id(sdsid, SDSTYPE);
1889     if(handle == NULL)
1890       {
1891     HGOTO_ERROR(DFE_ARGS, FAIL);
1892       }
1893 
1894     var = SDIget_var(handle, sdsid);
1895     if(var == NULL)
1896       {
1897     HGOTO_ERROR(DFE_ARGS, FAIL);
1898       }
1899 
1900     if((pmax == NULL) || (pmin == NULL))
1901       {
1902     HGOTO_ERROR(DFE_ARGS, FAIL);
1903       }
1904 
1905     /* move data values over */
1906     if (FAIL == (sz = DFKNTsize(var->HDFtype | DFNT_NATIVE)))
1907       {
1908     HGOTO_ERROR(DFE_ARGS, FAIL);
1909       }
1910 
1911     HDmemcpy(data, pmin, sz);
1912     HDmemcpy(data + sz, pmax, sz);
1913 
1914     /* call common code */
1915     if(SDIputattr(&var->attrs, _HDF_ValidRange, var->HDFtype, (intn) 2, data) == FAIL)
1916       {
1917     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
1918           /* Should propagate error code */
1919       }
1920 
1921     /* make sure it gets reflected in the file */
1922     handle->flags |= NC_HDIRTY;
1923 
1924 done:
1925     if (ret_value == FAIL)
1926       { /* Failure cleanup */
1927 
1928       }
1929     /* Normal cleanup */
1930 
1931 
1932     return ret_value;
1933 } /* SDsetrange */
1934 
1935 #ifdef MFSD_INTERNAL
1936 /******************************************************************************
1937  NAME
1938     SDIapfromid -- get the attribute list
1939 
1940  DESCRIPTION
1941     Given a ID figure out what the handle and attribute
1942     list pointer are for that object.
1943 
1944  RETURNS
1945      On error FAIL else SUCCEED.
1946 
1947 ******************************************************************************/
1948 intn
SDIapfromid(int32 id,NC ** handlep,NC_array *** app)1949 SDIapfromid(int32       id,      /* IN:  object ID */
1950             NC        **handlep, /* IN:  handle for this file */
1951             NC_array ***app      /* OUT: attribute list */)
1952 {
1953     CONSTR(FUNC, "SDIapfromid");    /* for HGOTO_ERROR */
1954     NC     *handle = NULL;
1955     NC_var *var = NULL;
1956     NC_dim *dim = NULL;
1957     int32   varid;
1958     intn    ret_value = SUCCEED;
1959 
1960     /* see if its a variable ID */
1961     handle = SDIhandle_from_id(id, SDSTYPE);
1962     if(handle != NULL)
1963       {
1964           /* find the variable */
1965           var = SDIget_var(handle, id);
1966           if(var == NULL)
1967             {
1968                 HGOTO_ERROR(DFE_ARGS, FAIL);
1969             }
1970 
1971           (*app) = &(var->attrs);
1972           (*handlep) = handle;
1973     HGOTO_DONE(SUCCEED);
1974       }
1975 
1976     /* see if its a file ID */
1977     handle = SDIhandle_from_id(id, CDFTYPE);
1978     if(handle != NULL)
1979       {
1980           (*app) = &(handle->attrs);
1981           (*handlep) = handle;
1982     HGOTO_DONE(SUCCEED);
1983       }
1984 
1985     /* see if its a dimension ID */
1986     handle = SDIhandle_from_id(id, DIMTYPE);
1987     if(handle != NULL)
1988       {
1989           /* find the dimension */
1990           dim = SDIget_dim(handle, id);
1991 
1992           /* the ID is neither file, data set, nor dimension ID */
1993           if(dim == NULL)
1994             {
1995                 HGOTO_ERROR(DFE_ARGS, FAIL);
1996             }
1997 
1998           /* get index of coordinate variable */
1999           varid = SDIgetcoordvar(handle, dim, (int32)(id & 0xffff), (int32) 0);
2000 
2001           /* get the variable object */
2002           var = NC_hlookupvar(handle, varid);
2003           if(var == NULL)
2004             {
2005                 HGOTO_ERROR(DFE_ARGS, FAIL);
2006             }
2007 
2008 
2009           (*app) = &(var->attrs);
2010           (*handlep) = handle;
2011     HGOTO_DONE(SUCCEED);
2012       }
2013 
2014     ret_value = FAIL;
2015 
2016 done:
2017     if (ret_value == FAIL)
2018       { /* Failure cleanup */
2019 
2020       }
2021     /* Normal cleanup */
2022 
2023     return ret_value;
2024 } /* SDIapfromid */
2025 
2026 #endif /* MFSD_INTERNAL */
2027 
2028 /******************************************************************************
2029  NAME
2030    SDsetattr -- user level function to create and set an attribute
2031 
2032  DESCRIPTION
2033    Given an ID and an attribute defintion attach the atrribute
2034    to the thing represented by the ID.  For starters, the valid
2035    IDs could be variable, file or dimesnion IDs
2036 
2037  RETURNS
2038    On error FAIL else SUCCEED.
2039 
2040 ******************************************************************************/
2041 intn
SDsetattr(int32 id,const char * name,int32 nt,int32 count,const void * data)2042 SDsetattr(int32 id,    /* IN: object ID */
2043           const char *name,  /* IN: attribute name */
2044           int32 nt,    /* IN: attribute number type */
2045           int32 count, /* IN: number of attribute values */
2046           const void * data   /* IN: attribute values */)
2047 {
2048     CONSTR(FUNC, "SDsetattr");    /* for HGOTO_ERROR */
2049     NC_array **ap = NULL;
2050     NC        *handle = NULL;
2051     intn       sz;
2052     intn       ret_value = SUCCEED;
2053 
2054 #ifdef SDDEBUG
2055     fprintf(stderr, "SDsetattr: I've been called\n");
2056 #endif
2057 
2058     /* Clear error stack */
2059     HEclear();
2060 
2061     /* Sanity check args */
2062     if(name == NULL)
2063       {
2064     HGOTO_ERROR(DFE_ARGS, FAIL);
2065       }
2066 
2067     /* This release doesn't support native number types for attr  */
2068     if (nt & DFNT_NATIVE)
2069       {
2070     HGOTO_ERROR(DFE_ARGS, FAIL);
2071       }
2072 
2073     /* Only positive count is valid (bug HDFFR-989) -BMR */
2074     if (count <= 0)
2075       {
2076     HGOTO_ERROR(DFE_ARGS, FAIL);
2077       }
2078 
2079     /* Make sure that count is less than MAX_ORDER(Vdata)
2080            and total size is less than MAX_FIELD_SIZE(Vdata) */
2081     if (FAIL == (sz = DFKNTsize(nt)))
2082       {
2083     HGOTO_ERROR(DFE_ARGS, FAIL);
2084       }
2085 
2086     if ((count > MAX_ORDER) ||
2087         ((count * sz) > MAX_FIELD_SIZE))
2088       {
2089     HGOTO_ERROR(DFE_ARGS, FAIL);
2090       }
2091 
2092     /* determine what type of ID we've been given */
2093     if(SDIapfromid(id, &handle, &ap) == FAIL)
2094       {
2095     HGOTO_ERROR(DFE_ARGS, FAIL);
2096       }
2097 
2098     /* still no handle ? */
2099     if(handle == NULL)
2100       {
2101     HGOTO_ERROR(DFE_ARGS, FAIL);
2102       }
2103 
2104     /* hand over to SDIputattr */
2105 
2106     if(SDIputattr(ap, name, nt, count, data) == FAIL)
2107       {
2108     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2109       }
2110 
2111     /* make sure it gets reflected in the file */
2112     handle->flags |= NC_HDIRTY;
2113 
2114 done:
2115     if (ret_value == FAIL)
2116       { /* Failure cleanup */
2117 
2118       }
2119     /* Normal cleanup */
2120 
2121 
2122     return ret_value;
2123 } /* SDsetattr */
2124 
2125 
2126 /******************************************************************************
2127  NAME
2128     SDattrinfo -- get info about an attribute
2129 
2130  DESCRIPTION
2131     Inquire about an attribute.  Attribute indexes are zero based.
2132 
2133     Given the ID of the attribute's parent and the attribute's
2134     index return the number type, name and count of the attribute
2135     so the user knows how much space to provide to read it
2136 
2137  RETURNS
2138         On error FAIL else SUCCEED.
2139 ******************************************************************************/
2140 intn
SDattrinfo(int32 id,int32 index,char * name,int32 * nt,int32 * count)2141 SDattrinfo(int32  id,    /* IN:  object ID */
2142            int32  index, /* IN:  attribute index */
2143            char  *name,  /* OUT: attribute name */
2144            int32 *nt,    /* OUT: attribute number type */
2145            int32 *count  /* OUT: number of attribute values */)
2146 {
2147     CONSTR(FUNC, "SDattrinfo");    /* for HGOTO_ERROR */
2148     NC_array  *ap = NULL;
2149     NC_array **app = NULL;
2150     NC_attr  **atp = NULL;
2151     NC        *handle = NULL;
2152     intn       ret_value = SUCCEED;
2153 
2154 #ifdef SDDEBUG
2155     fprintf(stderr, "SDattrinfo: I've been called\n");
2156 #endif
2157 
2158     /* clear error stack */
2159     HEclear();
2160 
2161     /* sanity check args */
2162     if((name == NULL) || (nt == NULL) || (count == NULL))
2163         HGOTO_ERROR(DFE_ARGS, FAIL);
2164 
2165     /* determine what type of ID we've been given */
2166     if(SDIapfromid(id, &handle, &app) == FAIL)
2167       {
2168     HGOTO_ERROR(DFE_ARGS, FAIL);
2169       }
2170 
2171     ap = (*app);
2172     if((ap == NULL) || (index >= ap->count))
2173       {
2174     HGOTO_ERROR(DFE_ARGS, FAIL);
2175       }
2176 
2177     /*
2178      * ap is the proper attribute list now look up something with this
2179      *  name
2180      */
2181     atp = (NC_attr **) ((char *)ap->values + index * ap->szof);
2182     if(*atp == NULL)
2183       {
2184     HGOTO_ERROR(DFE_ARGS, FAIL);
2185       }
2186 
2187     /* move the information over */
2188     if(name != NULL)
2189       {
2190 #if 0
2191           HDstrncpy(name, (*atp)->name->values, (*atp)->name->len);
2192 #endif
2193           HDmemcpy(name, (*atp)->name->values, (*atp)->name->len);
2194           name[(*atp)->name->len] = '\0';
2195       }
2196 
2197     *count = (*atp)->data->count;
2198     *nt = (*atp)->HDFtype;
2199 
2200 done:
2201     if (ret_value == FAIL)
2202       { /* Failure cleanup */
2203 
2204       }
2205     /* Normal cleanup */
2206 
2207 
2208     return ret_value;
2209 } /* SDattrinfo */
2210 
2211 
2212 /******************************************************************************
2213  NAME
2214     SDreadattr -- read an attribute's values
2215 
2216  DESCRIPTION
2217     Read the actual contents of the given attribute
2218     Assume that the user has called SDinqattr() and so
2219     has allocated sufficient space
2220 
2221  RETURNS
2222     On error FAIL else SUCCEED.
2223 
2224 ******************************************************************************/
2225 intn
SDreadattr(int32 id,int32 index,void * buf)2226 SDreadattr(int32 id,    /* IN:  object ID */
2227            int32 index, /* IN:  attribute index */
2228            void * buf    /* OUT: data buffer  */)
2229 {
2230     CONSTR(FUNC, "SDreadattr");    /* for HGOTO_ERROR */
2231     NC_array  *ap = NULL;
2232     NC_array **app = NULL;
2233     NC_attr  **atp = NULL;
2234     NC        *handle = NULL;
2235     intn       ret_value = SUCCEED;
2236 
2237 #ifdef SDDEBUG
2238     fprintf(stderr, "SDreadattr: I've been called\n");
2239 #endif
2240 
2241     /* clear error stack */
2242     HEclear();
2243 
2244     /* sanity check args */
2245     if(buf == NULL)
2246         HGOTO_ERROR(DFE_ARGS, FAIL);
2247 
2248     /* determine what type of ID we've been given */
2249     if(SDIapfromid(id, &handle, &app) == FAIL)
2250       {
2251     HGOTO_ERROR(DFE_ARGS, FAIL);
2252       }
2253 
2254     ap = (*app);
2255     if((ap == NULL) || (index >= ap->count))
2256       {
2257     HGOTO_ERROR(DFE_ARGS, FAIL);
2258       }
2259 
2260     /*
2261      * ap is the proper attribute list now look up something with this
2262      *  index
2263      */
2264     atp = (NC_attr **) ((char *)ap->values + index * ap->szof);
2265     if(*atp == NULL)
2266       {
2267     HGOTO_ERROR(DFE_ARGS, FAIL);
2268       }
2269 
2270     /* move the information over */
2271     HDmemcpy(buf, (*atp)->data->values, (*atp)->data->count * (*atp)->data->szof);
2272 
2273 done:
2274     if (ret_value == FAIL)
2275       { /* Failure cleanup */
2276 
2277       }
2278     /* Normal cleanup */
2279 
2280 
2281     return ret_value;
2282 } /* SDreadattr */
2283 
2284 
2285 /******************************************************************************
2286  NAME
2287     SDwritedata -- write a hyperslab of data
2288 
2289  DESCRIPTION
2290     Write out a chunk o data.  Except for the line setting the
2291     XDR op-code this is exactly the same as SDreaddata().  The
2292     two routines should really be combined at some point
2293 
2294  RETURNS
2295     SUCCEED / FAIL
2296 
2297 ******************************************************************************/
2298 intn
SDwritedata(int32 sdsid,int32 * start,int32 * stride,int32 * end,void * data)2299 SDwritedata(int32  sdsid,  /* IN: dataset ID */
2300             int32 *start,  /* IN: coords of starting point */
2301             int32 *stride, /* IN: stride along each dimension */
2302             int32 *end,    /* IN: number of values to write per dimension */
2303             void *  data    /* IN: data buffer */)
2304 {
2305     CONSTR(FUNC, "SDwritedata");    /* for HGOTO_ERROR */
2306     intn    varid;
2307     int32   status;
2308     comp_coder_t comp_type;
2309     uint32  comp_config;
2310     NC_var *var;
2311     NC     *handle = NULL;
2312     NC_dim *dim = NULL;
2313 #ifdef H4_BIG_LONGS
2314     long    Start[H4_MAX_VAR_DIMS];
2315     long    End[H4_MAX_VAR_DIMS];
2316     long    Stride[H4_MAX_VAR_DIMS];
2317 #else
2318     long   *Start = NULL;
2319     long   *End = NULL;
2320     long   *Stride = NULL;
2321 #endif
2322     intn    no_strides = 0;
2323     intn    ret_value = SUCCEED;
2324 
2325 #ifdef SDDEBUG
2326     fprintf(stderr, "SDwritedata: I've been called\n");
2327 #endif
2328 
2329     /* this decides how a dataset with unlimited dimension is written along the
2330        unlimited dimension; the behavior is different between SD and nc APIs */
2331     cdf_routine_name = "SDwritedata";
2332 
2333     /* clear error stack */
2334     HEclear();
2335 
2336     if((start == NULL) || (end == NULL) || (data == NULL))
2337         HGOTO_ERROR(DFE_ARGS, FAIL);
2338 
2339     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2340     if(handle == NULL)
2341       {
2342         handle = SDIhandle_from_id(sdsid, DIMTYPE);
2343         if(handle == NULL)
2344             HGOTO_ERROR(DFE_ARGS, FAIL);
2345 
2346         dim = SDIget_dim(handle, sdsid);
2347       }
2348 
2349     if(handle->vars == NULL)
2350         HGOTO_ERROR(DFE_ARGS, FAIL);
2351 
2352     var = SDIget_var(handle, sdsid);
2353 
2354     if(var == NULL)
2355         HGOTO_ERROR(DFE_ARGS, FAIL);
2356 
2357     /* Check if compression method is enabled */
2358 
2359     /* Make sure that the file is an HDF file before checking about compression */
2360     if(handle->file_type == HDF_FILE) /* bug HDFFR-473 */
2361     {
2362     status = HCPgetcomptype(handle->hdf_file, var->data_tag, var->data_ref,
2363                 &comp_type);
2364 
2365     if (status != FAIL)
2366         if (comp_type != COMP_CODE_NONE && comp_type != COMP_CODE_INVALID)
2367         {
2368         /* Must have encoder to write data */
2369         HCget_config_info( comp_type , &comp_config);
2370         if ((comp_config & COMP_ENCODER_ENABLED) == 0)
2371         { /* encoder not present?? */
2372             HGOTO_ERROR(DFE_BADCODER, FAIL);
2373         }
2374         }
2375     /* When HCPgetcomptype returns FAIL, assume no compression */
2376     } /* file is HDF */
2377 
2378     /* get ready to write */
2379     handle->xdrs->x_op = XDR_ENCODE;
2380 
2381     /*
2382      * figure out the index of the variable to write to
2383      * the user might have passed us a dimension, in which
2384      * case we want to write to its coordinate variable
2385      */
2386     if(dim)
2387       {
2388         varid = SDIgetcoordvar(handle, dim, (int32)(sdsid & 0xffff), (int32) 0);
2389       }
2390     else
2391       {
2392         /* oops, how do we know this ? */
2393         varid = (intn)sdsid & 0xffff;
2394       }
2395 
2396     /* Check for strides all set to '1', so it acts like NULL was passed */
2397     if(stride!=NULL)
2398       {
2399         int i;
2400         NC_var *var = SDIget_var(handle, sdsid);
2401 
2402         if(var == NULL)
2403           {
2404               HGOTO_ERROR(DFE_ARGS, FAIL);
2405           }
2406 
2407         no_strides=1;
2408         /* if the stride for any dim. is not '1', real stride processing has to occur */
2409         for(i = 0; i < var->assoc->count; i++)
2410           {
2411               if(stride[i]!=1)
2412                   no_strides=0;
2413           }
2414       } /* end if */
2415 
2416     /*
2417      * In general, (long) == int32
2418      * In cases where it doesn't we need to convert
2419      */
2420 #ifdef H4_BIG_LONGS
2421 
2422     {
2423         int i;
2424         NC_var *var = SDIget_var(handle, sdsid);
2425 
2426         if(var == NULL)
2427           {
2428               HGOTO_ERROR(DFE_ARGS, FAIL);
2429           }
2430 
2431         for(i = 0; i < var->assoc->count; i++)
2432           {
2433             Start[i]  = (long) start[i];
2434             End[i]    = (long) end[i];
2435             if(stride)
2436                 Stride[i] = (long) stride[i];
2437           }
2438     }
2439 
2440 #else
2441 
2442     Start  = (long *)start;
2443     End    = (long *)end;
2444     Stride = (long *)stride;
2445 
2446 #endif
2447 
2448     /* Check if this data is being written out to a newly created dataset */
2449     {
2450         NC_var *var = SDIget_var(handle, sdsid);
2451 
2452         if(var->created) {
2453             if(!IS_RECVAR(var) && (handle->flags & NC_NOFILL) ) {
2454               var->set_length=TRUE;
2455             } /* end if */
2456             var->created=FALSE;
2457         } /* end if */
2458     }
2459 
2460     /* call the writeg routines if a stride is given */
2461     if(stride == NULL || no_strides==1)
2462         status = NCvario(handle, varid, Start, End, (Void *)data);
2463     else
2464         status = NCgenio(handle, varid, Start, End, Stride, NULL, data);
2465 
2466     if(status == -1)
2467         ret_value = FAIL;
2468     else
2469         ret_value = SUCCEED;
2470 
2471 done:
2472     if (ret_value == FAIL)
2473       { /* Failure cleanup */
2474 
2475       }
2476     /* Normal cleanup */
2477 
2478 
2479     return ret_value;
2480 } /* SDwritedata */
2481 
2482 
2483 /******************************************************************************
2484  NAME
2485     SDsetdatastrs -- set "data strings"
2486 
2487  DESCRIPTION
2488     Store information about the 'label', 'units', 'format' and
2489     'cordsys' attributes of a dataset.  All of the values
2490     are optional.  If no string is desired NULL should be passed
2491     in its place.
2492 
2493  RETURNS
2494     SUCCEED / FAIL
2495 
2496 ******************************************************************************/
2497 intn
SDsetdatastrs(int32 sdsid,const char * l,const char * u,const char * f,const char * c)2498 SDsetdatastrs(int32 sdsid, /* IN: dataset ID */
2499               const char *l,     /* IN: label string ("long_name") */
2500               const char *u,     /* IN: units string ("units") */
2501               const char *f,     /* IN: format string ("format") */
2502               const char *c      /* IN: coordsys string ("coordsys") */)
2503 {
2504     CONSTR(FUNC, "SDsetdatastrs");    /* for HGOTO_ERROR */
2505     NC     *handle = NULL;
2506     NC_var *var = NULL;
2507     intn    ret_value = SUCCEED;
2508 
2509 #ifdef SDDEBUG
2510     fprintf(stderr, "SDsetdatastrs: I've been called\n");
2511 #endif
2512 
2513     /* clear error stack */
2514     HEclear();
2515 
2516     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2517     if(handle == NULL)
2518       {
2519     HGOTO_ERROR(DFE_ARGS, FAIL);
2520       }
2521 
2522     if(handle->vars == NULL)
2523       {
2524     HGOTO_ERROR(DFE_ARGS, FAIL);
2525       }
2526 
2527     var = SDIget_var(handle, sdsid);
2528     if(var == NULL)
2529       {
2530     HGOTO_ERROR(DFE_ARGS, FAIL);
2531       }
2532 
2533     if(l && l[0] != '\0')
2534       {
2535         if(SDIputattr(&var->attrs, _HDF_LongName, DFNT_CHAR,
2536                       (intn) HDstrlen(l), l) == FAIL)
2537           {
2538               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2539           }
2540       }
2541 
2542     if(u && u[0] != '\0')
2543       {
2544         if(SDIputattr(&var->attrs, _HDF_Units, DFNT_CHAR,
2545                       (intn) HDstrlen(u), u) == FAIL)
2546           {
2547               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2548           }
2549       }
2550 
2551     if(f && f[0] != '\0')
2552       {
2553         if(SDIputattr(&var->attrs, _HDF_Format, DFNT_CHAR,
2554                       (intn) HDstrlen(f), f) == FAIL)
2555           {
2556               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2557           }
2558       }
2559 
2560     if(c && c[0] !='\0')
2561       {
2562         if(SDIputattr(&var->attrs, _HDF_CoordSys, DFNT_CHAR,
2563                       (intn) HDstrlen(c), c) == FAIL)
2564           {
2565               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2566           }
2567       }
2568 
2569     /* make sure it gets reflected in the file */
2570     if(l || u || f || c)
2571         handle->flags |= NC_HDIRTY;
2572 
2573 done:
2574     if (ret_value == FAIL)
2575       { /* Failure cleanup */
2576 
2577       }
2578     /* Normal cleanup */
2579 
2580 
2581     return ret_value;
2582 } /* SDsetdatastrs */
2583 
2584 
2585 /******************************************************************************
2586  NAME
2587     SDsetcal -- set calibration information
2588 
2589  DESCRIPTION
2590     Store calibration information.  What is the formula? Good question -GV
2591 
2592  RETURNS
2593     SUCCEED / FAIL
2594 
2595 ******************************************************************************/
2596 intn
SDsetcal(int32 sdsid,float64 cal,float64 cale,float64 ioff,float64 ioffe,int32 nt)2597 SDsetcal(int32   sdsid,/* IN: dataset ID */
2598          float64 cal,  /* IN: multiplicative factor */
2599          float64 cale, /* IN: multiplicative factor error */
2600          float64 ioff, /* IN: integer offset */
2601          float64 ioffe,/* IN: integer offset error */
2602          int32   nt    /* IN: number type of uncalibrated data */)
2603 {
2604     CONSTR(FUNC, "SDsetcal");    /* for HGOTO_ERROR */
2605     NC     *handle = NULL;
2606     NC_var *var = NULL;
2607     intn    ret_value = SUCCEED;
2608 
2609 #ifdef SDDEBUG
2610     fprintf(stderr, "SDsetcal: I've been called\n");
2611 #endif
2612 
2613     /* clear error stack */
2614     HEclear();
2615 
2616     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2617     if(handle == NULL)
2618       {
2619     HGOTO_ERROR(DFE_ARGS, FAIL);
2620       }
2621 
2622     if(handle->vars == NULL)
2623       {
2624     HGOTO_ERROR(DFE_ARGS, FAIL);
2625       }
2626 
2627     var = SDIget_var(handle, sdsid);
2628     if(var == NULL)
2629       {
2630     HGOTO_ERROR(DFE_ARGS, FAIL);
2631       }
2632 
2633     if(SDIputattr(&var->attrs, _HDF_ScaleFactor, DFNT_FLOAT64,
2634                   (intn) 1, &cal) == FAIL)
2635       {
2636     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2637       }
2638 
2639     if(SDIputattr(&var->attrs, _HDF_ScaleFactorErr, DFNT_FLOAT64,
2640                   (intn) 1, &cale) == FAIL)
2641       {
2642     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2643       }
2644 
2645     if(SDIputattr(&var->attrs, _HDF_AddOffset, DFNT_FLOAT64,
2646                   (intn) 1, &ioff) == FAIL)
2647       {
2648     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2649       }
2650 
2651     if(SDIputattr(&var->attrs, _HDF_AddOffsetErr, DFNT_FLOAT64,
2652                   (intn) 1, &ioffe) == FAIL)
2653       {
2654     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2655       }
2656 
2657     if(SDIputattr(&var->attrs, _HDF_CalibratedNt, DFNT_INT32,
2658                   (intn) 1, &nt) == FAIL)
2659       {
2660     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2661       }
2662 
2663     /* make sure it gets reflected in the file */
2664     handle->flags |= NC_HDIRTY;
2665 
2666 done:
2667     if (ret_value == FAIL)
2668       { /* Failure cleanup */
2669 
2670       }
2671     /* Normal cleanup */
2672 
2673 
2674     return ret_value;
2675 } /* SDsetcal */
2676 
2677 
2678 /******************************************************************************
2679  NAME
2680     SDsetfillvalue -- set the fill value
2681 
2682  DESCRIPTION
2683     Set the fill value for this data set.  The fill value
2684     is assumed to have the same number type as the dataset
2685 
2686  RETURNS
2687     SUCCEED / FAIL
2688 
2689 ******************************************************************************/
2690 intn
SDsetfillvalue(int32 sdsid,void * val)2691 SDsetfillvalue(int32 sdsid, /* IN: dataset ID */
2692                void * val    /* IN: fillvalue */)
2693 {
2694     CONSTR(FUNC, "SDsetfillvalue");    /* for HGOTO_ERROR */
2695     NC     *handle = NULL;
2696     NC_var *var = NULL;
2697     intn    ret_value = SUCCEED;
2698 
2699 #ifdef SDDEBUG
2700     fprintf(stderr, "SDsetfillvalue: I've been called\n");
2701 #endif
2702 
2703     /* clear error stack */
2704     HEclear();
2705 
2706     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2707     if(handle == NULL)
2708       {
2709     HGOTO_ERROR(DFE_ARGS, FAIL);
2710       }
2711 
2712     if(handle->vars == NULL)
2713       {
2714     HGOTO_ERROR(DFE_ARGS, FAIL);
2715       }
2716 
2717     var = SDIget_var(handle, sdsid);
2718     if(var == NULL)
2719       {
2720     HGOTO_ERROR(DFE_ARGS, FAIL);
2721       }
2722 
2723     if(SDIputattr(&var->attrs, _FillValue, var->HDFtype,
2724                   (intn) 1, val) == FAIL)
2725       {
2726     HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
2727       }
2728 
2729     /* make sure it gets reflected in the file */
2730     handle->flags |= NC_HDIRTY;
2731 
2732 done:
2733     if (ret_value == FAIL)
2734       { /* Failure cleanup */
2735 
2736       }
2737     /* Normal cleanup */
2738 
2739 
2740     return ret_value;
2741 } /* SDsetfillvalue */
2742 
2743 
2744 /******************************************************************************
2745  NAME
2746     SDgetfillvalue -- get the fill value
2747 
2748  DESCRIPTION
2749     Retreive the fill value for this data set if one has been
2750     stored.  The fill value has the same number type as the
2751     dataset
2752 
2753  RETURNS
2754     SUCCEED / FAIL
2755 
2756 ******************************************************************************/
2757 intn
SDgetfillvalue(int32 sdsid,void * val)2758 SDgetfillvalue(int32 sdsid, /* IN:  dataset ID */
2759                void * val    /* OUT: fillvalue */)
2760 {
2761     CONSTR(FUNC, "SDgetfillvalue");    /* for HGOTO_ERROR */
2762     NC       *handle = NULL;
2763     NC_var   *var = NULL;
2764     NC_attr **attr = NULL;
2765     intn      ret_value = SUCCEED;
2766 
2767 #ifdef SDDEBUG
2768     fprintf(stderr, "SDgetfillvalue: I've been called\n");
2769 #endif
2770 
2771     /* clear error stack */
2772     HEclear();
2773 
2774     /* sanity check args */
2775     if(val == NULL)
2776         HGOTO_ERROR(DFE_ARGS, FAIL);
2777 
2778     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2779     if(handle == NULL)
2780       {
2781     HGOTO_ERROR(DFE_ARGS, FAIL);
2782       }
2783 
2784     if(handle->vars == NULL)
2785       {
2786     HGOTO_ERROR(DFE_ARGS, FAIL);
2787       }
2788 
2789     var = SDIget_var(handle, sdsid);
2790     if(var == NULL)
2791       {
2792     HGOTO_ERROR(DFE_ARGS, FAIL);
2793       }
2794 
2795     attr = (NC_attr **) NC_findattr(&(var->attrs), _FillValue);
2796     if(attr == NULL)
2797       {
2798     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
2799       }
2800 
2801     NC_copy_arrayvals((char *)val, (*attr)->data) ;
2802 
2803 done:
2804     if (ret_value == FAIL)
2805       { /* Failure cleanup */
2806 
2807       }
2808     /* Normal cleanup */
2809 
2810 
2811     return ret_value;
2812 } /* SDgetfillvalue */
2813 
2814 
2815 /******************************************************************************
2816  NAME
2817     SDgetdatastrs -- get "data strings"
2818 
2819  DESCRIPTION
2820     Read information about the 'label', 'units', 'format' and
2821     'cordsys' attributes of a dataset.  All of the values
2822      are optional.  If no string is desired NULL should be passed
2823      in its place.  Assume all buffers are len bytes long.
2824 
2825  RETURNS
2826     SUCCEED / FAIL
2827 
2828 ******************************************************************************/
2829 intn
SDgetdatastrs(int32 sdsid,char * l,char * u,char * f,char * c,intn len)2830 SDgetdatastrs(int32 sdsid, /* IN:  dataset ID */
2831               char *l,     /* OUT: label string ("long_name") */
2832               char *u,     /* OUT: units string ("units") */
2833               char *f,     /* OUT: format string ("format") */
2834               char *c,     /* OUT: coordsys string ("coordsys") */
2835               intn  len    /* IN:  buffer length */)
2836 {
2837     CONSTR(FUNC, "SDgetdatastrs");    /* for HGOTO_ERROR */
2838     NC       *handle = NULL;
2839     NC_var   *var = NULL;
2840     NC_attr **attr = NULL;
2841     intn      ret_value = SUCCEED;
2842 
2843 #ifdef SDDEBUG
2844     fprintf(stderr, "SDgetdatastrs: I've been called\n");
2845 #endif
2846 
2847     /* clear error stack */
2848     HEclear();
2849 
2850     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2851     if(handle == NULL)
2852       {
2853     HGOTO_ERROR(DFE_ARGS, FAIL);
2854       }
2855 
2856     if(handle->vars == NULL)
2857       {
2858     HGOTO_ERROR(DFE_ARGS, FAIL);
2859       }
2860 
2861     var = SDIget_var(handle, sdsid);
2862     if(var == NULL)
2863       {
2864     HGOTO_ERROR(DFE_ARGS, FAIL);
2865       }
2866 
2867     if(l)
2868       {
2869           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_LongName);
2870           if(attr != NULL)
2871             {
2872                 if((*attr)->data->count < (unsigned)len)
2873                   {
2874                       HDstrncpy((char *)l, (*attr)->data->values,(*attr)->data->count );
2875                       l[(*attr)->data->count] = '\0';
2876                   }
2877                 else
2878                     HDstrncpy((char *)l, (*attr)->data->values,len );
2879             }
2880           else
2881               l[0] = '\0';
2882       }
2883 
2884     if(u)
2885       {
2886           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_Units);
2887           if(attr != NULL)
2888             {
2889                 if((*attr)->data->count < (unsigned)len)
2890                   {
2891                       HDstrncpy((char *)u, (*attr)->data->values,(*attr)->data->count );
2892                       u[(*attr)->data->count] = '\0';
2893                   }
2894                 else
2895                     HDstrncpy((char *)u, (*attr)->data->values, len);
2896 
2897             }
2898           else
2899               u[0] = '\0';
2900       }
2901 
2902     if(f)
2903       {
2904           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_Format);
2905           if(attr != NULL)
2906             {
2907                 if((*attr)->data->count < (unsigned)len)
2908                   {
2909                       HDstrncpy((char *)f, (*attr)->data->values, (*attr)->data->count);
2910                       f[(*attr)->data->count] = '\0';
2911                   }
2912                 else
2913                     HDstrncpy((char *)f, (*attr)->data->values, len);
2914             }
2915           else
2916               f[0] = '\0';
2917       }
2918 
2919     if(c)
2920       {
2921           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_CoordSys);
2922           if(attr != NULL)
2923             {
2924                 if((*attr)->data->count < (unsigned)len)
2925                   {
2926                       HDstrncpy((char *)c, (*attr)->data->values, (*attr)->data->count);
2927                       c[(*attr)->data->count] = '\0';
2928                   }
2929                 else
2930                     HDstrncpy((char *)c, (*attr)->data->values, len);
2931 
2932             }
2933           else
2934               c[0] = '\0';
2935       }
2936 
2937 done:
2938     if (ret_value == FAIL)
2939       { /* Failure cleanup */
2940 
2941       }
2942     /* Normal cleanup */
2943 
2944 
2945     return ret_value;
2946 } /* SDgetdatastrs */
2947 
2948 
2949 /******************************************************************************
2950  NAME
2951     SDgetcal -- get calibration information
2952 
2953  DESCRIPTION
2954     Retreive calibration information.  What is the formula?
2955 
2956  RETURNS
2957     SUCCEED / FAIL
2958 
2959 ******************************************************************************/
2960 intn
SDgetcal(int32 sdsid,float64 * cal,float64 * cale,float64 * ioff,float64 * ioffe,int32 * nt)2961 SDgetcal(int32    sdsid, /* IN:  dataset ID */
2962          float64 *cal,   /* OUT: multiplicative factor */
2963          float64 *cale,  /* OUT: multiplicative factor error */
2964          float64 *ioff,  /* OUT: integer offset  */
2965          float64 *ioffe, /* OUT: integer offset error */
2966          int32   *nt     /* OUT: number type of uncalibrated data */)
2967 {
2968     CONSTR(FUNC, "SDgetcal");    /* for HGOTO_ERROR */
2969     NC       *handle = NULL;
2970     NC_var   *var    = NULL;
2971     NC_attr **attr   = NULL;
2972     intn      ret_value = SUCCEED;
2973 
2974 #ifdef SDDEBUG
2975     fprintf(stderr, "SDgetcal: I've been called\n");
2976 #endif
2977 
2978     /* clear error stack */
2979     HEclear();
2980 
2981     handle = SDIhandle_from_id(sdsid, SDSTYPE);
2982     if(handle == NULL)
2983       {
2984     HGOTO_ERROR(DFE_ARGS, FAIL);
2985       }
2986 
2987     if(handle->vars == NULL)
2988       {
2989     HGOTO_ERROR(DFE_ARGS, FAIL);
2990       }
2991 
2992     var = SDIget_var(handle, sdsid);
2993     if(var == NULL)
2994       {
2995     HGOTO_ERROR(DFE_ARGS, FAIL);
2996       }
2997 
2998     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_ScaleFactor);
2999     if(attr == NULL)
3000       {
3001     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
3002       }
3003     NC_copy_arrayvals((char *)cal, (*attr)->data) ;
3004 
3005     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_ScaleFactorErr);
3006     if(attr == NULL)
3007       {
3008     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
3009       }
3010     NC_copy_arrayvals((char *)cale, (*attr)->data) ;
3011 
3012     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_AddOffset);
3013     if(attr == NULL)
3014       {
3015     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
3016       }
3017     NC_copy_arrayvals((char *)ioff, (*attr)->data) ;
3018 
3019     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_AddOffsetErr);
3020     if(attr == NULL)
3021       {
3022     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
3023       }
3024     NC_copy_arrayvals((char *)ioffe, (*attr)->data) ;
3025 
3026     attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_CalibratedNt);
3027     if(attr == NULL)
3028       {
3029     HGOTO_ERROR(DFE_CANTGETATTR, FAIL);
3030       }
3031     NC_copy_arrayvals((char *)nt, (*attr)->data) ;
3032 
3033 done:
3034     if (ret_value == FAIL)
3035       { /* Failure cleanup */
3036 
3037       }
3038     /* Normal cleanup */
3039 
3040 
3041     return ret_value;
3042 } /* SDgetcal */
3043 
3044 #ifdef MFSD_INTERNAL
3045 /******************************************************************************
3046  NAME
3047     SDgetcoordvar -- get index of coordinate variable
3048 
3049  DESCRIPTION
3050     Given a dimension return the index of its coordinate variable
3051     creating one if needed.  If we need to create a variable and an nt
3052     is not supplied (i.e. is equal to zero) use 32bit floats.
3053 
3054     If the variable already exists and the existing nt is different
3055     from the supplied one (and the supplied one is not zero) replace
3056     the nt by the new one.  ID is needed so that we can set the
3057     dimension of the variable correctly if we need to.  Yuck.
3058 
3059  RETURNS
3060      A variable index or FAIL on error
3061 
3062 ******************************************************************************/
3063 int32
SDIgetcoordvar(NC * handle,NC_dim * dim,int32 id,int32 nt)3064 SDIgetcoordvar(NC     *handle, /* IN: file handle */
3065                NC_dim *dim,    /* IN: dimension to find coord var of */
3066                int32   id,     /* IN: dimension ID */
3067                int32   nt      /* IN: number type to use if new variable*/)
3068 {
3069     CONSTR(FUNC, "SDIgetcoordvar");    /* for HGOTO_ERROR */
3070     unsigned      ii;
3071     unsigned      len;
3072     nc_type    nctype;
3073     intn       dimindex;
3074     NC_string *name = NULL;
3075     NC_var   **dp = NULL;
3076     NC_var    *var = NULL;
3077     int32      ret_value = FAIL;
3078 
3079     /* look for a variable with the same name */
3080     name = dim->name;
3081     len = dim->name->len;
3082     dp = (NC_var**)handle->vars->values ;
3083     for(ii = 0 ; ii < handle->vars->count ; ii++, dp++)
3084       {
3085     /* eliminate vars with rank > 1, coord vars only have rank 1 */
3086     if((*dp)->assoc->count == 1)
3087             if( len == (*dp)->name->len
3088               && HDstrncmp(name->values, (*dp)->name->values, (size_t)len) == 0)
3089         /* only proceed if the file is a netCDF file (bugz 1644)
3090         or if this variable is a coordinate var or when
3091         the status is unknown due to its being created prior to
3092         the fix of bugzilla 624 - BMR 05/14/2007 */
3093         if ((handle->file_type != HDF_FILE) ||
3094             (*dp)->var_type == IS_CRDVAR || (*dp)->var_type == UNKNOWN)
3095         {
3096             /* see if we need to change the number type */
3097             if((nt != 0) && (nt != (*dp)->type))
3098             {
3099 #ifdef SDDEBUG
3100                       fprintf(stderr, "SDIgetcoordvar redefining type\n");
3101 #endif
3102                       if (((*dp)->type = hdf_unmap_type((int)nt)) == FAIL)
3103                         {
3104 #ifdef SDDEBUG
3105                             /* replace it with NCAdvice or HERROR? */
3106                             fprintf(stderr, "SDIgetcoordvar: hdf_unmap_type failed for %d\n", nt);
3107 #endif
3108                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
3109                         }
3110 
3111                       (*dp)->HDFtype = nt;
3112                       (*dp)->cdf = handle;
3113                       /* don't forget to reset the sizes  */
3114                       (*dp)->szof = NC_typelen((*dp)->type);
3115                       if (FAIL == ((*dp)->HDFsize = DFKNTsize(nt)))
3116                         {
3117                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
3118                         }
3119 
3120                       /* recompute all of the shape information */
3121                       /* BUG: this may be a memory leak ??? */
3122                       if(NC_var_shape((*dp), handle->dims) == -1)
3123                         {
3124                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
3125                         }
3126                   }
3127 
3128                 /* found it? */
3129                 HGOTO_DONE((int32)ii);
3130             }
3131       }
3132 
3133     /* create a new var with this dim as only coord */
3134     if(nt == 0)
3135         nt = DFNT_FLOAT32;
3136 
3137     if ((nctype = hdf_unmap_type((int)nt)) == FAIL)
3138       {
3139           /* replace it with NCAdvice or HERROR? */
3140     HGOTO_ERROR(DFE_ARGS, FAIL);
3141       }
3142 
3143     dimindex = (intn)id;
3144     var = (NC_var *) NC_new_var(name->values, nctype, (unsigned)1, &dimindex);
3145     if(var == NULL)
3146       {
3147     HGOTO_ERROR(DFE_ARGS, FAIL);
3148       }
3149 
3150     /* Set flag to indicate that this variable is a coordinate variable -
3151        BMR - 05/14/2007 */
3152     var->var_type = IS_CRDVAR;
3153 
3154     /* BMR: put back hdf type that was set wrong by NC_new_var; please refer
3155        to the cvs history of bug #172 for reason on this statement - 4/17/01*/
3156     var->HDFtype = nt;
3157 
3158     /* get a new NDG ref for this sucker */
3159 #ifdef NOT_YET
3160     var->ndg_ref = Htagnewref(handle->hdf_file,DFTAG_NDG);
3161 #else /* NOT_YET */
3162     var->ndg_ref = Hnewref(handle->hdf_file);
3163 #endif /* NOT_YET */
3164 
3165     /* add it to the handle */
3166     if(handle->vars->count >= H4_MAX_NC_VARS)
3167       {
3168     HGOTO_ERROR(DFE_ARGS, FAIL);
3169       }
3170 
3171     var->cdf = handle; /* set cdf before calling NC_var_shape */
3172     /* compute all of the shape information */
3173     if(NC_var_shape(var, handle->dims) == -1)
3174       {
3175     HGOTO_ERROR(DFE_ARGS, FAIL);
3176       }
3177 
3178     if(NC_incr_array(handle->vars, (Void *)&var) == NULL)
3179       {
3180     HGOTO_ERROR(DFE_ARGS, FAIL);
3181       }
3182 
3183     ret_value = handle->vars->count - 1;
3184 
3185 done:
3186     if (ret_value == FAIL)
3187       { /* Failure cleanup */
3188 
3189       }
3190     /* Normal cleanup */
3191 
3192     return ret_value;
3193 } /* SDIgetcoordvar */
3194 
3195 #endif /* MFSD_INTERNAL */
3196 
3197 /******************************************************************************
3198  NAME
3199     SDsetdimstrs -- set "dimension strings"
3200 
3201  DESCRIPTION
3202     Store information about the 'label', 'units' and 'format'
3203     attributes of a dimension.  All three of the values are optional.
3204     If no string is desired NULL should be passed in its place.
3205 
3206  RETURNS
3207     SUCCEED / FAIL
3208 
3209 ******************************************************************************/
3210 intn
SDsetdimstrs(int32 id,const char * l,const char * u,const char * f)3211 SDsetdimstrs(int32 id, /* IN: dimension ID */
3212              const char *l,  /* IN: label string ("long_name") */
3213              const char *u,  /* IN: units string ("units") */
3214              const char *f   /* IN: format string ("format") */)
3215 {
3216     CONSTR(FUNC, "SDsetdimstrs");    /* for HGOTO_ERROR */
3217     intn       varid;
3218     NC        *handle = NULL;
3219     NC_dim    *dim = NULL;
3220     NC_var    *var = NULL;
3221     intn       ret_value = SUCCEED;
3222 
3223 #ifdef SDDEBUG
3224     fprintf(stderr, "SDsetdimstrs: I've been called\n");
3225 #endif
3226 
3227     /* clear error stack */
3228     HEclear();
3229 
3230     /* get the handle */
3231     handle = SDIhandle_from_id(id, DIMTYPE);
3232     if(handle == NULL)
3233       {
3234     HGOTO_ERROR(DFE_ARGS, FAIL);
3235       }
3236 
3237     /* get the dimension structure */
3238     dim = SDIget_dim(handle, id);
3239     if(dim == NULL)
3240       {
3241     HGOTO_ERROR(DFE_ARGS, FAIL);
3242       }
3243 
3244     /* look for a variable with the same name */
3245     varid = (intn)SDIgetcoordvar(handle, dim, (int32)(id & 0xffff), (int32)0);
3246     if(varid == FAIL)
3247       {
3248         HGOTO_ERROR(DFE_ARGS, FAIL);
3249       }
3250 
3251     /* get the variable object */
3252     var = NC_hlookupvar(handle, varid);
3253     if(var == NULL)
3254       {
3255         HGOTO_ERROR(DFE_ARGS, FAIL);
3256       }
3257 
3258     /* set the attributes */
3259     if(l && l[0] != '\0')
3260       {
3261         if(SDIputattr(&var->attrs, _HDF_LongName, DFNT_CHAR,
3262                       (intn) HDstrlen(l), l) == FAIL)
3263           {
3264               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
3265           }
3266       }
3267 
3268     if(u && u[0] != '\0')
3269       {
3270         if(SDIputattr(&var->attrs, _HDF_Units, DFNT_CHAR,
3271                       (intn) HDstrlen(u), u) == FAIL)
3272           {
3273               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
3274           }
3275       }
3276 
3277     if(f && f[0] != '\0')
3278       {
3279         if(SDIputattr(&var->attrs, _HDF_Format, DFNT_CHAR,
3280                       (intn) HDstrlen(f), f) == FAIL)
3281           {
3282               HGOTO_ERROR(DFE_CANTSETATTR, FAIL);
3283           }
3284       }
3285 
3286     /* make sure it gets reflected in the file */
3287     handle->flags |= NC_HDIRTY;
3288 
3289 done:
3290     if (ret_value == FAIL)
3291       { /* Failure cleanup */
3292 
3293       }
3294     /* Normal cleanup */
3295 
3296 
3297     return ret_value;
3298 } /* SDsetdimstrs */
3299 
3300 #ifdef MFSD_INTERNAL
3301 /******************************************************************************
3302  NAME
3303     SDIfreevarAID -- free a variables AID
3304 
3305  DESCRIPTION
3306     Free the AID of the variable with the given index
3307 
3308  RETURNS
3309     SUCCEED / FAIL
3310 
3311 ******************************************************************************/
3312 int32
SDIfreevarAID(NC * handle,int32 index)3313 SDIfreevarAID(NC   *handle, /* IN: file handle */
3314               int32 index   /* IN: variable index */)
3315 {
3316     CONSTR(FUNC, "SDIfreevarAID");    /* for HGOTO_ERROR */
3317     NC_array **ap = NULL;
3318     NC_var    *var = NULL;
3319     int32      ret_value = SUCCEED;
3320 
3321     if(handle == NULL || !handle->vars)
3322       {
3323     HGOTO_ERROR(DFE_ARGS, FAIL);
3324       }
3325 
3326     if(index < 0 || index > handle->vars->count)
3327       {
3328     HGOTO_ERROR(DFE_ARGS, FAIL);
3329       }
3330 
3331     ap = (NC_array **)handle->vars->values;
3332     ap += index;
3333 
3334     var = (NC_var *) *ap;
3335 
3336     if(var->aid != 0 && var->aid != FAIL)
3337       {
3338         if (Hendaccess(var->aid) == FAIL)
3339           {
3340               HGOTO_ERROR(DFE_ARGS, FAIL);
3341           }
3342       }
3343 
3344     var->aid = FAIL;
3345 
3346 done:
3347     if (ret_value == FAIL)
3348       { /* Failure cleanup */
3349 
3350       }
3351     /* Normal cleanup */
3352 
3353     return ret_value;
3354 } /* SDIfreevarAID */
3355 #endif /* MFSD_INTERNAL */
3356 
3357 /******************************************************************************
3358  NAME
3359     SDsetdimscale -- store scale information for the dimension
3360 
3361  DESCRIPTION
3362     Store information about the 'scales' of a dimension.  Dimensions
3363     do not have to have the same number type as the dataset.
3364 
3365  RETURNS
3366     SUCCEED / FAIL
3367 
3368 ******************************************************************************/
3369 intn
SDsetdimscale(int32 id,int32 count,int32 nt,void * data)3370 SDsetdimscale(int32 id,    /* IN: dimension ID */
3371               int32 count, /* IN: number of values */
3372               int32 nt,    /* IN: number type of data */
3373               void * data   /* IN: scale values */)
3374 {
3375     CONSTR(FUNC, "SDsetdimscale");    /* for HGOTO_ERROR */
3376     NC        *handle = NULL;
3377     NC_dim    *dim = NULL;
3378     int32      status;
3379     intn       varid;
3380     long       start[1];
3381     long       end[1];
3382     intn       ret_value = SUCCEED;
3383 
3384 #ifdef SDDEBUG
3385     fprintf(stderr, "SDsetdimscales: I've been called\n");
3386 #endif
3387 
3388     /* this decides how a dataset with unlimited dimension is written along the
3389        unlimited dimension; the behavior is different between SD and nc APIs */
3390     cdf_routine_name = "SDsetdimscales";
3391 
3392     /* clear error stack */
3393     HEclear();
3394 
3395     /* get the handle */
3396     handle = SDIhandle_from_id(id, DIMTYPE);
3397     if(handle == NULL)
3398       {
3399     HGOTO_ERROR(DFE_ARGS, FAIL);
3400       }
3401 
3402     /* get the dimension structure */
3403     dim = SDIget_dim(handle, id);
3404     if(dim == NULL)
3405       {
3406     HGOTO_ERROR(DFE_ARGS, FAIL);
3407       }
3408 
3409     /* sanity check, if not SD_UNLIMITED */
3410     if( dim->size != 0 && count != dim->size)
3411       {
3412     HGOTO_ERROR(DFE_ARGS, FAIL);
3413       }
3414 
3415     /* look for a variable with the same name */
3416     varid = (intn)SDIgetcoordvar(handle, dim, id & 0xffff, nt);
3417     if(varid == -1)
3418       {
3419     HGOTO_ERROR(DFE_ARGS, FAIL);
3420       }
3421 
3422     /* store the data */
3423     handle->xdrs->x_op = XDR_ENCODE;
3424     start[0] = 0;
3425     end[0]   = count;
3426     status = NCvario(handle, varid, start, end, (Void *)data);
3427     if(status == FAIL)
3428       {
3429     HGOTO_ERROR(DFE_ARGS, FAIL);
3430       }
3431 
3432     /* free the AID */
3433     status = SDIfreevarAID(handle, varid);
3434     if(status == FAIL)
3435       {
3436     HGOTO_ERROR(DFE_ARGS, FAIL);
3437       }
3438 
3439     /* make sure it gets reflected in the file */
3440     handle->flags |= NC_HDIRTY;
3441 
3442 done:
3443     if (ret_value == FAIL)
3444       { /* Failure cleanup */
3445 
3446       }
3447     /* Normal cleanup */
3448 
3449 
3450     return ret_value;
3451 } /* SDsetdimscale */
3452 
3453 
3454 /******************************************************************************
3455  NAME
3456     SDgetdimscale -- get scale information for the dimension
3457 
3458  DESCRIPTION
3459     Retreive the scale information stored with a dimension.  It is
3460     assumed that the user has called SDdiminfo() and that the data
3461     array is long enough to hold the values.
3462 
3463  RETURNS
3464     SUCCEED / FAIL
3465 
3466 ******************************************************************************/
3467 intn
SDgetdimscale(int32 id,void * data)3468 SDgetdimscale(int32 id,   /* IN:  dimension ID */
3469               void * data  /* OUT: scale values */)
3470 {
3471     CONSTR(FUNC, "SDgetdimscale");    /* for HGOTO_ERROR */
3472     NC        *handle = NULL;
3473     NC_dim    *dim = NULL;
3474     NC_var    *vp = NULL;
3475     int32      status;
3476     intn       varid;
3477     long       start[1];
3478     long       end[1];
3479     intn       ret_value = SUCCEED;
3480 
3481 #ifdef SDDEBUG
3482     fprintf(stderr, "SDgetdimscale: I've been called\n");
3483 #endif
3484 
3485     /* this decides how a dataset with unlimited dimension is read along the
3486        unlimited dimension; the behavior is different between SD and nc APIs */
3487     cdf_routine_name = "SDgetdimscale";
3488 
3489     /* clear error stack */
3490     HEclear();
3491 
3492     /* sanity check args */
3493     if(data == NULL)
3494       {
3495     HGOTO_ERROR(DFE_ARGS, FAIL);
3496       }
3497 
3498     /* get the handle */
3499     handle = SDIhandle_from_id(id, DIMTYPE);
3500     if(handle == NULL)
3501       {
3502     HGOTO_ERROR(DFE_ARGS, FAIL);
3503       }
3504 
3505     /* get the dimension structure */
3506     dim = SDIget_dim(handle, id);
3507     if(dim == NULL)
3508       {
3509     HGOTO_ERROR(DFE_ARGS, FAIL);
3510       }
3511 
3512     /* look for a variable with the same name */
3513     /* assume type Float32 can be over-ridden later */
3514     varid = (intn)SDIgetcoordvar(handle, dim, (int32)(id & 0xffff), (int32)0);
3515     if(varid == FAIL)
3516       {
3517     HGOTO_ERROR(DFE_ARGS, FAIL);
3518       }
3519 
3520     /* store the data */
3521     handle->xdrs->x_op = XDR_DECODE;
3522     start[0] = 0;
3523     if (dim->size != 0)
3524         end[0] = dim->size;
3525     else
3526       {
3527         if (handle->file_type != HDF_FILE)
3528             end[0] = handle->numrecs;
3529         else
3530           {
3531             vp = SDIget_var(handle, varid);
3532             if (vp == NULL)
3533               {
3534                 HGOTO_ERROR(DFE_ARGS, FAIL);
3535               }
3536 
3537             end[0] = vp->numrecs;
3538           }
3539       }
3540 
3541     status = NCvario(handle, varid, start, end, (Void *)data);
3542     if(status == FAIL)
3543       {
3544         HGOTO_ERROR(DFE_ARGS, FAIL);
3545       }
3546 
3547     /* free the AID */
3548     status = SDIfreevarAID(handle, varid);
3549     if(status == FAIL)
3550       {
3551     HGOTO_ERROR(DFE_ARGS, FAIL);
3552       }
3553 
3554 done:
3555     if (ret_value == FAIL)
3556       { /* Failure cleanup */
3557 
3558       }
3559     /* Normal cleanup */
3560 
3561 
3562     return ret_value;
3563 } /* SDgetdimscale */
3564 
3565 
3566 /******************************************************************************
3567  NAME
3568     SDdiminfo -- get info about a dimension
3569 
3570  DESCRIPTION
3571     Return basic information about a dimension (name, sizes, number
3572     of attributes, number type, etc...) The user is repsonsible for
3573     allocating space to hold the dataset name.  It can be at most
3574     H4_MAX_NC_NAME characters in length.  NULL can be passed for the
3575     name if it is not required.
3576 
3577  RETURNS
3578     SUCCEED / FAIL
3579 
3580 ******************************************************************************/
3581 intn
SDdiminfo(int32 id,char * name,int32 * size,int32 * nt,int32 * nattr)3582 SDdiminfo(int32  id,    /* IN:  dimension ID */
3583           char  *name,  /* OUT: name of the dimension */
3584           int32 *size,  /* OUT: size of the dimension */
3585           int32 *nt,    /* OUT: number type of scales */
3586           int32 *nattr  /* OUT: the number of local attributes */)
3587 {
3588     CONSTR(FUNC, "SDdiminfo");    /* for HGOTO_ERROR */
3589     NC      *handle = NULL;
3590     NC_dim  *dim = NULL;
3591     NC_var   *var = NULL;
3592     NC_var **dp = NULL;
3593     intn     ii;
3594     intn     len;
3595     int32    varid;
3596     int      ret_value = SUCCEED;
3597 
3598 #ifdef SDDEBUG
3599     fprintf(stderr, "SDdiminfo: I've been called\n");
3600 #endif
3601 
3602     /* clear error stack */
3603     HEclear();
3604 
3605     handle = SDIhandle_from_id(id, DIMTYPE);
3606     if(handle == NULL)
3607       {
3608     HGOTO_ERROR(DFE_ARGS, FAIL);
3609       }
3610 
3611     if(handle->dims == NULL)
3612       {
3613     HGOTO_ERROR(DFE_ARGS, FAIL);
3614       }
3615 
3616     dim = SDIget_dim(handle, id);
3617     if(dim == NULL)
3618       {
3619     HGOTO_ERROR(DFE_ARGS, FAIL);
3620       }
3621 
3622     if(name != NULL)
3623       {
3624 /* GeorgeV switched to use HDmemcpy in r2739.  Trying back to HDstrncpy because
3625    it should be used to copy a string (emailed with QK 5/27/2016), but tests
3626    failed.  Some strings are stored with NC_string, more time is needed to
3627    figure out the whole scheme.  Switch back to using HDmemcpy for now.
3628    -BMR, 5/30/2016
3629 */
3630 
3631 #if 0
3632         HDstrncpy(name, dim->name->values, dim->name->len);
3633 #endif
3634         HDmemcpy(name, dim->name->values, dim->name->len);
3635         name[dim->name->len] = '\0';
3636       }
3637     else
3638         name = dim->name->values;
3639 
3640     /* Get dimension's size, which is the one application provided at SDcreate.
3641        Application must use SDgetinfo to get current size of unlimited dim */
3642     *size = dim->size;
3643 
3644     /* assuming no number type and no attributes */
3645     *nt    = 0;
3646     *nattr = 0;
3647 
3648     /* In HDF files, number type and attribute info are only stored in the
3649        coordinate var of the dimension; so, if there is no coord var associated
3650        with the dimension being inquired, these info will not be available. */
3651     if(handle->vars)
3652       {
3653           len = dim->name->len;
3654           dp = (NC_var**)handle->vars->values;
3655           for(ii = 0 ; ii < handle->vars->count ; ii++, dp++)
3656             {
3657         /* eliminate vars with rank > 1, coord vars only have rank 1 */
3658         if((*dp)->assoc->count == 1)
3659         {
3660         /* check if this variable matches the searched name */
3661                  if( len == (*dp)->name->len
3662                     && HDstrncmp(name, (*dp)->name->values, (*dp)->name->len) == 0)
3663         {
3664             if (handle->file_type == HDF_FILE) /* HDF file */
3665             {
3666             /* only proceed if this variable is a coordinate var or
3667             when its status is unknown due to its being created
3668             prior to the fix of bugzilla 624 - BMR - 05/14/2007 */
3669             if ((*dp)->var_type == IS_CRDVAR ||
3670                 (*dp)->var_type == UNKNOWN)
3671             {
3672                 *nt = ((*dp)->numrecs ? (*dp)->HDFtype : 0);
3673                 *nattr = ((*dp)->attrs ? (*dp)->attrs->count : 0);
3674                             HGOTO_DONE(ret_value);
3675             }
3676             }
3677             else /* netCDF file */
3678             {
3679             *nt = (*dp)->HDFtype;
3680             *nattr = ((*dp)->attrs ? (*dp)->attrs->count : 0);
3681                         HGOTO_DONE(ret_value);
3682             }
3683         } /* name matched */
3684         } /* rank = 1 */
3685             }
3686       }
3687 done:
3688     if (ret_value == FAIL)
3689       { /* Failure cleanup */
3690 
3691       }
3692     /* Normal cleanup */
3693     return ret_value;
3694 } /* SDdiminfo */
3695 
3696 
3697 /******************************************************************************
3698  NAME
3699     SDgetdimstrs -- get "data strings"
3700 
3701  DESCRIPTION
3702     Read as many of the dimension strings as possible.  Assume that
3703     if a pointer is not NULL that we have len bytes that we can use
3704     to return the values
3705 
3706  RETURNS
3707      SUCCEED / FAIL
3708 
3709 ******************************************************************************/
3710 intn
SDgetdimstrs(int32 id,char * l,char * u,char * f,intn len)3711 SDgetdimstrs(int32 id,  /* IN:  dataset ID */
3712              char *l,   /* OUT: label string ("long_name") */
3713              char *u,   /* OUT: units string ("units") */
3714              char *f,   /* OUT: format string ("format") */
3715              intn  len  /* IN:  buffer length */)
3716 {
3717     CONSTR(FUNC, "SDgetdimstrs");    /* for HGOTO_ERROR */
3718     NC       *handle = NULL;
3719     NC_var   *var = NULL;
3720     NC_var  **dp = NULL;
3721     NC_dim   *dim = NULL;
3722     NC_attr **attr = NULL;
3723     char     *name = NULL;
3724     int32     ii;
3725     int32     namelen;
3726     intn      ret_value = SUCCEED;
3727 
3728 #ifdef SDDEBUG
3729     fprintf(stderr, "SDgetdimstrs: I've been called\n");
3730 #endif
3731 
3732     /* clear error stack */
3733     HEclear();
3734 
3735     /* sanity check args */
3736     if(len < 0) HGOTO_ERROR(DFE_ARGS, FAIL);
3737 
3738     handle = SDIhandle_from_id(id, DIMTYPE);
3739     if(handle == NULL)
3740       {
3741     HGOTO_ERROR(DFE_ARGS, FAIL);
3742       }
3743 
3744     if(handle->vars == NULL)
3745       {
3746     HGOTO_ERROR(DFE_ARGS, FAIL);
3747       }
3748 
3749     dim = SDIget_dim(handle, id);
3750     if(dim == NULL)
3751       {
3752     HGOTO_ERROR(DFE_ARGS, FAIL);
3753       }
3754 
3755     /* need to get a pointer to the var now */
3756     var = NULL;
3757     if(handle->vars)
3758       {
3759           name = dim->name->values;
3760           namelen = HDstrlen(name);
3761           dp = (NC_var**)handle->vars->values;
3762           for(ii = 0 ; ii < handle->vars->count ; ii++, dp++)
3763             {
3764         /* eliminate vars with rank > 1, coord vars only have rank 1 */
3765         if((*dp)->assoc->count == 1)
3766                   if( namelen == (*dp)->name->len
3767                     && HDstrncmp(name, (*dp)->name->values, HDstrlen(name)) == 0)
3768         /* because a dim was given, make sure that this is a coord var */
3769         /* if it is an SDS, the function will fail */
3770         if ((*dp)->var_type == IS_SDSVAR)
3771             HGOTO_ERROR(DFE_ARGS, FAIL)
3772             /* only proceed if this variable is a coordinate var or when
3773             its status is unknown due to its being created prior to
3774             the fix of bugzilla 624 - BMR - 05/14/2007 */
3775         else
3776         /* i.e., (*dp)->var_type == IS_CRDVAR ||
3777             (*dp)->var_type == UNKNOWN) */
3778                   {
3779                       var = (*dp);
3780                   }
3781             }
3782       }
3783 
3784     if(var != NULL)
3785     {
3786     if(l)
3787       {
3788           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_LongName);
3789           if(attr != NULL)
3790             {
3791                 intn minlen;
3792                 minlen = ((unsigned)len > (*attr)->data->count)? (*attr)->data->count: (unsigned)len;
3793                 HDstrncpy((char *)l, (*attr)->data->values, minlen);
3794                 if((*attr)->data->count < (unsigned)len)
3795                     l[(*attr)->data->count] = '\0';
3796             }
3797           else
3798               l[0] = '\0';
3799       }
3800 
3801     if(u)
3802       {
3803           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_Units);
3804           if(attr != NULL)
3805             {
3806                 intn minlen;
3807                 minlen = (len > (*attr)->data->count)? (*attr)->data->count: (unsigned)len;
3808                 HDstrncpy((char *)u, (*attr)->data->values, minlen);
3809                 if((*attr)->data->count < (unsigned)len)
3810                     u[(*attr)->data->count] = '\0';
3811             }
3812           else
3813               u[0] = '\0';
3814       }
3815 
3816     if(f)
3817       {
3818           attr = (NC_attr **) NC_findattr(&(var->attrs), _HDF_Format);
3819           if(attr != NULL)
3820             {
3821                 intn minlen;
3822                 minlen = (len > (*attr)->data->count)? (*attr)->data->count: (unsigned)len;
3823                 HDstrncpy((char *)f, (*attr)->data->values, minlen);
3824                 if((*attr)->data->count < (unsigned)len)
3825                     f[(*attr)->data->count] = '\0';
3826             }
3827           else
3828               f[0] = '\0';
3829       }
3830     }
3831     /* the given dimension is not a coordinate variable, that means it
3832        doesn't have attribute attached to it, because if it did, then it
3833        would have been promoted to be a coordinate variable. */
3834     else
3835     {
3836       if(l) l[0] = '\0';
3837 
3838       if(u) u[0] = '\0';
3839 
3840       if(f) f[0] = '\0';
3841     }
3842 
3843 done:
3844     if (ret_value == FAIL)
3845       { /* Failure cleanup */
3846 
3847       }
3848     /* Normal cleanup */
3849     return ret_value;
3850 } /* SDgetdimstrs */
3851 
3852 
3853 /******************************************************************************
3854  NAME
3855     SDsetexternalfile -- store info in a separate file
3856  USAGE
3857     int32 SDsetexternalfile(id, filename, offset)
3858         int32   id;
3859         const char  * filename;
3860         int32   offset;
3861 
3862  DESCRIPTION
3863     Specify that the actual data for this dataset be stored in a
3864     separate file (and "external file" in HDF terms).
3865 
3866     Only the data (as in SDwritedata()) will be stored externally.
3867     Attributes and such will still be in the main file
3868 
3869     IMPORTANT:  It is the user's responsibility to see that the
3870     separate files are transported when the main file is moved.
3871 
3872     IMPORTANT:  This can only be called *once* for a given dataset.
3873     The HDF utility 'hdfpack' may be able to undo it.
3874 
3875     IMPORTANT:  This will only work on datasets stored in HDF files.
3876 
3877     FORTRAN    - sfsextf
3878 
3879  RETURNS
3880     SUCCEED/FAIL
3881 
3882 ******************************************************************************/
3883 intn
SDsetexternalfile(int32 id,const char * filename,int32 offset)3884 SDsetexternalfile(int32 id,       /* IN: dataset ID */
3885                   const char *filename, /* IN: name of external file */
3886                   int32 offset    /* IN: offset in external file */)
3887 {
3888     CONSTR(FUNC, "SDsetexternalfile");    /* for HGOTO_ERROR */
3889     NC     *handle = NULL;
3890     NC_var *var = NULL;
3891     intn    extfname_len = 0; /* Length of external file's name */
3892     intn    status;
3893     int     ret_value = SUCCEED;
3894 
3895 #ifdef SDDEBUG
3896     fprintf(stderr, "SDsetexternalfile: I've been called\n");
3897 #endif
3898 
3899     /* clear error stack */
3900     HEclear();
3901 
3902     /* Call SDgetexternalinfo passing in 0 and NULLs to get only the length of
3903        the external filename if it exists.  A positive value indicates an
3904        external file exists and SDsetexternalfile should not have any effect */
3905     extfname_len = SDgetexternalinfo(id, 0, NULL, NULL, NULL);
3906     if (extfname_len > 0)
3907     HGOTO_DONE(DFE_NONE);
3908 
3909     if(NULL == filename || offset < 0)
3910       {
3911     HGOTO_ERROR(DFE_ARGS, FAIL);
3912       }
3913 
3914     handle = SDIhandle_from_id(id, SDSTYPE);
3915     if(handle == NULL || handle->file_type != HDF_FILE)
3916       {
3917     HGOTO_ERROR(DFE_ARGS, FAIL);
3918       }
3919 
3920     if(handle->vars == NULL)
3921       {
3922     HGOTO_ERROR(DFE_ARGS, FAIL);
3923       }
3924 
3925     var = SDIget_var(handle, id);
3926     if(var == NULL)
3927       {
3928     HGOTO_ERROR(DFE_ARGS, FAIL);
3929       }
3930 
3931     /* already exists */
3932     if(var->data_ref)
3933       {
3934           /* no need to give a length since the element already exists */
3935           status = (intn)HXcreate(handle->hdf_file, (uint16)DATA_TAG,
3936                          (uint16) var->data_ref, filename, offset, (int32)0);
3937       }
3938     else
3939       {
3940           int32   length;
3941 
3942           /* look up the length */
3943           length = var->len;
3944 
3945           /* element doesn't exist so we need a reference number */
3946 #ifdef NOT_YET
3947           var->data_ref = Htagnewref(handle->hdf_file,DATA_TAG);
3948 #else /* NOT_YET */
3949           var->data_ref = Hnewref(handle->hdf_file);
3950 #endif /* NOT_YET */
3951           if(var->data_ref == 0)
3952             {
3953                 HGOTO_ERROR(DFE_NOREF, FAIL);
3954             }
3955 
3956           /* need to give a length since the element does not exist yet */
3957           status = (intn)HXcreate(handle->hdf_file, (uint16)DATA_TAG,
3958                          (uint16) var->data_ref, filename, offset, length);
3959       }
3960     if(status != FAIL)
3961       {
3962           if((var->aid != 0) && (var->aid != FAIL))
3963             {
3964                 if (Hendaccess(var->aid) == FAIL)
3965                   {
3966                       HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
3967                   }
3968             }
3969           var->aid = status;
3970           ret_value = SUCCEED;
3971       }
3972     else
3973         ret_value = FAIL;
3974 
3975 done:
3976     if (ret_value == FAIL)
3977       { /* Failure cleanup */
3978 
3979       }
3980     /* Normal cleanup */
3981     return ret_value;
3982 } /* SDsetexternalfile */
3983 
3984 
3985 /******************************************************************************
3986  NAME
3987     SDgetexternalinfo -- retrieves external file and data information
3988  USAGE
3989     int32 SDgetexternalinfo(id, buf_size, filename, offset, length)
3990         int32 id;
3991     intn  buf_size;
3992         char  *ext_filename;
3993         int32 *offset;
3994         int32 *length;
3995 
3996  DESCRIPTION
3997     SDgetexternalinfo gets the external file's name and the external data's
3998     offset and length, which specify the location and size of the data in
3999     the external file.
4000 
4001     buf_size specifies the size of the buffer ext_filename.  When buf_size
4002     is 0, SDgetexternalinfo will simply return the length of the external file
4003     name, and not the file name itself.
4004 
4005     When the element is not special or special but not external,
4006     SDgetexternalinfo will return 0.  If the element is SPECIAL_EXT,
4007     but the external file name doesn't exist, SDgetexternalinfo will
4008     return FAIL.
4009 
4010     IMPORTANT:  It is the user's responsibility to see that the
4011     external files are located in the same directory with the main
4012     file.  SDgetexternalinfo does not check that.
4013 
4014  RETURNS
4015     Returns length of the external file name or FAIL.  If the SDS
4016     does not have external element, this length will be 0.
4017 
4018 ******************************************************************************/
4019 intn
SDgetexternalinfo(int32 id,uintn buf_size,char * ext_filename,int32 * offset,int32 * length)4020 SDgetexternalinfo(int32 id,      /* IN: dataset ID */
4021               uintn buf_size,    /* IN: size of buffer for external file name */
4022               char *ext_filename,/* IN: buffer for external file name */
4023               int32 *offset,     /* IN: offset in external file */
4024               int32 *length      /* IN: length of external data */)
4025 {
4026     CONSTR(FUNC, "SDgetexternalinfo");    /* for HGOTO_ERROR */
4027     NC     *handle = NULL;
4028     NC_var *var = NULL;
4029     int32   aid = FAIL;
4030     intn    actual_fname_len = 0;
4031     intn    ret_value = SUCCEED;
4032 
4033 #ifdef SDDEBUG
4034     fprintf(stderr, "SDgetexternalinfo: I've been called\n");
4035 #endif
4036 
4037     /* Clear error stack */
4038     HEclear();
4039 
4040     /* Get the var structure of the SDS */
4041     handle = SDIhandle_from_id(id, SDSTYPE);
4042     if(handle == NULL || handle->file_type != HDF_FILE)
4043     HGOTO_ERROR(DFE_ARGS, FAIL);
4044 
4045     if(handle->vars == NULL)
4046     HGOTO_ERROR(DFE_ARGS, FAIL);
4047 
4048     var = SDIget_var(handle, id);
4049     if(var == NULL)
4050     HGOTO_ERROR(DFE_ARGS, FAIL);
4051 
4052     /* SDS exists */
4053     if(var->data_ref)
4054     {
4055     int32 retcode=0;
4056     sp_info_block_t info_block;    /* special info block */
4057     HDmemset(&info_block, 0, sizeof(sp_info_block_t));
4058 
4059     /* Get the access id and then its special info */
4060     aid = Hstartread(handle->hdf_file, var->data_tag, var->data_ref);
4061     if (aid == FAIL) /* catch FAIL from Hstartread */
4062         HGOTO_ERROR(DFE_ARGS, FAIL);
4063     retcode = HDget_special_info(aid, &info_block);
4064 
4065         /* When HDget_special_info returns FAIL, it could be the element is not
4066            special or some failure occur internally, info_block.key will be
4067            FAIL in the former case */
4068         if (retcode == FAIL)
4069         {
4070             if (info_block.key == FAIL)
4071                 ret_value = 0;  /* not a special elem, no external file name */
4072 
4073             /* Some failure occurred in HDget_special_info */
4074             else
4075                 HGOTO_ERROR(DFE_ARGS, FAIL)
4076         }
4077 
4078     /* If the SDS has external element, get the external info */
4079         else if (info_block.key == SPECIAL_EXT)
4080         {
4081         /* If the file name is not available, something must be wrong,
4082         so we need to report it. */
4083             if (info_block.path == NULL || HDstrlen(info_block.path) <= 0)
4084         ret_value = FAIL;
4085             else
4086             {
4087                 intn tmp_len = info_block.length_file_name;
4088 
4089                 /* If caller requests the length of the external file name
4090                    only, return the length */
4091                 if (buf_size == 0)
4092                     actual_fname_len  = tmp_len;
4093                 else
4094                 {
4095                     /* Caller requests file name, so buffer must not be NULL */
4096                     if (ext_filename == NULL)
4097                         HGOTO_ERROR(DFE_ARGS, FAIL);
4098 
4099             /* Compute the length of the name to be returned: if
4100             requested buffer size is smaller, use that value for
4101             name's length, but that means file name could be
4102             truncated! */
4103                     actual_fname_len  = (intn)buf_size < tmp_len ? (intn)buf_size : tmp_len;
4104 
4105                     /* Get the name */
4106                     HDstrncpy(ext_filename, info_block.path, actual_fname_len);
4107 
4108                     /* Get offset/length of the external data if requested */
4109                     if (offset != NULL)
4110                         *offset = info_block.offset;
4111                     if (length != NULL)
4112                         *length = info_block.length;
4113                 } /* buf_size != 0 */
4114         ret_value = actual_fname_len ;
4115             }
4116         }
4117     /* Special but not external, so no external file name */
4118         else
4119             ret_value = 0;
4120 
4121     /* End access to the aid */
4122     if (Hendaccess(aid) == FAIL)
4123         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
4124     }
4125     else /* SDS doesn't exist */
4126     HGOTO_ERROR(DFE_ARGS, FAIL);
4127 done:
4128     if (ret_value == FAIL)
4129       { /* Failure cleanup */
4130     /* End access to the aid if neccessary */
4131     if (aid != FAIL)
4132         Hendaccess(aid);
4133       }
4134     /* Normal cleanup */
4135     return ret_value;
4136 } /* SDgetexternalinfo */
4137 
4138 
4139 /************************** Deprecated ******************************
4140  NAME
4141     SDgetexternalfile -- retrieves external file information
4142     (Deprecated)
4143  USAGE
4144     int32 SDgetexternalfile(id, filename, offset)
4145         int32 id;
4146     intn  buf_size;
4147         char  *filename;
4148         int32 *offset;
4149 
4150  DESCRIPTION
4151     SDgetexternalfile uses HDget_special_info to get the external
4152     file's name and offset, which indicates where the data starts
4153     in the external file.
4154 
4155     When the element is not special, SDgetexternalfile will return
4156     0.  If the element is SPECIAL_EXT, but the external file name
4157     doesn't exist, SDgetexternalfile will fail.
4158 
4159     IMPORTANT:  It is the user's responsibility to see that the
4160     separate files are transported when the main file is moved.
4161 
4162     FORTRAN    N/A
4163 
4164  RETURNS
4165     Returns length of the external file name or FAIL.  If the SDS
4166     does not have external element, the length will be 0.
4167 
4168  NOTE: This function is replaced by SDgetexternalinfo because it had
4169        missed the "length" parameter.
4170 
4171 ******************************************************************************/
4172 intn
SDgetexternalfile(int32 id,intn buf_size,char * ext_filename,int32 * offset)4173 SDgetexternalfile(int32 id,       /* IN: dataset ID */
4174                   intn buf_size,   /* IN: name of external file */
4175                   char *ext_filename, /* IN: name of external file */
4176                   int32 *offset    /* IN: offset in external file */)
4177 {
4178     CONSTR(FUNC, "SDgetexternalfile");    /* for HGOTO_ERROR */
4179     NC     *handle = NULL;
4180     NC_var *var = NULL;
4181     intn    actual_len = 0;
4182     int     ret_value = 0;
4183 
4184 #ifdef SDDEBUG
4185     fprintf(stderr, "SDgetexternalfile: I've been called\n");
4186 #endif
4187 
4188     /* Clear error stack */
4189     HEclear();
4190 
4191     /* Get the var structure */
4192     handle = SDIhandle_from_id(id, SDSTYPE);
4193     if(handle == NULL || handle->file_type != HDF_FILE)
4194     HGOTO_ERROR(DFE_ARGS, FAIL);
4195 
4196     if(handle->vars == NULL)
4197     HGOTO_ERROR(DFE_ARGS, FAIL);
4198 
4199     var = SDIget_var(handle, id);
4200     if(var == NULL)
4201     HGOTO_ERROR(DFE_ARGS, FAIL);
4202 
4203     /* SDS exists */
4204     if(var->data_ref)
4205     {
4206     int32 aid=-1;
4207     int32 retcode=0;
4208     sp_info_block_t info_block;    /* special info block */
4209 
4210     /* Get the access id and then its special info */
4211     aid = Hstartread(handle->hdf_file, var->data_tag, var->data_ref);
4212     retcode = HDget_special_info(aid, &info_block);
4213 
4214     /* If the SDS has external element, return the external file info */
4215         if (info_block.key == SPECIAL_EXT)
4216         {
4217         /* If the file name is not available, the file is probably
4218         corrupted, so we need to report it. */
4219             if (info_block.path == NULL || HDstrlen(info_block.path) <= 0)
4220                 ret_value = FAIL;
4221             else
4222             {
4223                 size_t ext_file_len = HDstrlen(info_block.path);
4224 
4225                 /* If caller requests the length of the external file name
4226                    only, return the length */
4227                 if (buf_size == 0)
4228                     actual_len = (intn)ext_file_len;
4229                 else
4230                 {
4231                     /* Caller requests file name, so buffer must not be NULL */
4232                     if (ext_filename == NULL)
4233                         HGOTO_ERROR(DFE_ARGS, FAIL);
4234 
4235                     /* Get the name and its length */
4236                     HDstrncpy(ext_filename, info_block.path, buf_size);
4237                     actual_len = buf_size < ext_file_len ? buf_size : ext_file_len;
4238 
4239                     /* Get the offset in the external file if it's requested */
4240                     if (offset != NULL)
4241                         *offset = info_block.offset;
4242                 } /* buf_size != 0 */
4243         ret_value = actual_len;
4244             }
4245         }
4246     /* Not external */
4247         else
4248             ret_value = FAIL;
4249 
4250     /* End access to the aid */
4251     if (Hendaccess(aid) == FAIL)
4252         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
4253     }
4254 done:
4255     if (ret_value == FAIL)
4256       { /* Failure cleanup */
4257 
4258       }
4259     /* Normal cleanup */
4260     return ret_value;
4261 } /* SDgetexternalfile (Deprecated) */
4262 
4263 
4264 /******************************************************************************
4265  NAME
4266     SDsetnbitdataset -- Create/convert a dataset to n-bit representation
4267 
4268 
4269  DESCRIPTION
4270     Specify that the actual data for this dataset be represented as a
4271     n-bit dataset internally in the HDF file.
4272 
4273     The start_bit parameter determines the lowest bit to write out,
4274     the bit_len parameter determines how many bits to write out.  The
4275     bits in the data include the lowest bit (start_bit) and count up
4276     bit_len-1 bits to write out.  For example, starting at bit 2
4277     and writing 4 bits from the following bit data, "01111011", would
4278     write out the bit data, "1110", to the dataset on disk.
4279 
4280     The sign_ext parameter determines whether the top bit (highest bit #)
4281     is used to sign extend the bits whether data is read back from the
4282     disk.  The fill_one parameter is used to determine whether to
4283     fill the "background bits" (the bits not in the data written to the
4284     file) with 1's or 0's when the data is read back from the file.
4285 
4286     Only the data (as in SDwritedata()) will be stored in n-bit
4287     representation.  Attributes and such will still be stored normally.
4288 
4289     IMPORTANT:  This will only work on datasets stored in HDF files.
4290 
4291     NOTE: n-bit "compression" is described more fully in the cnbit.c file.
4292 
4293  RETURNS
4294     SUCCEED/FAIL
4295 
4296 ******************************************************************************/
4297 intn
SDsetnbitdataset(int32 id,intn start_bit,intn bit_len,intn sign_ext,intn fill_one)4298 SDsetnbitdataset(int32 id,       /* IN: dataset ID */
4299                  intn start_bit, /* IN: starting bit offset (lowest=0) */
4300                  intn bit_len,   /* IN: # of bits to write */
4301                  intn sign_ext,  /* IN: Whether to sign extend */
4302                  intn fill_one   /* IN: Whether to fill background w/1's */)
4303 {
4304     CONSTR(FUNC, "SDsetnbitdataset");    /* for HGOTO_ERROR */
4305     NC        *handle = NULL;
4306     NC_var    *var = NULL;
4307     model_info m_info;  /* modeling information for the HCcreate() call */
4308     comp_info  c_info;  /* "compression" information for the HCcreate() call */
4309     intn       status;
4310     intn       ret_value = SUCCEED;
4311 
4312 #ifdef SDDEBUG
4313     fprintf(stderr, "SDsetnbitdataset: I've been called\n");
4314 #endif
4315 
4316     /* clear error stack */
4317     HEclear();
4318 
4319     if(start_bit < 0 || bit_len <= 0)
4320       {
4321     HGOTO_ERROR(DFE_ARGS, FAIL);
4322       }
4323 
4324     handle = SDIhandle_from_id(id, SDSTYPE);
4325     if(handle == NULL || handle->file_type != HDF_FILE)
4326       {
4327     HGOTO_ERROR(DFE_ARGS, FAIL);
4328       }
4329 
4330     if(handle->vars == NULL)
4331       {
4332     HGOTO_ERROR(DFE_ARGS, FAIL);
4333       }
4334 
4335     var = SDIget_var(handle, id);
4336     if(var == NULL)
4337       {
4338     HGOTO_ERROR(DFE_ARGS, FAIL);
4339       }
4340 
4341     /* set up n-bit parameters */
4342     c_info.nbit.nt        = var->HDFtype;
4343     c_info.nbit.sign_ext  = sign_ext;
4344     c_info.nbit.fill_one  = fill_one;
4345     c_info.nbit.start_bit = start_bit;
4346     c_info.nbit.bit_len   = bit_len;
4347 
4348 #ifdef SDDEBUG
4349     printf("SDsetnbitdata(): nt=%d, sign_ext=%d, fill_one=%d, start_bit=%d, bit_len=%d\n",(intn)c_info.nbit.nt,(intn)c_info.nbit.sign_ext,(intn)c_info.nbit.fill_one,(intn)c_info.nbit.start_bit,(intn)c_info.nbit.bit_len);
4350 #endif
4351     if(!var->data_ref)
4352       {   /* doesn't exist */
4353 #ifdef SDDEBUG
4354           printf("SDsetnbitdata(): dataset doesn't exist\n");
4355 #endif
4356 
4357           /* element doesn't exist so we need a reference number */
4358 #ifdef NOT_YET
4359           var->data_ref=Htagnewref(handle->hdf_file,DATA_TAG);
4360 #else /* NOT_YET */
4361           var->data_ref=Hnewref(handle->hdf_file);
4362 #endif /* NOT_YET */
4363           if(var->data_ref == 0)
4364             {
4365                 HGOTO_ERROR(DFE_ARGS, FAIL);
4366             }
4367       } /* end if */
4368 
4369     status=(intn)HCcreate(handle->hdf_file,(uint16)DATA_TAG,
4370                           (uint16) var->data_ref,COMP_MODEL_STDIO,&m_info,
4371                           COMP_CODE_NBIT, &c_info);
4372 
4373 #ifdef SDDEBUG
4374     printf("SDsetnbitdata(): HCcreate() status=%d\n",(intn)status);
4375 #endif
4376     if(status != FAIL)
4377       {
4378           if((var->aid != 0) && (var->aid != FAIL))
4379             {
4380                 if (Hendaccess(var->aid) == FAIL)
4381                   {
4382                       HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
4383                   }
4384             }
4385 
4386           var->aid = status;
4387       } /* end if */
4388 
4389     ret_value = status;
4390 
4391 done:
4392     if (ret_value == FAIL)
4393       { /* Failure cleanup */
4394 
4395       }
4396     /* Normal cleanup */
4397 
4398 
4399     return ret_value;
4400 } /* SDsetnbitdataset */
4401 
4402 #ifdef H4_HAVE_LIBSZ          /* we have the library */
4403 
4404 /******************************************************************************
4405  NAME
4406     SDsetup_szip_parms -- check and set parameters for szip compression
4407               int32 id;            IN: the  varid
4408               NC *handle;          IN: the SD handle
4409               comp_info *c_info;   IN/OUT: the compression settings
4410               int32 *cdims;        IN: the chunk dims, NULL if not chunked
4411 
4412  DESCRIPTION
4413      Collect the parameters and call HCPcszip_setup_parms to set the
4414      computed szip paramters.
4415 
4416  RETURNS
4417     SUCCEED/FAIL
4418 
4419 ******************************************************************************/
4420 intn
SDsetup_szip_parms(int32 id,NC * handle,comp_info * c_info,int32 * cdims)4421 SDsetup_szip_parms( int32 id, NC *handle, comp_info *c_info, int32 *cdims)
4422 {
4423     CONSTR(FUNC, "SDsetup_szip_parms");    /* for HGOTO_ERROR */
4424     NC_dim    *dim;     /* to check if the dimension is unlimited */
4425     int32      dimindex;/* to obtain the NC_dim record */
4426     NC_var    *var;
4427     int32 ndims;
4428     int i;
4429     int32 xdims[H4_MAX_VAR_DIMS];
4430     int32 nt;
4431     intn       ret_value = SUCCEED;
4432 
4433     /* clear error stack */
4434     HEclear();
4435 
4436     if(handle->vars == NULL)
4437       {
4438     HGOTO_ERROR(DFE_ARGS, FAIL);
4439       }
4440 
4441     var = SDIget_var(handle, id);
4442     if(var == NULL)
4443       {
4444     HGOTO_ERROR(DFE_ARGS, FAIL);
4445       }
4446 
4447     ndims = var->assoc->count;
4448     for (i = 0; i < ndims; i++) {
4449         dimindex = var->assoc->values[i];
4450         dim = SDIget_dim(handle, dimindex);
4451         xdims[i] = dim->size;
4452     }
4453 
4454     nt = var->HDFtype;
4455 
4456     ret_value = HCPsetup_szip_parms( c_info, nt, 1, ndims, xdims, cdims);
4457 
4458 done:
4459     return(ret_value);
4460 }
4461 #endif
4462 /******************************************************************************
4463  NAME
4464     SDsetcompress -- Create/convert a dataset to compressed representation
4465 
4466  DESCRIPTION
4467     Specify a compression scheme for an SD dataset.
4468 
4469     Valid compression types available for this interface are listed in
4470     hcomp.h as COMP_nnnn.
4471 
4472     IMPORTANT:  This will only work on datasets stored in HDF files.
4473 
4474  RETURNS
4475     SUCCEED/FAIL
4476 
4477 ******************************************************************************/
4478 intn
SDsetcompress(int32 id,comp_coder_t comp_type,comp_info * c_info)4479 SDsetcompress(int32 id,                /* IN: dataset ID */
4480               comp_coder_t comp_type,  /* IN: the type of compression to
4481                     perform on the next image */
4482               comp_info *c_info        /* IN: ptr to compression info struct*/)
4483 {
4484     CONSTR(FUNC, "SDsetcompress");    /* for HGOTO_ERROR */
4485     NC        *handle;
4486     NC_var    *var;
4487     NC_dim    *dim;     /* to check if the dimension is unlimited */
4488     int32      dimindex;/* to obtain the NC_dim record */
4489     model_info m_info;  /* modeling information for the HCcreate() call */
4490     comp_info c_info_x;  /* local copy */
4491     uint32  comp_config;
4492     intn       status = FAIL;
4493     intn       ret_value = SUCCEED;
4494 
4495 #ifdef SDDEBUG
4496     fprintf(stderr, "SDsetcompress: I've been called\n");
4497 #endif /* SDDEBUG */
4498 
4499     /* clear error stack */
4500     HEclear();
4501 
4502     if (comp_type < COMP_CODE_NONE || comp_type >= COMP_CODE_INVALID)
4503       {
4504     HGOTO_ERROR(DFE_ARGS, FAIL);
4505       }
4506 
4507     /* Must have encoder to set compression */
4508     HCget_config_info(comp_type, &comp_config);
4509     if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
4510     /* encoder not present?? */
4511     HGOTO_ERROR(DFE_NOENCODER, FAIL);
4512     }
4513     HDmemcpy(&c_info_x,c_info,sizeof(comp_info));
4514 
4515     handle = SDIhandle_from_id(id, SDSTYPE);
4516     if(handle == NULL || handle->file_type != HDF_FILE)
4517       {
4518     HGOTO_ERROR(DFE_ARGS, FAIL);
4519       }
4520 
4521     if(handle->vars == NULL)
4522       {
4523     HGOTO_ERROR(DFE_ARGS, FAIL);
4524       }
4525 
4526     var = SDIget_var(handle, id);
4527     if(var == NULL)
4528       {
4529     HGOTO_ERROR(DFE_ARGS, FAIL);
4530       }
4531 
4532     /* disallow setting compress for SDS with rank = 0 - BMR, bug #1045 */
4533     if(var->shape == NULL)
4534       {
4535     HGOTO_ERROR(DFE_ARGS, FAIL);
4536       }
4537 
4538     /* unlimited dimensions don't work with compression */
4539         /* Get the index of the SDS' first dimension from the list of indices
4540          * branching out from NC_var.  This index indicates where this dim
4541          * is in the "dims" list branching out from NC. */
4542         dimindex = var->assoc->values[0];
4543 
4544         /* Retrieve the NC_dim record to check for unlimited dimension */
4545         dim = SDIget_dim(handle, dimindex);
4546         if(dim == NULL)
4547         {
4548             HGOTO_ERROR(DFE_ARGS, FAIL);
4549         }
4550 
4551         /* If this dimension is unlimited, then return FAIL; the subsequent
4552          * writing of this SDS will write uncompressed data */
4553         if (dim->size == SD_UNLIMITED)
4554         {
4555             HGOTO_ERROR(DFE_ARGS, FAIL);
4556         }
4557 #ifdef H4_HAVE_LIBSZ          /* we have the library */
4558     if (comp_type == COMP_CODE_SZIP) {
4559     if (SDsetup_szip_parms( id, handle, &c_info_x, NULL) == FAIL) {
4560         HGOTO_ERROR(DFE_INTERNAL, FAIL);
4561         }
4562     }
4563 #else
4564     /* no SZIP */
4565 /* probably covered by test at start */
4566     if (comp_type == COMP_CODE_SZIP) {
4567         HGOTO_ERROR(DFE_BADCODER, FAIL);
4568     }
4569 #endif /* H4_HAVE_LIBSZ          */
4570 
4571 #ifdef SDDEBUG
4572     printf("SDsetcompress(): var->data_ref=%d\n",(int)var->data_ref);
4573 #endif /* SDDEBUG */
4574     if(!var->data_ref)
4575       {   /* doesn't exist */
4576 #ifdef SDDEBUG
4577           printf("SDsetcompress(): dataset doesn't exist\n");
4578 #endif /* SDDEBUG */
4579 
4580           /* element doesn't exist so we need a reference number */
4581 #ifdef NOT_YET
4582           var->data_ref=Htagnewref(handle->hdf_file,DATA_TAG);
4583 #else /* NOT_YET */
4584           var->data_ref=Hnewref(handle->hdf_file);
4585 #endif /* NOT_YET */
4586           if(var->data_ref == 0)
4587             {
4588                 HGOTO_ERROR(DFE_ARGS, FAIL);
4589             }
4590       } /* end if */
4591 
4592     status=(intn)HCcreate(handle->hdf_file,(uint16)DATA_TAG,
4593                           (uint16) var->data_ref,COMP_MODEL_STDIO,&m_info,
4594                           comp_type, &c_info_x);
4595 
4596 #ifdef SDDEBUG
4597     printf("SDsetcompress(): HCcreate() status=%d\n",(intn)status);
4598     if(status==FAIL)
4599         HEprint(stderr,0);
4600 #endif /* SDDEBUG */
4601 
4602     if(status != FAIL)
4603       {
4604           if((var->aid != 0) && (var->aid != FAIL))
4605             {
4606                 if (Hendaccess(var->aid) == FAIL)
4607                   {
4608                       HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
4609                   }
4610             }
4611 
4612           var->aid = status;
4613       } /* end if */
4614 
4615     /* Insert data tag/ref into the variable's Vgroup */
4616     if(var->vgid)
4617       {
4618           int32 vg;
4619 
4620           /* attach to the variable's Vgroup */
4621           vg = Vattach(handle->hdf_file, var->vgid, "w");
4622           if(vg == FAIL)
4623             {
4624                 HGOTO_ERROR(DFE_ARGS, FAIL);
4625             }
4626 
4627           /* add new Vdata to existing Vgroup */
4628           if (Vaddtagref(vg, (int32) DATA_TAG, (int32) var->data_ref) == FAIL)
4629             {
4630                 HGOTO_ERROR(DFE_ARGS, FAIL);
4631             }
4632 
4633           /* detach from the variable's VGroup --- will no longer need it */
4634           if (Vdetach(vg) == FAIL)
4635             {
4636                 HGOTO_ERROR(DFE_ARGS, FAIL);
4637             }
4638       }
4639 
4640     /* added a new object -- make sure we flush the header */
4641     handle->flags |= NC_HDIRTY;
4642 
4643     ret_value = (status != FAIL ? SUCCEED : FAIL);
4644 
4645 done:
4646     if (ret_value == FAIL)
4647       { /* Failure cleanup */
4648 
4649       }
4650     /* Normal cleanup */
4651 
4652 
4653     return ret_value;
4654 } /* SDsetcompress */
4655 
4656 #ifndef H4_NO_DEPRECATED_SYMBOLS
4657 
4658 /******************************************************************************
4659  NAME
4660     SDgetcompress -- Retrieves compression information of a dataset
4661 
4662  DESCRIPTION
4663     This routine uses HCPgetcompress to retrieve the compression type
4664     and the compression information of the identified dataset.
4665 
4666  RETURNS
4667     SUCCEED/FAIL
4668 
4669  MODIFICATION
4670     July 2001: Added to fix bug #307 - BMR
4671     Apr 2005:  This function has incorrect behavior and is replaced by
4672         SDgetcompinfo.  SDgetcompress will be removed in the future.
4673 
4674 ******************************************************************************/
4675 intn
SDgetcompress(int32 id,comp_coder_t * comp_type,comp_info * c_info)4676 SDgetcompress(int32     id,     /* IN: dataset ID */
4677               comp_coder_t*    comp_type,   /* OUT: the type of compression */
4678               comp_info* c_info)/* OUT: ptr to compression information
4679                 structure for storing the retrieved info */
4680 {
4681     CONSTR(FUNC, "SDgetcompress");    /* for HGOTO_ERROR */
4682     NC        *handle;
4683     NC_var    *var;
4684     intn       status = FAIL;
4685     intn       ret_value = SUCCEED;
4686 
4687 #ifdef SDDEBUG
4688     fprintf(stderr, "SDgetcompress: I've been called\n");
4689 #endif /* SDDEBUG */
4690 
4691     /* clear error stack */
4692     HEclear();
4693 
4694     if(comp_type == NULL || c_info == NULL)
4695     HGOTO_ERROR(DFE_ARGS, FAIL);
4696 
4697     handle = SDIhandle_from_id(id, SDSTYPE);
4698     if(handle == NULL || handle->file_type != HDF_FILE)
4699     HGOTO_ERROR(DFE_ARGS, FAIL);
4700     if(handle->vars == NULL)
4701     HGOTO_ERROR(DFE_ARGS, FAIL);
4702 
4703     var = SDIget_var(handle, id);
4704     if(var == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
4705 
4706 #ifdef SDDEBUG
4707     printf("SDgetcompress(): var->data_ref=%d, var->aid=%d\n",(int)var->data_ref, (int)var->aid);
4708 #endif /* SDDEBUG */
4709     if(!var->data_ref)
4710     HGOTO_ERROR(DFE_ARGS, FAIL);
4711 
4712     /* use lower-level routine to get the compression information */
4713     status = HCPgetcompress(handle->hdf_file, var->data_tag, var->data_ref,
4714         comp_type, c_info);
4715     if(status==FAIL) HGOTO_ERROR(DFE_INTERNAL, FAIL);
4716 
4717 done:
4718     if (ret_value == FAIL)
4719       { /* Failure cleanup */
4720 
4721       }
4722     /* Normal cleanup */
4723 
4724     return ret_value;
4725 } /* SDgetcompress */
4726 
4727 #endif /* H4_NO_DEPRECATED_SYMBOLS */
4728 
4729 /******************************************************************************
4730  NAME
4731     SDgetcompinfo -- Retrieves compression information of a dataset
4732 
4733  DESCRIPTION
4734     This routine uses HCPgetcompinfo to retrieve the compression type
4735     and the compression information of the identified dataset.
4736 
4737  RETURNS
4738     SUCCEED/FAIL
4739 
4740  MODIFICATION
4741     July 2001: Added to fix bug #307 - BMR (from SDgetcompress)
4742     Apr 2005:  This function was actually created at this time, but it is
4743         almost a duplicate of SDgetcompress, which is intended to be
4744         removed in the future, due to its incorrect behavior.  The
4745         only difference is the call to the low-level routine,
4746         HCPgetcompinfo, instead of HCPgetcompress.
4747 
4748 ******************************************************************************/
4749 intn
SDgetcompinfo(int32 sdsid,comp_coder_t * comp_type,comp_info * c_info)4750 SDgetcompinfo(int32 sdsid,     /* IN: dataset ID */
4751               comp_coder_t*    comp_type,   /* OUT: the type of compression */
4752               comp_info* c_info)/* OUT: ptr to compression information
4753                 structure for storing the retrieved info */
4754 {
4755     CONSTR(FUNC, "SDgetcompinfo");    /* for HGOTO_ERROR */
4756     NC        *handle;
4757     NC_var    *var;
4758     intn       status = FAIL;
4759     intn       ret_value = SUCCEED;
4760 
4761 #ifdef SDDEBUG
4762     fprintf(stderr, "SDgetcompinfo: I've been called\n");
4763 #endif /* SDDEBUG */
4764 
4765     /* clear error stack */
4766     HEclear();
4767 
4768     if(comp_type == NULL || c_info == NULL)
4769     HGOTO_ERROR(DFE_ARGS, FAIL);
4770 
4771     handle = SDIhandle_from_id(sdsid, SDSTYPE);
4772     if(handle == NULL || handle->file_type != HDF_FILE)
4773     HGOTO_ERROR(DFE_ARGS, FAIL);
4774     if(handle->vars == NULL)
4775     HGOTO_ERROR(DFE_ARGS, FAIL);
4776 
4777     var = SDIget_var(handle, sdsid);
4778     if(var == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
4779 
4780 #ifdef SDDEBUG
4781     printf("SDgetcompinfo(): var->data_ref=%d, var->aid=%d\n",(int)var->data_ref, (int)var->aid);
4782 #endif /* SDDEBUG */
4783     /* return with SUCCEED if the data set is empty and not compressed; when
4784        the data set is set compressed, the data has a valid reference number */
4785     if(!var->data_ref)
4786     {
4787     *comp_type = COMP_CODE_NONE;
4788     HGOTO_DONE(SUCCEED);
4789     }
4790 
4791     /* use lower-level routine to get the compression information */
4792     status = HCPgetcompinfo(handle->hdf_file, var->data_tag, var->data_ref,
4793         comp_type, c_info);
4794 
4795     if(status==FAIL) HGOTO_ERROR(DFE_INTERNAL, FAIL);
4796 
4797 done:
4798     if (ret_value == FAIL)
4799       { /* Failure cleanup */
4800 
4801       }
4802     /* Normal cleanup */
4803 
4804     return ret_value;
4805 } /* SDgetcompinfo */
4806 
4807 /******************************************************************************
4808  NAME
4809     SDgetcomptype -- Retrieves compression method of a dataset
4810 
4811  DESCRIPTION
4812     This routine uses HCPgetcomptype to retrieve the compression type
4813     of the identified dataset.
4814 
4815  RETURNS
4816     SUCCEED/FAIL
4817 
4818  MODIFICATION
4819     Dec 2007: Added to work around the problem where an external library is
4820         missing, SDgetcompinfo will fail.  This new API will not need
4821         to get the compression information but only the compression type,
4822         which sometime is the only thing an application needs - BMR
4823 
4824 ******************************************************************************/
4825 intn
SDgetcomptype(int32 sdsid,comp_coder_t * comp_type)4826 SDgetcomptype(int32 sdsid,        /* IN: dataset ID */
4827               comp_coder_t* comp_type    /* OUT: the type of compression */)
4828 {
4829     CONSTR(FUNC, "SDgetcomptype");    /* for HGOTO_ERROR */
4830     NC        *handle;
4831     NC_var    *var;
4832     intn       status = FAIL;
4833     intn       ret_value = SUCCEED;
4834 
4835 #ifdef SDDEBUG
4836     fprintf(stderr, "SDgetcomptype: I've been called\n");
4837 #endif /* SDDEBUG */
4838 
4839     /* clear error stack */
4840     HEclear();
4841 
4842     if(comp_type == NULL)
4843     HGOTO_ERROR(DFE_ARGS, FAIL);
4844 
4845     handle = SDIhandle_from_id(sdsid, SDSTYPE);
4846     if(handle == NULL || handle->file_type != HDF_FILE)
4847     HGOTO_ERROR(DFE_ARGS, FAIL);
4848     if(handle->vars == NULL)
4849     HGOTO_ERROR(DFE_ARGS, FAIL);
4850 
4851     var = SDIget_var(handle, sdsid);
4852     if(var == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
4853 
4854     /* return with SUCCEED if the data set is empty and not compressed - when
4855        the data set was set to be compressed, the data would have had a
4856        valid reference number even there was no data written */
4857     if(!var->data_ref)
4858     {
4859     *comp_type = COMP_CODE_NONE;
4860     HGOTO_DONE(SUCCEED);
4861     }
4862 
4863     /* use lower-level routine to get the compression method */
4864     status = HCPgetcomptype(handle->hdf_file, var->data_tag, var->data_ref,
4865         comp_type);
4866 
4867     if(status==FAIL) HGOTO_ERROR(DFE_INTERNAL, FAIL);
4868 
4869 done:
4870     if (ret_value == FAIL)
4871       { /* Failure cleanup */
4872 
4873       }
4874     /* Normal cleanup */
4875 
4876     return ret_value;
4877 } /* SDgetcomptype */
4878 
4879 /******************************************************************************
4880  NAME
4881     SDgetdatasize -- Retrieves the sizes of original and compressed data.
4882 
4883  DESCRIPTION
4884     This routine uses HCPgetdatasize to retrievethe original data and
4885     compressed data sizes of the identified dataset.  At least of the OUT
4886     arguments must be non-null and a null argument will be unchanged.
4887 
4888  RETURNS
4889     SUCCEED/FAIL
4890 
4891  MODIFICATION
4892 
4893 ******************************************************************************/
4894 intn
SDgetdatasize(int32 sdsid,int32 * comp_size,int32 * orig_size)4895 SDgetdatasize(int32 sdsid,        /* IN: dataset ID */
4896               int32* comp_size,        /* OUT: size of compressed data */
4897               int32* orig_size)        /* OUT: size of original data */
4898 
4899 {
4900     CONSTR(FUNC, "SDgetdatasize");    /* for HGOTO_ERROR */
4901     NC     *handle;
4902     NC_var *var;
4903     int32  *comp_size_tmp=NULL, *orig_size_tmp=NULL;
4904     intn   status = FAIL;
4905     intn   ret_value = SUCCEED;
4906 
4907     /* clear error stack */
4908     HEclear();
4909 
4910     /* must have at least one non-null argument */
4911     if (comp_size == NULL && orig_size == NULL)
4912     HGOTO_ERROR(DFE_ARGS, FAIL);
4913 
4914     /* allocate temporary buffers so user's arguments can be kept intact
4915        until finished */
4916     if (comp_size != NULL)
4917         comp_size_tmp = (int32 *) HDmalloc(sizeof(int32));
4918     if (orig_size != NULL)
4919         orig_size_tmp = (int32 *) HDmalloc(sizeof(int32));
4920 
4921     /* get NC_var record */
4922     handle = SDIhandle_from_id(sdsid, SDSTYPE);
4923     if(handle == NULL || handle->file_type != HDF_FILE)
4924     HGOTO_ERROR(DFE_ARGS, FAIL);
4925     if(handle->vars == NULL)
4926     HGOTO_ERROR(DFE_ARGS, FAIL);
4927 
4928     var = SDIget_var(handle, sdsid);
4929     if(var == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
4930 
4931     /* if the data ref# of the SDS is 0, it indicates that the SDS has
4932     not been written with data because no storage is created
4933     for the SDS data */
4934     if (var->data_ref == 0)
4935     {
4936     *comp_size_tmp = *orig_size_tmp = 0;
4937     }
4938     else
4939     {
4940     /* use lower-level routine to get the data sizes */
4941     status = HCPgetdatasize(handle->hdf_file, var->data_tag, var->data_ref,
4942         comp_size_tmp, orig_size_tmp);
4943     if (status == FAIL)
4944         HGOTO_ERROR(DFE_INTERNAL, FAIL);
4945     }
4946 
4947     /* Return the requested sizes */
4948     if (comp_size != NULL)
4949         *comp_size = *comp_size_tmp;
4950     if (orig_size != NULL)
4951         *orig_size = *orig_size_tmp;
4952 
4953 done:
4954     if (ret_value == FAIL)
4955       { /* Failure cleanup */
4956 
4957       }
4958     /* Normal cleanup */
4959     if (comp_size_tmp != NULL)
4960         HDfree(comp_size_tmp);
4961     if (orig_size_tmp != NULL)
4962         HDfree(orig_size_tmp);
4963 
4964     return ret_value;
4965 } /* SDgetdatasize */
4966 
4967 
4968 /******************************************************************************
4969  NAME
4970     SDfindattr -- find an attribute's index by name
4971 
4972  DESCRIPTION
4973     Given an ID to an object and an attribute name return the index
4974     of the attribute with that name.  This does not support any
4975     form of wildcards / regular expressions
4976 
4977  RETURNS
4978      An attribute index or FAIL
4979 
4980 ******************************************************************************/
4981 int32
SDfindattr(int32 id,const char * attrname)4982 SDfindattr(int32 id,       /* IN: object ID */
4983            const char *attrname  /* IN: attribute name */)
4984 {
4985     CONSTR(FUNC, "SDfindattr");    /* for HGOTO_ERROR */
4986     NC_array  *ap = NULL;
4987     NC_array **app = NULL;
4988     NC_attr  **attr = NULL;
4989     NC        *handle = NULL;
4990     int32      attrid;
4991     size_t      len;
4992     int32      ret_value = FAIL;
4993 
4994     /* clear error stack */
4995     HEclear();
4996 
4997     /* determine what type of ID we've been given */
4998     if(SDIapfromid(id, &handle, &app) == FAIL)
4999       {
5000     HGOTO_ERROR(DFE_ARGS, FAIL);
5001       }
5002 
5003     ap = (*app);
5004     if(ap == NULL)
5005       {
5006     HGOTO_ERROR(DFE_ARGS, FAIL);
5007       }
5008 
5009     /*
5010      * ap is the proper attribute list now look up something with this
5011      *  name
5012      */
5013 
5014     attr = (NC_attr **) ap->values;
5015     len = HDstrlen(attrname);
5016 
5017     for(attrid = 0 ; attrid < ap->count ; attrid++, attr++)
5018       {
5019           if( len == (*attr)->name->len
5020               && HDstrncmp(attrname, (*attr)->name->values, HDstrlen(attrname)) == 0)
5021             {
5022                 /* found it */
5023                 HGOTO_DONE(attrid);
5024             }
5025       }
5026 
5027 done:
5028     if (ret_value == FAIL)
5029       { /* Failure cleanup */
5030 
5031       }
5032     /* Normal cleanup */
5033 
5034 
5035     return ret_value;
5036 } /* SDfindattr */
5037 
5038 
5039 /******************************************************************************
5040  NAME
5041     SDidtoref -- get a unique reference number for this dataset
5042 
5043  DESCRIPTION
5044     Given an index return the ref of the associated NDG for
5045     inclusion in Vgroups and annotations
5046 
5047  RETURNS
5048      A reference number or FAIL
5049 
5050 ******************************************************************************/
5051 int32
SDidtoref(int32 id)5052 SDidtoref(int32 id /* IN: dataset ID */)
5053 {
5054     CONSTR(FUNC, "SDidtoref");    /* for HGOTO_ERROR */
5055     NC       *handle = NULL;
5056     NC_var   *var = NULL;
5057     int32     ret_value = FAIL;
5058 
5059 #ifdef SDDEBUG
5060     fprintf(stderr, "SDidtoref: I've been called\n");
5061 #endif
5062 
5063     /* clear error stack */
5064     HEclear();
5065 
5066     handle = SDIhandle_from_id(id, SDSTYPE);
5067     if(handle == NULL || handle->file_type != HDF_FILE)
5068       {
5069     HGOTO_ERROR(DFE_ARGS, FAIL);
5070       }
5071 
5072     if(handle->vars == NULL)
5073       {
5074     HGOTO_ERROR(DFE_ARGS, FAIL);
5075       }
5076 
5077     var = SDIget_var(handle, id);
5078     if(var == NULL)
5079       {
5080     HGOTO_ERROR(DFE_ARGS, FAIL);
5081       }
5082 
5083     ret_value = (int32) var->ndg_ref;
5084 
5085 done:
5086     if (ret_value == FAIL)
5087       { /* Failure cleanup */
5088 
5089       }
5090     /* Normal cleanup */
5091 
5092 
5093     return ret_value;
5094 } /* SDidtoref */
5095 
5096 
5097 /******************************************************************************
5098  NAME
5099     SDreftoindex -- map a reference number to a dataset index
5100 
5101  DESCRIPTION
5102     Given a ref number return the index of the cooresponding dataset
5103 
5104  RETURNS
5105     A dataset index or FAIL
5106 
5107 ******************************************************************************/
5108 int32
SDreftoindex(int32 fid,int32 ref)5109 SDreftoindex(int32 fid, /* IN: file ID */
5110              int32 ref  /* IN: reference number */)
5111 {
5112     CONSTR(FUNC, "SDreftoindex");    /* for HGOTO_ERROR */
5113     NC       *handle = NULL;
5114     NC_var  **dp = NULL;
5115     intn      ii;
5116     int32     ret_value = FAIL;
5117 
5118 #ifdef SDDEBUG
5119     fprintf(stderr, "SDreftoindex: I've been called\n");
5120 #endif
5121 
5122     /* clear error stack */
5123     HEclear();
5124 
5125     handle = SDIhandle_from_id(fid, CDFTYPE);
5126     if(handle == NULL || handle->file_type != HDF_FILE)
5127       {
5128     HGOTO_ERROR(DFE_ARGS, FAIL);
5129       }
5130 
5131     if(handle->vars == NULL)
5132       {
5133     HGOTO_ERROR(DFE_ARGS, FAIL);
5134       }
5135 
5136     dp = (NC_var**) handle->vars->values;
5137     for(ii = 0 ; ii < handle->vars->count ; ii++, dp++)
5138       {
5139         if((*dp)->ndg_ref == ref)
5140           {
5141         HGOTO_ERROR(DFE_ARGS, ii);
5142           }
5143       }
5144 
5145     ret_value = FAIL;
5146 
5147 done:
5148     if (ret_value == FAIL)
5149       { /* Failure cleanup */
5150 
5151       }
5152     /* Normal cleanup */
5153 
5154 
5155     return ret_value;
5156 } /* SDreftoindex */
5157 
5158 
5159 /******************************************************************************
5160  NAME
5161     SDisrecord -- check is var is a record variable
5162 
5163  DESCRIPTION
5164     Return TRUE if the dataset in question is a record variable
5165     else FALSE
5166 
5167  RETURNS
5168     TRUE/FALSE
5169 
5170 ******************************************************************************/
5171 int32
SDisrecord(int32 id)5172 SDisrecord(int32 id /* IN: dataset ID */)
5173 {
5174     CONSTR(FUNC, "SDisrecord");    /* for HGOTO_ERROR */
5175     NC       *handle;
5176     NC_var   *var;
5177     int32     ret_value = TRUE;
5178 
5179 #ifdef SDDEBUG
5180     fprintf(stderr, "SDisrecord: I've been called\n");
5181 #endif
5182 
5183     /* clear error stack */
5184     HEclear();
5185 
5186     handle = SDIhandle_from_id(id, SDSTYPE);
5187     if(handle == NULL)
5188       {
5189         HGOTO_ERROR(DFE_ARGS, FALSE);
5190       }
5191 
5192     if(handle->vars == NULL)
5193       {
5194         HGOTO_ERROR(DFE_ARGS, FALSE);
5195       }
5196 
5197     var = SDIget_var(handle, id);
5198     if(var == NULL)
5199       {
5200         HGOTO_ERROR(DFE_ARGS, FALSE);
5201       }
5202 
5203     if(var->shape == NULL)
5204       {
5205         /* EP thinks it should return true - BMR, bug #1045 */
5206         HGOTO_ERROR(DFE_ARGS, TRUE);
5207       }
5208 
5209     if(var->shape[0] == SD_UNLIMITED)
5210         ret_value = TRUE;
5211     else
5212         ret_value = FALSE;
5213 
5214 done:
5215     if (ret_value == FALSE)
5216       { /* FALSE cleanup */
5217 
5218       }
5219     /* Normal cleanup */
5220 
5221 
5222     return ret_value;
5223 } /* SDisrecord */
5224 
5225 
5226 /******************************************************************************
5227  NAME
5228     SDiscoordvar -- check is var is a coord var
5229 
5230  DESCRIPTION
5231     Return TRUE if the dataset in question is a coordinate variable
5232 
5233  RETURNS
5234      TRUE/FALSE
5235 
5236 ******************************************************************************/
5237 intn
SDiscoordvar(int32 id)5238 SDiscoordvar(int32 id /* IN: dataset ID */)
5239 {
5240     CONSTR(FUNC, "SDiscoordvar");    /* for HGOTO_ERROR */
5241     NC       *handle = NULL;
5242     NC_var   *var = NULL;
5243     NC_dim   *dim = NULL;
5244     int32     dimindex;
5245     intn      ret_value = TRUE;
5246 
5247 #ifdef SDDEBUG
5248     fprintf(stderr, "SDiscoordvar: I've been called\n");
5249 #endif
5250 
5251     /* clear error stack */
5252     HEclear();
5253 
5254     handle = SDIhandle_from_id(id, SDSTYPE);
5255     if(handle == NULL)
5256       {
5257         HGOTO_ERROR(DFE_ARGS, FAIL);
5258       }
5259 
5260     if(handle->vars == NULL)
5261       {
5262         HGOTO_ERROR(DFE_ARGS, FAIL);
5263       }
5264 
5265     var = SDIget_var(handle, id);
5266     if(var == NULL)
5267       {
5268         HGOTO_ERROR(DFE_ARGS, FAIL);
5269       }
5270 
5271     /* check whether this var is an SDS or a coordinate variable, then
5272        return the appropriate value (if and else if) */
5273     if (var->var_type == IS_SDSVAR)
5274       {
5275         HGOTO_DONE(FALSE);
5276       }
5277 
5278     else if(var->var_type == IS_CRDVAR)
5279       {
5280         HGOTO_DONE(TRUE);
5281       }
5282 
5283     /* whether or not this var is a coord var is unknown because the data was
5284        created by earlier version of the library which did not distinguish
5285        the two kinds of variables, SDS variable and coordinate variables.
5286        (see bugzilla 624) - BMR - 05/14/2007 */
5287     else  /* proceed exactly as before the fix of bugzilla 624 is available */
5288       {
5289     dimindex = var->assoc->values[0];
5290 
5291     dim = SDIget_dim(handle, dimindex);
5292     if(dim == NULL)
5293     {
5294             HGOTO_ERROR(DFE_ARGS, FALSE);
5295     }
5296 
5297     if(var->name->len != dim->name->len)
5298     {
5299             HGOTO_ERROR(DFE_ARGS, FALSE);
5300     }
5301 
5302     if(HDstrcmp(var->name->values, dim->name->values))
5303     {
5304             HGOTO_ERROR(DFE_ARGS, FALSE);
5305     }
5306 
5307     ret_value = TRUE;
5308       }
5309 
5310 done:
5311     if (ret_value == FALSE)
5312       { /* FALSE cleanup */
5313 
5314       }
5315     /* Normal cleanup */
5316 
5317 
5318     return ret_value;
5319 } /* SDiscoordvar */
5320 
5321 
5322 #if 0
5323 /* ---------------------------- RAGGED ARRAYS ----------------------------- */
5324 /*
5325 
5326   Ragged arrays are a cross between datasets and index structures.  The
5327   basic idea is that all but one of the dimensions is constant.  The
5328   other dimension can vary over the course of the dataset.  This is
5329   useful for storing equalarea grids and for making alogrithms much
5330   more complex.
5331 
5332   Ragged arrays can be multi-dimensional and, eventually, record variables
5333   too.  A 2-dimensional ragged array would look like:
5334 
5335   **********
5336   ********
5337   *********    <---------- This is a line
5338   *****
5339   ***
5340   *********
5341   *******
5342 
5343   The above ragged array has 7 "lines" the "line length" of the fifth line is
5344   three.  It is not necessary to set all of the line lengths at the same time
5345   nor retreive them all at the same time.   However, to specify the line
5346   length for line X, the length must be specified for all Y < X (is this
5347   really necessary?)
5348 
5349   Internally, the above ragged array would be stored as a one-dimensional
5350   dataset.  In addition, there will be a rag_fill array that contains the
5351   line lengths.  This rag_fill array will get written to a separate
5352   structure in the file (tag DFTAG_SDRAG).
5353 
5354 */
5355 /* ------------------------------------------------------------------------ */
5356 
5357 
5358 /******************************************************************************
5359   Set the lengths of the lines of a ragged array.
5360 
5361   Currently, these lines must be specified in increasing order (i.e. can't
5362   use hyperslab type locations to set them).  This should probably be made
5363   nicer once everything else works.
5364 
5365 ******************************************************************************/
5366 int32
5367 SDsetrag(int32 sdsid,
5368          int32 low,
5369          int32 count,
5370          int32 *sizes)
5371 {
5372     NC       *handle = NULL;
5373     NC_var   *var = NULL;
5374     int32     ret_value = SUCCEED;
5375 
5376 #ifdef SDDEBUG
5377     fprintf(stderr, "SDsetrag: I've been called\n");
5378 #endif
5379 
5380     /* clear error stack */
5381     HEclear();
5382 
5383     /* get the variable */
5384     handle = SDIhandle_from_id(sdsid, SDSTYPE);
5385     if(handle == NULL || handle->file_type != HDF_FILE)
5386       {
5387     HGOTO_ERROR(DFE_ARGS, FAIL);
5388       }
5389 
5390     if(handle->vars == NULL)
5391       {
5392     HGOTO_ERROR(DFE_ARGS, FAIL);
5393       }
5394 
5395     var = SDIget_var(handle, sdsid);
5396     if((var == NULL) || (var->is_ragged == FALSE))
5397       {
5398     HGOTO_ERROR(DFE_ARGS, FAIL);
5399       }
5400 
5401     /* verify writing to a valid area */
5402     if(var->rag_fill != low)
5403       {
5404         printf("var->rag_fill %d    low %d\n", var->rag_fill, low);
5405         HGOTO_ERROR(DFE_ARGS, FAIL);
5406       }
5407 
5408     /* allocate some space for the ragged dimension if needed */
5409     /* BUG: will need to be changed for ragged records */
5410     if(var->rag_list == NULL)
5411       {
5412         var->rag_list = (int32 *) HDmalloc(sizeof(int32) * var->dsizes[0]);
5413         if(var->rag_list == NULL)
5414           {
5415               HGOTO_ERROR(DFE_ARGS, FAIL);
5416           }
5417       }
5418 
5419     /* copy over the new values */
5420     HDmemcpy(&(var->rag_list[low]), sizes, sizeof(int32) * count);
5421 
5422     /* update count */
5423     var->rag_fill += count;
5424 
5425 done:
5426     if (ret_value == FAIL)
5427       { /* Failure cleanup */
5428 
5429       }
5430     /* Normal cleanup */
5431 
5432 
5433     return ret_value;
5434 } /* SDsetrag */
5435 
5436 #endif /* 0 */
5437 
5438 
5439 /******************************************************************************
5440  NAME
5441     SDsetaccesstype -- set the I/O access type of an SD
5442 
5443  DESCRIPTION
5444     Set the type of I/O (serial, parallel, ...) for accessing the
5445     data of the SD.  Access types can be DFACC_SERIAL, DFACC_PARALLEL,
5446     DFACC_DEFAULT.
5447 
5448  RETURNS
5449     Return SUCCEED if the SD data can be accessed via accesstype.
5450     Otherwise return FAIL.
5451 
5452 ******************************************************************************/
5453 intn
SDsetaccesstype(int32 id,uintn accesstype)5454 SDsetaccesstype(int32 id,         /* IN: dataset ID */
5455                 uintn accesstype  /* IN: access type */)
5456 {
5457     CONSTR(FUNC, "SDsetaccesstype");    /* for HGOTO_ERROR */
5458     NC       *handle = NULL;
5459     NC_var   *var = NULL;
5460     intn      ret_value = SUCCEED;
5461 
5462 #ifdef SDDEBUG
5463     fprintf(stderr, "SDsetaccesstype: I've been called\n");
5464 #endif
5465 
5466     /* clear error stack */
5467     HEclear();
5468 
5469     switch (accesstype)
5470       {
5471         case DFACC_DEFAULT:
5472         case DFACC_SERIAL:
5473         case DFACC_PARALLEL:
5474             break;
5475         default:
5476             HGOTO_ERROR(DFE_ARGS, FAIL);
5477       }
5478 
5479     handle = SDIhandle_from_id(id, SDSTYPE);
5480     if(handle == NULL || handle->file_type != HDF_FILE)
5481       {
5482     HGOTO_ERROR(DFE_ARGS, FAIL);
5483       }
5484 
5485     if(handle->vars == NULL)
5486       {
5487     HGOTO_ERROR(DFE_ARGS, FAIL);
5488       }
5489 
5490     var = SDIget_var(handle, id);
5491     if(var == NULL)
5492       {
5493     HGOTO_ERROR(DFE_ARGS, FAIL);
5494       }
5495 
5496     /* if aid is not valid yet, there is no access_rec setup yet. */
5497     /* Go ahead and try set it up. */
5498     if(var->aid == FAIL && hdf_get_vp_aid(handle, var) == FAIL)
5499         ret_value = FAIL;
5500     else
5501         ret_value = (intn)Hsetaccesstype(var->aid, accesstype);
5502 
5503 done:
5504     if (ret_value == FAIL)
5505       { /* Failure cleanup */
5506 
5507       }
5508     /* Normal cleanup */
5509 
5510 
5511     return ret_value;
5512 } /* SDsetaccesstype */
5513 
5514 
5515 /******************************************************************************
5516  NAME
5517     SDsetblocksize -- set the size of the linked blocks created.
5518 
5519  DESCRIPTION
5520     Set the size of the blocks used for storing the data for unlimited
5521     dimension datasets.  This is used when creating new datasets only,
5522     it does not have any affect on existing datasets.  The block_size
5523     should probably be set to a multiple of the "slice" size.
5524 
5525  RETURNS
5526     SUCCEED/FAIL
5527 
5528 ******************************************************************************/
5529 intn
SDsetblocksize(int32 sdsid,int32 block_size)5530 SDsetblocksize(int32 sdsid,      /* IN: dataset ID */
5531                int32 block_size  /* IN: size of the block in bytes */)
5532 {
5533     CONSTR(FUNC, "SDsetblocksize");    /* for HGOTO_ERROR */
5534     NC      *handle = NULL;
5535     NC_var  *var = NULL;
5536     intn     ret_value = SUCCEED;
5537 
5538 #ifdef SDDEBUG
5539     fprintf(stderr, "SDsetblocksize: I've been called\n");
5540 #endif
5541 
5542     /* clear error stack */
5543     HEclear();
5544 
5545     /* get the handle */
5546     handle = SDIhandle_from_id(sdsid, SDSTYPE);
5547     if(handle == NULL)
5548       {
5549     HGOTO_ERROR(DFE_ARGS, FAIL);
5550       }
5551 
5552     /* get the variable */
5553     var = SDIget_var(handle, sdsid);
5554     if(var == NULL)
5555       {
5556     HGOTO_ERROR(DFE_ARGS, FAIL);
5557       }
5558 
5559     /* set the block size */
5560     var->block_size = block_size;
5561 
5562 done:
5563     if (ret_value == FAIL)
5564       { /* Failure cleanup */
5565 
5566       }
5567     /* Normal cleanup */
5568 
5569     return ret_value;
5570 } /* SDsetblocksize */
5571 
5572 
5573 /******************************************************************************
5574  NAME
5575     SDgetblocksize -- get the size of the linked blocks.
5576 
5577  DESCRIPTION
5578     Get the size of the blocks to be used for storing data of unlimited
5579     dimension datasets.
5580 
5581  RETURNS
5582     SUCCEED/FAIL
5583 
5584 ******************************************************************************/
5585 intn
SDgetblocksize(int32 sdsid,int32 * block_size)5586 SDgetblocksize(int32 sdsid,      /* IN: dataset ID */
5587                int32 *block_size /* OUT: size of the block in bytes */)
5588 {
5589     CONSTR(FUNC, "SDgetblocksize");    /* for HGOTO_ERROR */
5590     NC      *handle = NULL;
5591     NC_var  *var = NULL;
5592     int32    block_length = -1;
5593     int32    temp_aid = -1;
5594     intn     ret_value = SUCCEED;
5595 
5596 #ifdef SDDEBUG
5597     fprintf(stderr, "SDgetblocksize: I've been called\n");
5598 #endif
5599 
5600     /* clear error stack */
5601     HEclear();
5602 
5603     /* get the handle */
5604     handle = SDIhandle_from_id(sdsid, SDSTYPE);
5605     if(handle == NULL)
5606     HGOTO_ERROR(DFE_ARGS, FAIL);
5607 
5608     /* get the variable */
5609     var = SDIget_var(handle, sdsid);
5610     if(var == NULL)
5611     HGOTO_ERROR(DFE_ARGS, FAIL);
5612 
5613     /* Get access id using data tag/ref.  Fail if data ref has not been defined;
5614        this happens when SDgetblocksize is called when no data has been written
5615        or no special element has been created. -BMR, 2013/12/17 */
5616     temp_aid = var->aid;    /* use temp to avoid messing up var->aid. -BMR */
5617     if (temp_aid == FAIL)
5618     {
5619     if (var->data_ref == 0)        /* no data means no linked-block storage */
5620             HGOTO_ERROR(DFE_GENAPP, FAIL);
5621 
5622     /* Start read access on the element to acquire access id */
5623         temp_aid = Hstartread(handle->hdf_file, var->data_tag, var->data_ref);
5624         if(temp_aid == FAIL) /* catch FAIL from Hstartread */
5625             HGOTO_ERROR(DFE_INTERNAL, FAIL);
5626     }
5627 
5628     /* Use internal routine to do the actual retrieval */
5629     if (HLgetblockinfo(temp_aid, &block_length, NULL) == FAIL)
5630         HGOTO_ERROR(DFE_INTERNAL, FAIL);
5631     if (block_length > 0)
5632     *block_size = block_length;
5633 
5634     /* End access to the temp_aid only when var->aid is -1, so we won't end
5635        access var->aid if it was valid. */
5636     if (var->aid == FAIL && temp_aid != FAIL)
5637     Hendaccess(temp_aid);
5638 done:
5639     if (ret_value == FAIL)
5640       { /* Failure cleanup */
5641     if (var->aid == FAIL && temp_aid != FAIL)
5642         Hendaccess(temp_aid);
5643       }
5644     /* Normal cleanup */
5645     return ret_value;
5646 } /* SDgetblocksize */
5647 
5648 
5649 /******************************************************************************
5650  NAME
5651    SDsetfillmode -- set fill mode as fill or nofill
5652 
5653  DESCRIPTION
5654    Calls ncsetfill().
5655 
5656  RETURNS
5657    The current fill mode of the file, or FAIL for error.
5658 
5659 ******************************************************************************/
5660 intn
SDsetfillmode(int32 sd_id,intn fillmode)5661 SDsetfillmode(int32 sd_id,  /* IN: HDF file ID, returned from SDstart */
5662               intn fillmode /* IN: Desired fill mode for the file,
5663                                    either SD_FILL or SD_NOFILL.
5664                                    SD_FILL is the default mode. */)
5665 {
5666     CONSTR(FUNC, "SDsetfillmode");    /* for HGOTO_ERROR */
5667     NC     *handle = NULL;
5668     intn    cdfid;
5669     intn    ret_value = FAIL;
5670 
5671 #ifdef SDDEBUG
5672     fprintf(stderr, "SDsetfillmode: I've been called\n");
5673 #endif
5674 
5675     /* clear error stack */
5676     HEclear();
5677 
5678     /* get the handle */
5679     handle = SDIhandle_from_id(sd_id, CDFTYPE);
5680     if(handle == NULL)
5681       {
5682         HGOTO_ERROR(DFE_ARGS, FAIL);
5683       }
5684 
5685     cdfid = (intn)sd_id & 0xffff;
5686     ret_value = ncsetfill(cdfid, fillmode);
5687 
5688 done:
5689     if (ret_value == FAIL)
5690       { /* Failure cleanup */
5691 
5692       }
5693     /* Normal cleanup */
5694 
5695 
5696     return ret_value;
5697 } /* SDsetfillmode() */
5698 
5699 /******************************************************************************
5700  NAME
5701     SDsetdimval_comp -- set dimval backward compatibility
5702 
5703  DESCRIPTION
5704 
5705  RETURNS
5706     SUCCEED/FAIL
5707 
5708 ******************************************************************************/
5709 intn
SDsetdimval_comp(int32 dimid,intn comp_mode)5710 SDsetdimval_comp(int32 dimid,    /* IN: dimension ID, returned from SDgetdimid */
5711                  intn comp_mode  /* IN: backward compatibility:
5712                                     SD_DIMVAL_BW_COMP -- compatible
5713                                     SD_DIMVAL_BW_INCOMP -- incompatible.
5714                                     (defined in mfhdf.h ) */)
5715 {
5716     CONSTR(FUNC, "SDsetdimval_comp");    /* for HGOTO_ERROR */
5717     NC      *handle = NULL;
5718     NC_dim  *dim = NULL;
5719     intn     ret_value = SUCCEED;
5720 
5721 #ifdef SDDEBUG
5722     fprintf(stderr, "SDsetdimval_comp: I've been called\n");
5723 #endif
5724 
5725     /* clear error stack */
5726     HEclear();
5727 
5728     /* get the handle */
5729     handle = SDIhandle_from_id(dimid, DIMTYPE);
5730     if(handle == NULL)
5731       {
5732     HGOTO_ERROR(DFE_ARGS, FAIL);
5733       }
5734 
5735     /* get the dimension structure */
5736     dim = SDIget_dim(handle, dimid);
5737     if(dim == NULL)
5738       {
5739     HGOTO_ERROR(DFE_ARGS, FAIL);
5740       }
5741 
5742 /*    if (dim->size != SD_UNLIMITED
5743         && dim->dim00_compat != comp_mode )
5744 */
5745     if (dim->dim00_compat != comp_mode)
5746       {
5747         dim->dim00_compat = comp_mode;
5748 
5749         /* make sure it gets reflected in the file */
5750         handle->flags |= NC_HDIRTY;
5751       }
5752 
5753 done:
5754     if (ret_value == FAIL)
5755       { /* Failure cleanup */
5756 
5757       }
5758     /* Normal cleanup */
5759 
5760 
5761     return ret_value;
5762 } /* SDsetdimval_comp */
5763 
5764 
5765 /******************************************************************************
5766  NAME
5767    SDisdimval_bwcomp -- get dimval backward compatibility
5768 
5769  DESCRIPTION
5770 
5771  RETURNS
5772     SD_DIMVAL_BW_COMP if dimval is backward compatible;
5773     SD_DIMVAL_BW_INCOMP for not compatible; FAIL for error.
5774 
5775 ******************************************************************************/
5776 intn
SDisdimval_bwcomp(int32 dimid)5777 SDisdimval_bwcomp(int32 dimid /* IN: dimension ID, returned from SDgetdimid */)
5778 {
5779     CONSTR(FUNC, "SDisdimval_bwcomp");    /* for HGOTO_ERROR */
5780     NC      *handle = NULL;
5781     NC_dim  *dim = NULL;
5782     intn    ret_value = FAIL;
5783 
5784 #ifdef SDDEBUG
5785     fprintf(stderr, "SDisdimval_bwcomp: I've been called\n");
5786 #endif
5787 
5788     /* clear error stack */
5789     HEclear();
5790 
5791     /* get the handle */
5792     handle = SDIhandle_from_id(dimid, DIMTYPE);
5793     if(handle == NULL)
5794       {
5795     HGOTO_ERROR(DFE_ARGS, FAIL);
5796       }
5797 
5798     /* get the dimension structure */
5799     dim = SDIget_dim(handle, dimid);
5800     if(dim == NULL)
5801       {
5802     HGOTO_ERROR(DFE_ARGS, FAIL);
5803       }
5804 
5805 /* Default is incompatible. Return dim->dim00_compat.
5806     if (dim->size == SD_UNLIMITED)
5807         ret_value = SD_DIMVAL_BW_COMP;
5808     else
5809 */
5810     ret_value = dim->dim00_compat;
5811 
5812 done:
5813     if (ret_value == FAIL)
5814       { /* Failure cleanup */
5815 
5816       }
5817     /* Normal cleanup */
5818 
5819 
5820     return ret_value;
5821 } /* SDisdimval_bwcomp */
5822 
5823 /*====================== Chunking Routines ================================*/
5824 
5825 /******************************************************************************
5826  NAME
5827       SDsetchunk  -- make SDS a chunked SDS
5828 
5829  DESCRIPTION
5830       This routine makes the SDS a chunked SDS according to the chunk
5831       definiton passed in.
5832 
5833       The dataset currently cannot be special already.  i.e. NBIT,
5834       COMPRESSED, or EXTERNAL. This is an Error.
5835 
5836       The defintion of the HDF_CHUNK_DEF union with relvant fields is:
5837 
5838       typedef union hdf_chunk_def_u
5839       {
5840          int32   chunk_lengths[H4_MAX_VAR_DIMS];  Chunk lengths along each dimension
5841 
5842          struct
5843           {
5844             int32     chunk_lengths[H4_MAX_VAR_DIMS]; Chunk lengths along each dimension
5845             int32     comp_type;                   Compression type
5846             comp_info cinfo;                       Compression info struct
5847           }comp;
5848 
5849       } HDF_CHUNK_DEF
5850 
5851       The variable agruement 'flags' is a bit-or'd value which can currently be
5852       'HDF_CHUNK' or 'HDF_CHUNK | HDF_COMP'.
5853 
5854       The simplist is the 'chunk_lengths' array specifiying chunk
5855       lengths for each dimension where the 'flags' argument set to
5856       'HDF_CHUNK';
5857 
5858       COMPRESSION is set by using the 'HDF_CHUNK_DEF' union to set the
5859       appropriate compression information along with the required chunk lengths
5860       for each dimension. The compression information is the same as
5861       that set in 'SDsetcompress()'. The bit-or'd 'flags' argument' is set to
5862       'HDF_CHUNK | HDF_COMP'.
5863 
5864       See the example in pseudo-C below for further usage.
5865 
5866       The maximum number of Chunks in an HDF file is 65,535.
5867 
5868       The dataset currently cannot have an UNLIMITED dimension.
5869 
5870       The performance of the SDxxx interface with chunking is greatly
5871       affected by the users access pattern over the dataset and by
5872       the maximum number of chunks set in the chunk cache. The cache contains
5873       the Least Recently Used(LRU cache replacment policy) chunks. See the
5874       routine SDsetchunkcache() for further info on the chunk cache and how
5875       to set the maximum number of chunks in the chunk cache. A default chunk
5876       cache is always created.
5877 
5878       The following example shows the organization of chunks for a 2D array.
5879       e.g. 4x4 array with 2x2 chunks. The array shows the layout of
5880            chunks in the chunk array.
5881 
5882             4 ---------------------
5883               |         |         |
5884         Y     |  (0,1)  |  (1,1)  |
5885         ^     |         |         |
5886         |   2 ---------------------
5887         |     |         |         |
5888         |     |  (0,0)  |  (1,0)  |
5889         |     |         |         |
5890         |     ---------------------
5891         |     0         2         4
5892         ---------------> X
5893 
5894         --Without compression--:
5895         {
5896         HDF_CHUNK_DEF chunk_def;
5897 
5898         .......
5899         -- Set chunk lengths --
5900         chunk_def.chunk_lengths[0]= 2;
5901         chunk_def.chunk_lengths[1]= 2;
5902 
5903         -- Set Chunking --
5904         SDsetchunk(sdsid, chunk_def, HDF_CHUNK);
5905          ......
5906         }
5907 
5908         --With compression--:
5909         {
5910         HDF_CHUNK_DEF chunk_def;
5911 
5912         .......
5913         -- Set chunk lengths first --
5914         chunk_def.chunk_lengths[0]= 2;
5915         chunk_def.chunk_lengths[1]= 2;
5916 
5917         -- Set compression --
5918         chunk_def.comp.cinfo.deflate.level = 9;
5919         chunk_def.comp.comp_type = COMP_CODE_DEFLATE;
5920 
5921         -- Set Chunking with Compression --
5922         SDsetchunk(sdsid, chunk_def, HDF_CHUNK | HDF_COMP);
5923          ......
5924         }
5925 
5926         NOTE:
5927            This routine directly calls a Special Chunked Element fcn HMCxxx.
5928 
5929  RETURNS
5930         SUCCEED/FAIL
5931 
5932  AUTHOR
5933         -GeorgeV
5934 ******************************************************************************/
5935 intn
SDsetchunk(int32 sdsid,HDF_CHUNK_DEF chunk_def,int32 flags)5936 SDsetchunk(int32         sdsid,     /* IN: sds access id */
5937            HDF_CHUNK_DEF chunk_def, /* IN: chunk definition */
5938            int32         flags      /* IN: flags */)
5939 {
5940     CONSTR(FUNC, "SDsetchunk");    /* for HGOTO_ERROR */
5941     NC        *handle = NULL;      /* file handle */
5942     NC_var    *var    = NULL;      /* SDS variable */
5943     NC_attr  **fill_attr = NULL;   /* fill value attribute */
5944     HCHUNK_DEF chunk[1];           /* H-level chunk defintion */
5945     HDF_CHUNK_DEF *cdef   = NULL;  /* SD Chunk definition */
5946     model_info minfo;              /* dummy model info struct */
5947     comp_info  cinfo;              /* compression info - NBIT */
5948     uint32 comp_config;
5949     int32     *cdims    = NULL;    /* array of chunk lengths */
5950     int32      fill_val_len = 0;   /* fill value length */
5951     void      *fill_val    = NULL; /* fill value */
5952     int32      ndims    = 0;       /* # dimensions i.e. rank */
5953     uint8      nlevels  = 1;       /* default # levels is 1 */
5954     int8       platntsubclass;     /* the machine type of the current platform */
5955     int8       outntsubclass;      /* the data's machine type */
5956     uintn      convert;            /* whether to convert or not */
5957     int32 tBuf_size = 0;       /* conversion buffer size */
5958     void  *tBuf = NULL;           /* buffer used for conversion */
5959     intn       i;                  /* loop variable */
5960     intn       ret_value = SUCCEED;   /* return value */
5961 
5962 #ifdef CHK_DEBUG
5963     fprintf(stderr,"SDsetchunk: called  \n");
5964 #endif
5965 
5966     /* clear error stack */
5967     HEclear();
5968 
5969      /* make sure this is cleared */
5970      memset(chunk,0,sizeof(chunk[0]));
5971     /* Check some args */
5972 
5973     /* get file handle and verify it is an HDF file
5974        we only handle dealing with SDS only not coordinate variables */
5975     handle = SDIhandle_from_id(sdsid, SDSTYPE);
5976     if(handle == NULL || handle->file_type != HDF_FILE || handle->vars == NULL)
5977       {
5978     HGOTO_ERROR(DFE_ARGS, FAIL);
5979       }
5980 
5981     /* get variable from id */
5982     var = SDIget_var(handle, sdsid);
5983     if(var == NULL)
5984       {
5985     HGOTO_ERROR(DFE_ARGS, FAIL);
5986       }
5987 
5988     /* disallow setting chunk for SDS with rank = 0 - BMR, bug #1045 */
5989     if(var->shape == NULL)
5990       {
5991         HGOTO_ERROR(DFE_ARGS, FAIL);
5992       }
5993 
5994     /* Decide type of defintion passed in  */
5995     switch (flags)
5996       {
5997       case HDF_CHUNK: /* case where chunk_def only has chunk lengths */
5998           cdef  = (HDF_CHUNK_DEF *)&chunk_def;
5999           cdims = cdef->chunk_lengths;
6000           chunk[0].chunk_flag = 0;  /* nothing set for this now */
6001           chunk[0].comp_type = COMP_CODE_NONE; /* nothing set */
6002           chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
6003           chunk[0].cinfo = &cinfo; /* dummy */
6004           chunk[0].minfo = &minfo; /* dummy */
6005           break;
6006       case (HDF_CHUNK | HDF_COMP):
6007       /*  EIP 9/11/03
6008        *  We have to take special care if SZIP library is not available;
6009        *  For all other compression types do
6010        */
6011           cdef  = (HDF_CHUNK_DEF *)&chunk_def;
6012 
6013     HCget_config_info( (comp_coder_t)cdef->comp.comp_type , &comp_config);
6014     if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
6015     /* coder not present?? */
6016         HGOTO_ERROR(DFE_NOENCODER, FAIL);
6017     }
6018     if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
6019     /* encoder not present?? */
6020     HGOTO_ERROR(DFE_BADCODER, FAIL);
6021     }
6022       if ((comp_coder_t)cdef->comp.comp_type != COMP_CODE_SZIP) {
6023           cdims = cdef->comp.chunk_lengths;
6024           chunk[0].chunk_flag = SPECIAL_COMP;  /* Compression */
6025           chunk[0].comp_type  = (comp_coder_t)cdef->comp.comp_type;
6026           chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
6027           chunk[0].cinfo = &cdef->comp.cinfo;
6028           chunk[0].minfo = &minfo; /* dummy */
6029        }
6030        else /* requested compression is SZIP */
6031 
6032 #ifdef H4_HAVE_LIBSZ          /* we have the library */
6033           {
6034            cdims = cdef->comp.chunk_lengths;
6035            chunk[0].chunk_flag = SPECIAL_COMP;  /* Compression */
6036            chunk[0].comp_type  = (comp_coder_t)cdef->comp.comp_type;
6037            chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
6038            chunk[0].minfo = &minfo; /* dummy */
6039         HDmemcpy(&cinfo,&(cdef->comp.cinfo),sizeof(comp_info));
6040     if ( SDsetup_szip_parms( sdsid, handle, &cinfo, cdims) == FAIL ) {
6041         HGOTO_ERROR(DFE_INTERNAL, FAIL);
6042     }
6043               chunk[0].cinfo = &cinfo;
6044           }
6045 #else                         /* we do not have the SZIP library */
6046           {
6047         HGOTO_ERROR(DFE_BADCODER, FAIL);
6048           }
6049 #endif /* H4_HAVE_LIBSZ */
6050 
6051           break;
6052       case (HDF_CHUNK | HDF_NBIT):
6053           cdef  = (HDF_CHUNK_DEF *)&chunk_def;
6054           cdims = cdef->nbit.chunk_lengths;
6055           chunk[0].chunk_flag = SPECIAL_COMP;  /* NBIT is a type of compression */
6056           chunk[0].comp_type  = COMP_CODE_NBIT;   /* Nbit compression? */
6057           chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
6058           /* set up n-bit parameters */
6059           cinfo.nbit.nt        = var->HDFtype;
6060           cinfo.nbit.sign_ext  = cdef->nbit.sign_ext;
6061           cinfo.nbit.fill_one  = cdef->nbit.fill_one;
6062           cinfo.nbit.start_bit = cdef->nbit.start_bit;
6063           cinfo.nbit.bit_len   = cdef->nbit.bit_len;
6064           chunk[0].cinfo = &cinfo;
6065           chunk[0].minfo = &minfo; /* dummy */
6066           break;
6067       default:
6068     HGOTO_ERROR(DFE_ARGS, FAIL);
6069       }
6070 
6071 #ifdef CHK_DEBUG
6072     fprintf(stderr,"SDsetchunk: does data ref exist?  \n");
6073 #endif
6074     /* Does data exist yet */
6075     if(!var->data_ref)
6076       {   /* doesn't exist */
6077 #ifdef CHK_DEBUG
6078     fprintf(stderr,"SDsetchunk: data ref does not exist  \n");
6079 #endif
6080           /* element doesn't exist so we need a reference number */
6081           var->data_ref=Hnewref(handle->hdf_file);
6082           if(var->data_ref == 0)
6083             {
6084 #ifdef CHK_DEBUG
6085     fprintf(stderr,"SDsetchunk: failed to get data ref  \n");
6086 #endif
6087               HGOTO_ERROR(DFE_ARGS, FAIL);
6088             }
6089       }
6090     else /* data ref exists, Error since can't convert existing SDS to chunked */
6091       {
6092     HGOTO_ERROR(DFE_ARGS, FAIL);
6093       }
6094 
6095     /* Now start setting chunk info */
6096     ndims = var->assoc->count; /* set number of dims i.e. rank */
6097 #ifdef CHK_DEBUG
6098     fprintf(stderr,"SDsetchunk: got data ref, ndims =%d  \n",ndims);
6099 #endif
6100 
6101     /* allocate space for chunk dimensions */
6102     if ((chunk[0].pdims = (DIM_DEF *)HDmalloc(ndims*sizeof(DIM_DEF))) == NULL)
6103       {
6104     HGOTO_ERROR(DFE_ARGS, FAIL);
6105       }
6106 
6107     /* initialize datset/chunk sizes using CHUNK defintion structure */
6108     chunk[0].chunk_size = 1;
6109     chunk[0].num_dims = ndims;
6110 
6111 /* Developer's note: should move unlim check to the beginning and clean up this for loop */
6112     for (i = 0; i < ndims; i++)
6113       {   /* get dimension length from shape arrays */
6114           /* check if dimension in unlimited since we don't
6115              handle that yet */
6116           if (var->shape[i] != SD_UNLIMITED)
6117               chunk[0].pdims[i].dim_length = (int32) var->shape[i];
6118           else
6119             { /* UNLIMITED dimension case */
6120 #ifdef CHK_DEBUG
6121     fprintf(stderr,"SDsetchunk: unlimited dimension case  \n");
6122     fflush(stderr);
6123 #endif
6124                 HGOTO_ERROR(DFE_ARGS, FAIL);
6125             }
6126 
6127 #ifdef CHK_DEBUG
6128     fprintf(stderr,"SDsetchunk: (int32) var->shape[%d]=%d\n",i,(int32) var->shape[i]);
6129     fflush(stderr);
6130 #endif
6131           /* set chunk lengths */
6132           if (cdims[i] >= 1)
6133               chunk[0].pdims[i].chunk_length = cdims[i];
6134           else
6135             { /* chunk length is less than 1 */
6136 #ifdef CHK_DEBUG
6137     fprintf(stderr,"SDsetchunk: chunk length less than 1, cdims[%d]=%d \n",i,cdims[i]);
6138     fflush(stderr);
6139 #endif
6140                 HGOTO_ERROR(DFE_ARGS, FAIL);
6141             }
6142 #ifdef CHK_DEBUG
6143     fprintf(stderr,"SDsetchunk: cdims[%d]=%d \n",i,cdims[i]);
6144     fflush(stderr);
6145 #endif
6146           /* Data distribution along dimensions
6147           *  Check dimension length agains chunk length */
6148           if (cdims[i] == (int32)var->shape[i])
6149               chunk[0].pdims[i].distrib_type = 0;     /* NONE */
6150           else
6151               chunk[0].pdims[i].distrib_type = 1;     /* BLOCK */
6152 
6153           /* compute chunk size */
6154           chunk[0].chunk_size *= cdims[i];
6155       } /* end for ndims */
6156 
6157     /* Set number type size i.e. size of data type */
6158     chunk[0].nt_size = var->HDFsize;
6159 
6160 #ifdef CHK_DEBUG
6161     fprintf(stderr,"SDsetchunk: var->HDFsize=%d\n",var->HDFsize);
6162     fflush(stderr);
6163 #endif
6164     /* allocate space for fill value whose number type is the same as
6165        the dataset */
6166     fill_val_len = var->HDFsize;
6167     if ((fill_val = (void *)HDmalloc(fill_val_len)) == NULL)
6168       {
6169     HGOTO_ERROR(DFE_ARGS, FAIL);
6170       }
6171 
6172     /* get fill value if one is set for this Dataset.
6173        The number type is the same as that for the dataset. */
6174     fill_attr = (NC_attr **) NC_findattr(&(var->attrs), _FillValue);
6175     if(fill_attr != NULL)
6176       {
6177           NC_copy_arrayvals((char *)fill_val, (*fill_attr)->data) ;
6178       }
6179     else /* copy standard default fill value for now */
6180       {
6181         void *p = fill_val;
6182 
6183         switch(var->HDFtype & 0xff)
6184           {
6185           case DFNT_CHAR:
6186           case DFNT_UCHAR:
6187               *((uint8 *)p) = FILL_CHAR;
6188               break;
6189           case DFNT_INT8:
6190           case DFNT_UINT8:
6191               *((int8 *)p) = FILL_BYTE;
6192               break;
6193           case DFNT_INT16:
6194           case DFNT_UINT16:
6195               *((int16 *)p) = FILL_SHORT;
6196               break;
6197           case DFNT_INT32:
6198           case DFNT_UINT32:
6199               *((int32 *)p) = FILL_LONG;
6200               break;
6201           case DFNT_FLOAT32:
6202               *((float32 *)p) = FILL_FLOAT;
6203               break;
6204           case DFNT_FLOAT64:
6205               *((float64 *)p) = FILL_DOUBLE;
6206               break;
6207         default:
6208             HGOTO_ERROR(DFE_ARGS, FAIL);
6209         }
6210       }
6211 
6212     /* figure out if fill value has to be converted */
6213     if (FAIL == (platntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6214       {
6215     HGOTO_ERROR(DFE_INTERNAL, FAIL);
6216       }
6217 
6218     if (DFKisnativeNT(var->HDFtype))
6219       {
6220         if (FAIL == (outntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6221           {
6222               HGOTO_ERROR(DFE_INTERNAL, FAIL);
6223           }
6224        }
6225     else
6226       {
6227           outntsubclass = DFKislitendNT(var->HDFtype) ? DFNTF_PC : DFNTF_HDFDEFAULT;
6228       }
6229 
6230     convert = (uintn)(platntsubclass != outntsubclass);
6231 
6232     /* make sure our tmp buffer is big enough to hold fill value */
6233     if(convert && tBuf_size < fill_val_len)
6234       {
6235           if(tBuf != NULL)
6236               HDfree(tBuf);
6237           tBuf_size = fill_val_len;
6238           tBuf      = HDmalloc(tBuf_size);
6239           if(tBuf == NULL)
6240             {
6241                 tBuf_size = 0;
6242                 HGOTO_ERROR(DFE_NOSPACE, FAIL);
6243             } /* end if */
6244       } /* end if */
6245 
6246 #ifdef CHK_DEBUG
6247     fprintf(stderr,"SDsetchunk: get ready to create, convert=%d\n",convert);
6248 #endif
6249     if (convert)
6250       { /* convert fill value */
6251           if (FAIL == DFKconvert(fill_val, tBuf, var->HDFtype,
6252                                 (uint32) (fill_val_len/var->HDFsize), DFACC_WRITE, 0, 0))
6253             {
6254                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
6255             }
6256 
6257         /* check to see already special.
6258            Error if already special since doubly special elements are
6259            not yet handled. HMCcreate should catch this....*/
6260         /* Create SDS as chunked element  */
6261         ret_value = HMCcreate(handle->hdf_file,       /* HDF file handle */
6262                            (uint16)DATA_TAG,       /* Data tag */
6263                            (uint16) var->data_ref, /* Data ref */
6264                            nlevels,                /* nlevels */
6265                            fill_val_len,           /* fill value length */
6266                            tBuf,           /* fill value */
6267                            (HCHUNK_DEF *)chunk      /* chunk definition */);
6268       }
6269     else /* no need to convert fill value */
6270       {
6271           /* check to see already special.
6272              Error if already special since doubly special elements are
6273              not yet handled. HMCcreate should catch this....*/
6274           /* Create SDS as chunked element  */
6275           ret_value = HMCcreate(handle->hdf_file,       /* HDF file handle */
6276                              (uint16)DATA_TAG,       /* Data tag */
6277                              (uint16) var->data_ref, /* Data ref */
6278                              nlevels,                /* nlevels */
6279                              fill_val_len,           /* fill value length */
6280                              fill_val,       /* fill value */
6281                              (HCHUNK_DEF *)chunk      /* chunk definition */);
6282       }
6283 
6284 #ifdef CHK_DEBUG
6285     fprintf(stderr,"SDsetchunk: ret_value =%d \n", ret_value);
6286 #endif
6287     /* check return */
6288     if(ret_value != FAIL)
6289       { /* close old aid and set new one
6290          ..hmm......maybe this is for the doubly specail hack since
6291          this code framework came from SDsetcompress()....*/
6292           if((var->aid != 0) && (var->aid != FAIL))
6293             {
6294               if (Hendaccess(var->aid) == FAIL)
6295                   {
6296                       HGOTO_ERROR(DFE_INTERNAL, FAIL);
6297                   }
6298             }
6299 
6300           var->aid = ret_value;
6301           ret_value = SUCCEED; /* re-set to successful */
6302       } /* end if */
6303 
6304 done:
6305     if (ret_value == FAIL)
6306       { /* Failure cleanup */
6307 
6308       }
6309     /* Normal cleanup */
6310 
6311     /* free fill value */
6312     if (fill_val != NULL)
6313         HDfree(fill_val);
6314     if (tBuf != NULL)
6315         HDfree(tBuf);
6316 
6317     /* free chunk dims */
6318     if (chunk[0].pdims != NULL)
6319         HDfree(chunk[0].pdims);
6320 
6321 
6322     return ret_value;
6323 } /* SDsetchunk */
6324 
6325 
6326 /******************************************************************************
6327  NAME
6328      SDgetchunkinfo -- get Info on SDS
6329 
6330  DESCRIPTION
6331      This routine gets any special information on the SDS. If its chunked,
6332      chunked and compressed or just a regular SDS. Currently it will only
6333      fill the array of chunk lengths for each dimension as specified in
6334      the 'HDF_CHUNK_DEF' union. It does not tell you the type of compression
6335      or the compression parameters used. You can pass in a NULL for 'chunk_def'
6336      if don't want the chunk lengths for each dimension.
6337      If successfull it will return a bit-or'd value in 'flags' indicating
6338      if the SDS is  chunked(HDF_CHUNK), chunked and compressed(HDF_CHUNK | HDF_COMP)
6339      or non-chunked(HDF_NONE).
6340 
6341      e.g. 4x4 array - Pseudo-C
6342      {
6343      HDF_CHUNK_DEF rchunk_def;
6344      int32   cflags;
6345      ...
6346      SDgetchunkinfo(sdsid, &rchunk_def, &cflags);
6347      ...
6348      }
6349 
6350  RETURNS
6351         SUCCEED/FAIL
6352 
6353  AUTHOR
6354         -GeorgeV
6355 
6356  MODIFICATION
6357     Jun, 2009: Added compression type and compression parameters.- BMR
6358 
6359 ******************************************************************************/
6360 intn
SDgetchunkinfo(int32 sdsid,HDF_CHUNK_DEF * chunk_def,int32 * flags)6361 SDgetchunkinfo(int32          sdsid,      /* IN: sds access id */
6362                HDF_CHUNK_DEF *chunk_def,  /* IN/OUT: chunk definition */
6363                int32         *flags       /* IN/OUT: flags */)
6364 {
6365     CONSTR(FUNC, "SDgetchunkinfo");    /* for HGOTO_ERROR */
6366     NC       *handle = NULL;       /* file handle */
6367     NC_var   *var    = NULL;       /* SDS variable */
6368     sp_info_block_t info_block;    /* special info block */
6369     comp_coder_t comp_type;
6370     comp_info c_info;
6371     int16     special;             /* Special code */
6372     intn      i;                   /* loop variable */
6373     intn      ret_value = SUCCEED; /* return value */
6374 
6375     /* Clear error stack */
6376     HEclear();
6377 
6378     /* Check args */
6379 
6380     /* Get file handle and verify it is an HDF file
6381        we only handle dealing with SDS only not coordinate variables */
6382     handle = SDIhandle_from_id(sdsid, SDSTYPE);
6383     if(handle == NULL || handle->file_type != HDF_FILE || handle->vars == NULL)
6384       {
6385         HGOTO_ERROR(DFE_ARGS, FAIL);
6386       }
6387 
6388     /* Get variable from id */
6389     var = SDIget_var(handle, sdsid);
6390     if(var == NULL)
6391     HGOTO_ERROR(DFE_ARGS, FAIL);
6392 
6393     /* If SDsetchunk had been called for this SDS, data_ref would have been a
6394        valid one.  This is the case where data set is empty and not special */
6395     if(var->data_ref == 0)
6396       {
6397     *flags = HDF_NONE; /* regular SDS */
6398         HGOTO_DONE(SUCCEED);
6399       }
6400 
6401 #ifdef added_by_mistake
6402     /* Replaced this if statement by if (var->aid == FAIL) because it seemed
6403        that hdf_get_vp_aid was called here by mistake (perhaps, copy/paste.)
6404        For more info, see SVN log messages and bug HDFFR-171. -BMR, 2011/10 */
6405 
6406     /* Check if data aid exists; if not, set up an access elt for reading */
6407     if(var->aid == FAIL && hdf_get_vp_aid(handle, var) == FAIL)
6408       {
6409         HGOTO_ERROR(DFE_ARGS, FAIL);
6410       }
6411 #endif
6412 
6413     /* Need to get access id for the subsequent calls */
6414     if (var->aid == FAIL)
6415     {
6416     var->aid = Hstartread(handle->hdf_file, var->data_tag, var->data_ref);
6417     if(var->aid == FAIL) /* catch FAIL from Hstartread */
6418         HGOTO_ERROR(DFE_INTERNAL, FAIL);
6419     }
6420 
6421     /* Inquire about element's specialness */
6422     ret_value = Hinquire(var->aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6423     if (ret_value == FAIL)
6424     HGOTO_ERROR(DFE_INTERNAL, FAIL);
6425 
6426     /* Make sure it is chunked element */
6427     if (special == SPECIAL_CHUNKED)
6428     {   /* Get info about chunked element */
6429     if ((ret_value = HDget_special_info(var->aid, &info_block)) != FAIL)
6430     {   /* Does user want chunk/comp info back? */
6431         /* If no compression, fill in chunk length, otherwise, fill
6432         in chunk length and compression info. */
6433         switch(info_block.comp_type) {
6434         case COMP_CODE_NONE:
6435         *flags = HDF_CHUNK;
6436 
6437                   /* if chunk info is requested */
6438         if (chunk_def != NULL)
6439         {
6440             /* copy chunk lengths over */
6441                       for (i = 0; i < info_block.ndims; i++)
6442                            chunk_def->chunk_lengths[i] = info_block.cdims[i];
6443         }
6444                   break;
6445 
6446         case COMP_CODE_NBIT:
6447                   *flags = (HDF_CHUNK | HDF_NBIT);
6448 
6449                   /* if chunk info is requested */
6450         if (chunk_def != NULL)
6451         {
6452             /* copy chunk lengths over */
6453                       for (i = 0; i < info_block.ndims; i++)
6454                           chunk_def->nbit.chunk_lengths[i] = info_block.cdims[i];
6455             /* get the NBIT compression info */
6456             ret_value = HCPgetcompinfo(handle->hdf_file,
6457                     var->data_tag, var->data_ref,
6458                     &comp_type, &c_info);
6459             /* For backward compatibility, it will not fail here.
6460             However, the compression information parameters will
6461             be set to -1 to indicate that there are no compression
6462             information retrieved - BMR - 2009/06 */
6463             if (ret_value == FAIL)
6464             {
6465             chunk_def->nbit.start_bit =
6466             chunk_def->nbit.bit_len =
6467             chunk_def->nbit.sign_ext =
6468             chunk_def->nbit.fill_one = -1;
6469             }
6470             else
6471             {
6472             chunk_def->nbit.start_bit = c_info.nbit.start_bit;
6473             chunk_def->nbit.bit_len = c_info.nbit.bit_len;
6474             chunk_def->nbit.sign_ext = c_info.nbit.sign_ext;
6475             chunk_def->nbit.fill_one = c_info.nbit.fill_one;
6476             }
6477         }
6478                   break;
6479 
6480         default:
6481                   *flags = (HDF_CHUNK | HDF_COMP);
6482 
6483                   /* if chunk info is requested */
6484         if (chunk_def != NULL)
6485         {
6486             /* copy chunk lengths over */
6487                       for (i = 0; i < info_block.ndims; i++)
6488                       {
6489                           chunk_def->comp.chunk_lengths[i] = info_block.cdims[i];
6490                       }
6491 
6492             /* get the compression info */
6493             ret_value = HCPgetcompinfo(handle->hdf_file,
6494                     var->data_tag, var->data_ref,
6495                     &comp_type, &c_info);
6496 
6497             /* For backward compatibility, it will not fail here.
6498             However, the compression information parameters will
6499             be set to -1 to indicate that there are no compression
6500             information retrieved - EIP/BMR - 2010/02 */
6501             if (ret_value == FAIL)
6502             {
6503             chunk_def->comp.comp_type = info_block.comp_type;
6504             switch (info_block.comp_type)
6505             {
6506                 case COMP_CODE_NBIT:
6507                 chunk_def->comp.cinfo.nbit.nt =
6508                 chunk_def->comp.cinfo.nbit.sign_ext =
6509                 chunk_def->comp.cinfo.nbit.fill_one =
6510                 chunk_def->comp.cinfo.nbit.start_bit =
6511                 chunk_def->comp.cinfo.nbit.bit_len = -1;
6512                 break;
6513 
6514                 case COMP_CODE_SKPHUFF:
6515                 chunk_def->comp.cinfo.skphuff.skp_size = -1;
6516                 break;
6517 
6518                 case COMP_CODE_DEFLATE:
6519                 chunk_def->comp.cinfo.deflate.level = -1;
6520                 break;
6521 
6522                 case COMP_CODE_SZIP:
6523                 chunk_def->comp.cinfo.szip.pixels =
6524                 chunk_def->comp.cinfo.szip.pixels_per_scanline =
6525                 chunk_def->comp.cinfo.szip.options_mask =
6526                 chunk_def->comp.cinfo.szip.bits_per_pixel =
6527                 chunk_def->comp.cinfo.szip.pixels_per_block = -1;
6528                 break;
6529 
6530         /* What about JPEG? - BMR */
6531                 default:  /* no additional info needed */
6532                 break;
6533             }  /* end switch */
6534             }
6535             else
6536             {
6537             HDmemcpy(&(chunk_def->comp.cinfo), &c_info, sizeof(comp_info));
6538             chunk_def->comp.comp_type = (int32)comp_type;
6539             }
6540         }  /* chunk_def != NULL */
6541                   break; /* default */
6542                 } /* end of switch info_block.comp_type */
6543             /* Free up info in special info block, allocated by the library */
6544             HDfree(info_block.cdims);
6545     }
6546     }
6547     else /* not special chunked element */
6548     {
6549         *flags = HDF_NONE; /* regular SDS */
6550     }
6551 
6552   done:
6553     if (ret_value == FAIL)
6554       { /* Failure cleanup */
6555       }
6556     /* Normal cleanup */
6557     return ret_value;
6558 } /* SDgetchunkinfo() */
6559 
6560 
6561 /******************************************************************************
6562  NAME
6563      SDwritechunk   -- write the specified chunk to the SDS
6564 
6565  DESCRIPTION
6566      This routine writes a whole chunk of data to the chunked SDS
6567      specified by chunk 'origin' for the given SDS and can be used
6568      instead of SDwritedata() when this information is known. This
6569      routine has less overhead and is much faster than using SDwritedata().
6570 
6571      Origin specifies the co-ordinates of the chunk according to the chunk
6572      position in the overall chunk array.
6573 
6574      'datap' must point to a whole chunk of data.
6575 
6576      See SDsetchunk() for a description of the organization of chunks in an SDS.
6577 
6578      NOTE:
6579            This routine directly calls a Special Chunked Element fcn HMCxxx.
6580 
6581  RETURNS
6582         SUCCEED/FAIL
6583 
6584  AUTHOR
6585        -GeorgeV
6586 ******************************************************************************/
6587 intn
SDwritechunk(int32 sdsid,int32 * origin,const void * datap)6588 SDwritechunk(int32       sdsid, /* IN: access aid to SDS */
6589              int32      *origin,/* IN: origin of chunk to write */
6590              const void *datap  /* IN: buffer for data */)
6591 {
6592     CONSTR(FUNC, "SDwritechunk");    /* for HGOTO_ERROR */
6593     NC        *handle = NULL;   /* file handle */
6594     NC_var    *var    = NULL;   /* SDS variable */
6595     int16      special;         /* Special code */
6596     int32      csize;           /* phsical chunk size */
6597     uint32     byte_count;      /* bytes to write */
6598     int8       platntsubclass;  /* the machine type of the current platform */
6599     int8       outntsubclass;   /* the data's machine type */
6600     uintn      convert;         /* whether to convert or not */
6601     comp_coder_t comp_type;
6602     uint32  comp_config;
6603     int32 status;
6604     intn       i;
6605     sp_info_block_t info_block; /* special info block */
6606     uint32 tBuf_size = 0;    /* conversion buffer size */
6607     void  *tBuf = NULL;        /* buffer used for conversion */
6608     intn       ret_value = SUCCEED;
6609 
6610     /* clear error stack */
6611     HEclear();
6612 
6613     info_block.cdims = NULL;
6614 
6615     /* Check args */
6616     if (origin == NULL || datap == NULL)
6617         HGOTO_ERROR(DFE_ARGS, FAIL);
6618 
6619     /* get file handle and verify it is an HDF file
6620        we only handle writinng to SDS only not coordinate variables */
6621     handle = SDIhandle_from_id(sdsid, SDSTYPE);
6622     if(handle == NULL || handle->file_type != HDF_FILE || handle->vars == NULL)
6623       {
6624         HGOTO_ERROR(DFE_ARGS, FAIL);
6625       }
6626 
6627 
6628     /* get variable from id */
6629     var = SDIget_var(handle, sdsid);
6630     if(var == NULL)
6631       {
6632         HGOTO_ERROR(DFE_ARGS, FAIL);
6633       }
6634 
6635     /* Check to see if data aid exists? i.e. may need to create a ref for SDS */
6636     if(var->aid == FAIL && hdf_get_vp_aid(handle, var) == FAIL)
6637       {
6638         HGOTO_ERROR(DFE_ARGS, FAIL);
6639       }
6640 
6641     /* Check compression method is enabled */
6642     status = HCPgetcomptype(handle->hdf_file, var->data_tag, var->data_ref,
6643                 &comp_type);
6644 
6645     if (status != FAIL)
6646     if (comp_type != COMP_CODE_NONE && comp_type != COMP_CODE_INVALID)
6647       {
6648     /* Must have encoder to write */
6649         HCget_config_info( comp_type , &comp_config);
6650         if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
6651         /* encoder not present?? */
6652         HGOTO_ERROR(DFE_BADCODER, FAIL);
6653           }
6654       }
6655 
6656     /* inquire about element */
6657     ret_value = Hinquire(var->aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6658     if (ret_value != FAIL)
6659       {
6660           if (special == SPECIAL_CHUNKED)
6661             {  /* yes */
6662 
6663                 /* get ready to write */
6664                 handle->xdrs->x_op = XDR_ENCODE;
6665 
6666                 /* get info about chunked element */
6667                 if ((ret_value = HDget_special_info(var->aid, &info_block)) != FAIL)
6668                   {
6669                       /* calcualte chunk size  */
6670                       csize = 1;
6671                       for (i = 0; i < info_block.ndims; i++)
6672                           csize *= info_block.cdims[i];
6673 
6674                       /* adjust for number type size */
6675                       csize *= var->HDFsize;
6676 
6677                       /* figure out if data needs to be converted */
6678                       byte_count = csize;
6679 
6680                       if (FAIL == (platntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6681                         {
6682                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
6683                         }
6684 
6685                       if (DFKisnativeNT(var->HDFtype))
6686                         {
6687                             if (FAIL == (outntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6688                               {
6689                                   ret_value = FAIL;
6690                                   HGOTO_ERROR(DFE_INTERNAL, FAIL);
6691                               }
6692                         }
6693                       else
6694                         {
6695                             outntsubclass = DFKislitendNT(var->HDFtype) ? DFNTF_PC : DFNTF_HDFDEFAULT;
6696                         }
6697 
6698                       convert = (uintn)(platntsubclass != outntsubclass);
6699 
6700                       /* make sure our tmp buffer is big enough to hold everything */
6701                       if(convert && tBuf_size < byte_count)
6702                         {
6703                             if(tBuf != NULL)
6704                                 HDfree(tBuf);
6705                             tBuf_size = byte_count;
6706                             tBuf      = HDmalloc(tBuf_size);
6707                             if(tBuf == NULL)
6708                               {
6709                                   tBuf_size = 0;
6710                                   ret_value    = FAIL;
6711                                   HGOTO_ERROR(DFE_NOSPACE, FAIL);
6712                               } /* end if */
6713                         } /* end if */
6714 
6715                       /* Write chunk out, */
6716                       if(convert)
6717                         {
6718 #ifdef CHK_DEBUG
6719         fprintf(stderr,"SDwritechunk: convert, var->HDFsize=%d, var->HDFtype=%d \n",
6720                 var->HDFsize, var->HDFtype);
6721 #endif
6722                             /* convert it */
6723                             if (FAIL == DFKconvert((VOIDP)datap, tBuf, var->HDFtype,
6724                                                   (byte_count/var->HDFsize), DFACC_WRITE, 0, 0))
6725                               {
6726                                   HGOTO_ERROR(DFE_INTERNAL, FAIL);
6727                               }
6728 
6729                             /* write it out now */
6730                             if ((ret_value = HMCwriteChunk(var->aid, origin, tBuf)) != FAIL)
6731                               {
6732                                   HGOTO_DONE(SUCCEED);
6733                               }
6734 /* need to make sure correctness - remove when done */
6735                           else
6736                               HGOTO_ERROR(DFE_WRITEERROR, FAIL);
6737                         } /* end if */
6738                       else
6739                         {
6740                           if ((ret_value = HMCwriteChunk(var->aid, origin, datap)) != FAIL)
6741                             {
6742                               HGOTO_DONE(SUCCEED);
6743                             }
6744 /* need to make sure correctness - remove when done */
6745                           else
6746                               HGOTO_ERROR(DFE_WRITEERROR, FAIL);
6747                         }
6748                   } /* end if get special info block */
6749             }
6750           else /* not special CHUNKED */
6751               ret_value = FAIL;
6752       } /* end if Hinquire */
6753 
6754   done:
6755     if (ret_value == FAIL)
6756       { /* Failure cleanup */
6757 
6758       }
6759     /* Normal cleanup */
6760     /* dont forget to free up info is special info block
6761        This space was allocated by the library */
6762     if (info_block.cdims != NULL)
6763         HDfree(info_block.cdims);
6764 
6765     if (tBuf != NULL)
6766         HDfree(tBuf);
6767 
6768     return ret_value;
6769 } /* SDwritechunk() */
6770 
6771 /******************************************************************************
6772  NAME
6773      SDreadchunk   -- read the specified chunk to the SDS
6774 
6775  DESCRIPTION
6776      This routine reads a whole chunk of data from the chunked SDS
6777      specified by chunk 'origin' for the given SDS and can be used
6778      instead of SDreaddata() when this information is known. This
6779      routine has less overhead and is much faster than using SDreaddata().
6780 
6781      Origin specifies the co-ordinates of the chunk according to the chunk
6782      position in the overall chunk array.
6783 
6784      'datap' must point to a whole chunk of data.
6785 
6786      See SDsetchunk() for a description of the organization of chunks in an SDS.
6787 
6788      NOTE:
6789          This routine directly calls a Special Chunked Element fcn HMCxxx.
6790 
6791  RETURNS
6792         SUCCEED/FAIL
6793 
6794  AUTHOR
6795        -GeorgeV
6796 ******************************************************************************/
6797 intn
SDreadchunk(int32 sdsid,int32 * origin,void * datap)6798 SDreadchunk(int32  sdsid,  /* IN: access aid to SDS */
6799             int32 *origin, /* IN: origin of chunk to write */
6800             void  *datap   /* IN/OUT: buffer for data */)
6801 {
6802     CONSTR(FUNC, "SDreadchunk");    /* for HGOTO_ERROR */
6803     NC        *handle = NULL;   /* file handle */
6804     NC_var    *var    = NULL;   /* SDS variable */
6805     int16      special;         /* Special code */
6806     int32      csize;           /* phsical chunk size */
6807     uint32     byte_count;      /* bytes to read */
6808     int8       platntsubclass;  /* the machine type of the current platform */
6809     int8       outntsubclass;   /* the data's machine type */
6810     uintn      convert;         /* whether to convert or not */
6811     comp_coder_t comp_type;
6812     uint32  comp_config;
6813     int32 status;
6814     intn       i;
6815     sp_info_block_t info_block; /* special info block */
6816     uint32 tBuf_size = 0; /* conversion buffer size */
6817     void  *tBuf = NULL; /* buffer used for conversion */
6818     intn       ret_value = SUCCEED;
6819 
6820     /* clear error stack */
6821     HEclear();
6822 
6823     info_block.cdims = NULL;
6824 
6825     /* Check args */
6826     if (origin == NULL || datap == NULL)
6827         HGOTO_ERROR(DFE_ARGS, FAIL);
6828 
6829     /* get file handle and verify it is an HDF file
6830        we only handle reading from SDS only not coordinate variables */
6831     handle = SDIhandle_from_id(sdsid, SDSTYPE);
6832     if(handle == NULL || handle->file_type != HDF_FILE || handle->vars == NULL)
6833       {
6834         HGOTO_ERROR(DFE_ARGS, FAIL);
6835       }
6836 
6837     /* get variable from id */
6838     var = SDIget_var(handle, sdsid);
6839     if(var == NULL)
6840       {
6841         HGOTO_ERROR(DFE_ARGS, FAIL);
6842       }
6843 
6844     /* Dev note: empty SDS should have been checked here and SDreadchunk would
6845        have failed, but since it wasn't, for backward compatibility, we won't
6846        do it now either. -BMR 2011 */
6847 
6848 #ifdef added_by_mistake
6849     /* Replaced this if statement by if (var->aid == FAIL) because it seemed
6850        that hdf_get_vp_aid was called here by mistake (perhaps, copy/paste.)
6851        For more info, see SVN log messages and bug HDFFR-171. -BMR, 2011/10 */
6852 
6853     /* Check to see if data aid exists? i.e. may need to create a ref for SDS */
6854     if(var->aid == FAIL && hdf_get_vp_aid(handle, var) == FAIL)
6855       {
6856         HGOTO_ERROR(DFE_ARGS, FAIL);
6857       }
6858 #endif
6859 
6860     /* Check compression method is enabled */
6861     status = HCPgetcomptype(handle->hdf_file, var->data_tag, var->data_ref,
6862                 &comp_type);
6863 
6864     if (status != FAIL)
6865     if (comp_type != COMP_CODE_NONE && comp_type != COMP_CODE_INVALID)
6866       {
6867     /* Must have decoder to read data */
6868         HCget_config_info( comp_type , &comp_config);
6869         if ((comp_config & COMP_DECODER_ENABLED) == 0) {
6870         /* decoder not present?? */
6871         HGOTO_ERROR(DFE_BADCODER, FAIL);
6872           }
6873       }
6874 
6875     /* Need to get access id for the following calls */
6876     if (var->aid == FAIL)
6877     {
6878     var->aid = Hstartread(handle->hdf_file, var->data_tag, var->data_ref);
6879         if(var->aid == FAIL) /* catch FAIL from Hstartread */
6880             HGOTO_ERROR(DFE_CANTACCESS, FAIL);
6881     }
6882 
6883     /* inquire about element */
6884     ret_value = Hinquire(var->aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6885     if (ret_value != FAIL)
6886       {
6887           if (special == SPECIAL_CHUNKED)
6888             {  /* yes */
6889                 /* get ready to read */
6890                 handle->xdrs->x_op = XDR_DECODE;
6891 
6892                 /* get info about chunked element */
6893                 if ((ret_value = HDget_special_info(var->aid, &info_block)) != FAIL)
6894                   {
6895                       /* calcualte chunk size  */
6896                       csize = 1;
6897                       for (i = 0; i < info_block.ndims; i++)
6898                           csize *= info_block.cdims[i];
6899 
6900                       /* adjust for number type size */
6901                       csize *= var->HDFsize;
6902 
6903                       /* figure out if data needs to be converted */
6904                       byte_count = csize;
6905 
6906                       if (FAIL == (platntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6907                         {
6908                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
6909                         }
6910 
6911                       if (DFKisnativeNT(var->HDFtype))
6912                         {
6913                             if (FAIL == (outntsubclass = DFKgetPNSC(var->HDFtype, DF_MT)))
6914                               {
6915                                   HGOTO_ERROR(DFE_INTERNAL, FAIL);
6916                               }
6917                         }
6918                       else
6919                         {
6920                             outntsubclass = DFKislitendNT(var->HDFtype) ? DFNTF_PC : DFNTF_HDFDEFAULT;
6921                         }
6922 
6923                       convert = (uintn)(platntsubclass != outntsubclass);
6924 
6925                       /* make sure our tmp buffer is big enough to hold everything */
6926                       if(convert && tBuf_size < byte_count)
6927                         {
6928                             if(tBuf != NULL)
6929                                 HDfree(tBuf);
6930                             tBuf_size = byte_count;
6931                             tBuf      = HDmalloc(tBuf_size);
6932                             if(tBuf == NULL)
6933                               {
6934                                   tBuf_size = 0;
6935                                   HGOTO_ERROR(DFE_NOSPACE, FAIL);
6936                               } /* end if */
6937                         } /* end if */
6938 
6939                       /* read chunk in */
6940                       if(convert)
6941                         {
6942 #ifdef CHK_DEBUG
6943         fprintf(stderr,"SDreadchunk: convert, var->HDFsize=%d, var->HDFtype=%d \n",
6944                 var->HDFsize, var->HDFtype);
6945 #endif
6946                             /* read it in */
6947                             if ((ret_value = HMCreadChunk(var->aid, origin, tBuf))
6948                                 != FAIL)
6949                                 {
6950                                     /* convert chunk */
6951                                     if (FAIL == DFKconvert(tBuf, datap, var->HDFtype,
6952                                                          (byte_count/var->HDFsize), DFACC_READ, 0, 0))
6953                                       {
6954                                           HGOTO_ERROR(DFE_INTERNAL, FAIL);
6955                                       }
6956 
6957                                     ret_value = SUCCEED;
6958                                 }
6959                             else
6960                                 HGOTO_ERROR(DFE_READERROR, FAIL);
6961                         } /* end if */
6962                       else
6963                         {
6964                           if ((ret_value = HMCreadChunk(var->aid, origin, datap))
6965                               != FAIL)
6966                             {
6967                               ret_value = SUCCEED;
6968                             }
6969                           else
6970                               HGOTO_ERROR(DFE_READERROR, FAIL);
6971                         }
6972                   } /* end if get special info block */
6973             }
6974           else /* not special CHUNKED */
6975               ret_value = FAIL;
6976       } /* end if Hinquire */
6977 
6978     /* End access to the access id */
6979     if(Hendaccess(var->aid)==FAIL)
6980         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
6981     var->aid = FAIL;
6982 
6983   done:
6984     if (ret_value == FAIL)
6985       { /* Failure cleanup */
6986         /* End access to the aid if neccessary */
6987         if (var->aid != FAIL)
6988         {
6989             Hendaccess(var->aid);
6990             var->aid = FAIL;
6991         }
6992       }
6993     /* Normal cleanup */
6994     /* dont forget to free up info in special info block
6995        This space was allocated by the library */
6996     if (info_block.cdims != NULL)
6997         HDfree(info_block.cdims);
6998 
6999     if (tBuf != NULL)
7000         HDfree(tBuf);
7001 
7002     return ret_value;
7003 } /* SDreadchunk() */
7004 
7005 /******************************************************************************
7006 NAME
7007      SDsetchunkcache - maximum number of chunks to cache
7008 
7009 DESCRIPTION
7010      Set the maximum number of chunks to cache.
7011 
7012      The cache contains the Least Recently Used(LRU cache replacment policy)
7013      chunks. This routine allows the setting of maximum number of chunks that
7014      can be cached, 'maxcache'.
7015 
7016      The performance of the SDxxx interface with chunking is greatly
7017      affected by the users access pattern over the dataset and by
7018      the maximum number of chunks set in the chunk cache. The number chunks
7019      that can be set in the cache is process memory limited. It is a good
7020      idea to always set the maximum number of chunks in the cache as the
7021      default heuristic does not take into account the memory available for
7022      the application.
7023 
7024      By default when the SDS is promoted to a chunked element the
7025      maximum number of chunks in the cache 'maxcache' is set to the number of
7026      chunks along the last dimension.
7027 
7028      The values set here affects the current SDS object's caching behaviour.
7029 
7030      If the chunk cache is full and 'maxcache' is greater then the
7031      current 'maxcache' value, then the chunk cache is reset to the new
7032      'maxcache' value, else the chunk cache remains at the current
7033      'maxcache' value.
7034 
7035      If the chunk cache is not full, then the chunk cache is set to the
7036      new 'maxcache' value only if the new 'maxcache' value is greater than the
7037      current number of chunks in the cache.
7038 
7039      Use flags argument of 'HDF_CACHEALL' if the whole object is to be cached
7040      in memory, otherwise pass in zero(0). Currently you can only
7041      pass in zero.
7042 
7043      See SDsetchunk() for a description of the organization of chunks in an SDS.
7044 
7045      NOTE:
7046           This routine directly calls a Special Chunked Element fcn HMCxxx.
7047 
7048 RETURNS
7049      Returns the 'maxcache' value for the chunk cache if successful
7050      and FAIL otherwise
7051 
7052 AUTHOR
7053       -GeorgeV
7054 ******************************************************************************/
7055 intn
SDsetchunkcache(int32 sdsid,int32 maxcache,int32 flags)7056 SDsetchunkcache(int32 sdsid,     /* IN: access aid to mess with */
7057                 int32 maxcache,  /* IN: max number of chunks to cache */
7058                 int32 flags      /* IN: flags = 0, HDF_CACHEALL */)
7059 {
7060     CONSTR(FUNC, "SDsetchunkcache");    /* for HGOTO_ERROR */
7061     NC       *handle = NULL;        /* file handle */
7062     NC_var   *var    = NULL;        /* SDS variable */
7063     int16     special;              /* Special code */
7064     intn      ret_value = SUCCEED;
7065 
7066     /* clear error stack */
7067     HEclear();
7068 
7069     /* Check args */
7070     if (maxcache < 1 )
7071       {
7072         HGOTO_ERROR(DFE_ARGS, FAIL);
7073       }
7074 
7075     if (flags != 0 && flags != HDF_CACHEALL)
7076       {
7077         HGOTO_ERROR(DFE_ARGS, FAIL);
7078       }
7079 
7080     /* get file handle and verify it is an HDF file
7081        we only handle dealing with SDS only not coordinate variables */
7082     handle = SDIhandle_from_id(sdsid, SDSTYPE);
7083     if(handle == NULL || handle->file_type != HDF_FILE || handle->vars == NULL)
7084       {
7085         HGOTO_ERROR(DFE_ARGS, FAIL);
7086       }
7087 
7088     /* get variable from id */
7089     var = SDIget_var(handle, sdsid);
7090     if(var == NULL)
7091       {
7092         HGOTO_ERROR(DFE_ARGS, FAIL);
7093       }
7094 
7095     /* Check to see if data aid exists? i.e. may need to create a ref for SDS */
7096     if(var->aid == FAIL && hdf_get_vp_aid(handle, var) == FAIL)
7097       {
7098         HGOTO_ERROR(DFE_ARGS, FAIL);
7099       }
7100 
7101     /* inquire about element */
7102     ret_value = Hinquire(var->aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
7103     if (ret_value != FAIL)
7104       {
7105           if (special == SPECIAL_CHUNKED)
7106               ret_value = HMCsetMaxcache(var->aid, maxcache, flags); /* set cache*/
7107           else
7108               ret_value = FAIL;
7109       }
7110 
7111   done:
7112     if (ret_value == FAIL)
7113       { /* Failure cleanup */
7114 
7115       }
7116     /* Normal cleanup */
7117 
7118     return ret_value;
7119 } /* SDsetchunkcache() */
7120 
7121 
7122 /******************************************************************************
7123  NAME
7124     SDcheckempty -- checks whether an SDS is empty
7125 
7126  DESCRIPTION
7127     Given an sdsid, set the second parameter, emptySDS, to TRUE if the
7128     SDS has not been written with data, and FALSE, otherwise.
7129 
7130  RETURNS
7131     SUCCEED/FAIL
7132 
7133  PROGRAMMER
7134     bmribler - 9-01-98
7135 
7136  MODIFICATION
7137     bmribler - 9/29/2004
7138         When the SDS is not a special element, we only need to check
7139         its data ref# to decide whether it has data written, but
7140         when the SDS is a special element, it still has a valid
7141         data ref# even though it doesn't have data, we'll then need
7142         to perform a more detailed check.  Added more detailed checks.
7143 
7144 ******************************************************************************/
7145 int32
SDcheckempty(int32 sdsid,intn * emptySDS)7146 SDcheckempty(int32 sdsid,  /* IN: dataset ID */
7147         intn  *emptySDS /* TRUE if SDS is empty */)
7148 {
7149     CONSTR(FUNC, "SDcheckempty");    /* for HGOTO_ERROR */
7150     NC     *handle = NULL;        /* file record struct */
7151     NC_var *var = NULL;            /* variable record struct */
7152     int32   ret_value = SUCCEED;
7153 
7154 #ifdef SDDEBUG
7155     fprintf(stderr, "SDcheckempty: I've been called\n");
7156 #endif
7157 
7158     /* clear error stack */
7159     HEclear();
7160 
7161     /* get the handle */
7162     handle = SDIhandle_from_id(sdsid, SDSTYPE);
7163     if(handle == NULL)
7164       {
7165         HGOTO_ERROR(DFE_ARGS, FAIL);
7166       }
7167 
7168     /* get the variable */
7169     var = SDIget_var(handle, sdsid);
7170     if(var == NULL)
7171       {
7172         HGOTO_ERROR(DFE_ARGS, FAIL);
7173       }
7174 
7175     /* assume that the SDS is not empty until proving otherwise */
7176     *emptySDS = FALSE;
7177 
7178     /* if the data ref# of the SDS is 0, it indicates that the SDS has
7179     not been written with data because no storage is created
7180     for the SDS data */
7181     if (var->data_ref == 0)
7182     {
7183         *emptySDS = TRUE;
7184     }
7185     else
7186     { /* data_ref is not 0, so must check on special SDSs to determine if
7187     the SDS is empty */
7188     /* check for unlimited dimension, assuming that unlimited dimension is
7189     still not allowed with other specialness, according to GeorgeV */
7190     if (var->shape != NULL && var->shape[0] == NC_UNLIMITED)
7191     {
7192         /* if data has been written, var->numrecs will show the size
7193         of the unlimited dimension */
7194         if(var->numrecs <= 0)
7195         *emptySDS = TRUE;
7196     }
7197     /* handle other specialness via lower level functions */
7198     else
7199     {
7200         ret_value = HDcheck_empty(handle->hdf_file, var->data_tag,
7201                     var->data_ref, emptySDS);
7202         if (ret_value == FAIL) HGOTO_ERROR(DFE_INTERNAL, FAIL);
7203     }
7204     } /* var->data_ref != 0 */
7205 
7206 done:
7207     if (ret_value == FAIL)
7208       { /* Failure cleanup */
7209 
7210       }
7211     /* Normal cleanup */
7212     return ret_value;
7213 } /* SDcheckempty */
7214 
7215 /******************************************************************************
7216  NAME
7217     SDidtype -- returns the type of an id
7218 
7219  DESCRIPTION
7220     Given an id, return its type, which is either an SD id, an SDS id, or
7221     a dimension id, or indicate that it is not a valid SD API id.
7222 
7223  RETURNS
7224     A value of type hdf_idtype_t, which can be either of the following:
7225     SD_ID, SDS_ID, DIM_ID, NOT_SDAPI_ID.
7226 
7227  PROGRAMMER
7228     bmribler - 1-19-2005
7229 
7230  MODIFICATION
7231 
7232 ******************************************************************************/
7233 hdf_idtype_t
SDidtype(int32 an_id)7234 SDidtype(int32 an_id)
7235 {
7236     CONSTR(FUNC, "SDidtype");    /* for HGOTO_ERROR */
7237     NC     *handle = NULL;    /* file record struct */
7238     hdf_idtype_t ret_value = NOT_SDAPI_ID;
7239 
7240 #ifdef SDDEBUG
7241     fprintf(stderr, "SDidtype: I've been called\n");
7242 #endif
7243 
7244     /* clear error stack */
7245     HEclear();
7246 
7247     /* Assuming that the id is an SD id, get and check the handle */
7248     handle = SDIhandle_from_id(an_id, CDFTYPE);
7249 
7250     /* If it is, indicate so */
7251     if(handle != NULL)
7252     ret_value = SD_ID;
7253 
7254     /* otherwise, check further... */
7255     else
7256     {
7257     /* Assuming that it is an SDS id, get and check the handle */
7258     handle = SDIhandle_from_id(an_id, SDSTYPE);
7259 
7260     /* If it is, indicate so */
7261     if(handle != NULL)
7262             ret_value = SDS_ID;
7263 
7264     /* otherwise, check if it is a dimension id, or just not valid */
7265     else
7266     {
7267             handle = SDIhandle_from_id(an_id, DIMTYPE);
7268             if(handle != NULL)
7269         ret_value = DIM_ID;
7270         else
7271         ret_value = NOT_SDAPI_ID;
7272         }
7273     }
7274     return ret_value;
7275 } /* SDidtype */
7276 
7277 /******************************************************************************
7278  NAME
7279     SDreset_maxopenfiles -- resets the maximum number of files can be
7280                 opened at a time.
7281 
7282  DESCRIPTION
7283     Uses NC local function NC_reset_maxopenfiles to change the maximum
7284     number of opened files allowed.  This involves re-allocating of the
7285     internal cdf list.
7286 
7287  RETURNS
7288     The current maximum number of opened files allowed, or FAIL, if
7289     unable to reset it.
7290 
7291  PROGRAMMER
7292     bmribler - 9-06-2005
7293 
7294  MODIFICATION
7295 
7296 ******************************************************************************/
7297 intn
SDreset_maxopenfiles(intn req_max)7298 SDreset_maxopenfiles(intn req_max)
7299 {
7300     CONSTR(FUNC, "SDreset_maxopenfiles");    /* for HGOTO_ERROR */
7301     intn ret_value = SUCCEED;
7302 
7303 #ifdef SDDEBUG
7304     fprintf(stderr, "SDreset_maxopenfiles: I've been called\n");
7305 #endif
7306 
7307     /* clear error stack */
7308     HEclear();
7309 
7310     /* Reset the max NC open and re-allocate cdf list appropriately */
7311     ret_value = NC_reset_maxopenfiles(req_max);
7312 
7313     if (ret_value == -1)
7314     HGOTO_ERROR(DFE_INTERNAL, FAIL);  /* should propagate error code */
7315 
7316 done:
7317     if (ret_value == FAIL)
7318       { /* Failure cleanup */
7319 
7320       }
7321     /* Normal cleanup */
7322     return ret_value;
7323 } /* SDreset_maxopenfiles */
7324 
7325 /******************************************************************************
7326  NAME
7327     SDget_maxopenfiles -- retrieves the current number of opened files
7328                 allowed in HDF and the maximum number of opened
7329                 files allowed on a system.
7330 
7331  DESCRIPTION
7332     Uses NC_get_maxopenfiles.
7333 
7334  RETURNS
7335     SUCCEED/FAIL
7336 
7337  PROGRAMMER
7338     bmribler - 9-06-2005
7339 
7340  MODIFICATION
7341 
7342 ******************************************************************************/
7343 intn
SDget_maxopenfiles(intn * curr_max,intn * sys_limit)7344 SDget_maxopenfiles(intn *curr_max,  /* OUT: current # of open files allowed */
7345         intn *sys_limit) /* OUT: max # of open files allowed on
7346                     a system */
7347 {
7348     CONSTR(FUNC, "SDget_maxopenfiles");    /* for HGOTO_ERROR */
7349     intn ret_value = SUCCEED;
7350 
7351 #ifdef SDDEBUG
7352     fprintf(stderr, "SDget_maxopenfiles: I've been called\n");
7353 #endif
7354 
7355     /* clear error stack */
7356     HEclear();
7357 
7358     /* Retrieve the current max and the system limit */
7359     if (curr_max != NULL)
7360     {
7361     *curr_max = NC_get_maxopenfiles();
7362     if (*curr_max == FAIL)
7363         HGOTO_ERROR(DFE_INTERNAL, FAIL);
7364     }
7365     if (sys_limit != NULL)
7366     {
7367     *sys_limit = NC_get_systemlimit();
7368     if (*sys_limit == FAIL)
7369         HGOTO_ERROR(DFE_INTERNAL, FAIL);
7370     }
7371 
7372 done:
7373     if (ret_value == FAIL)
7374       { /* Failure cleanup */
7375 
7376       }
7377     /* Normal cleanup */
7378     return ret_value;
7379 } /* SDget_maxopenfiles */
7380 
7381 /******************************************************************************
7382  NAME
7383     SDget_numopenfiles -- returns the number of files currently being
7384                 opened.
7385 
7386  DESCRIPTION
7387     Uses NC_get_numopencdfs.
7388 
7389  RETURNS
7390     The number of files currently being opened or FAIL.
7391 
7392  PROGRAMMER
7393     bmribler - 9-06-2005
7394 
7395  MODIFICATION
7396 
7397 ******************************************************************************/
7398 intn
SDget_numopenfiles()7399 SDget_numopenfiles()
7400 {
7401     CONSTR(FUNC, "SDget_numopenfiles");    /* for HGOTO_ERROR */
7402     intn ret_value = SUCCEED;
7403 
7404 #ifdef SDDEBUG
7405     fprintf(stderr, "SDget_numopenfiles: I've been called\n");
7406 #endif
7407 
7408     /* clear error stack */
7409     HEclear();
7410 
7411     ret_value = (intn)NC_get_numopencdfs();
7412     return ret_value;
7413 } /* SDget_numopenfiles */
7414 
7415 /******************************************************************************
7416  NAME
7417     SDgetfilename -- retrieves the name of the file given its ID.
7418 
7419  DESCRIPTION
7420     Given an ID to a file, returns its name via parameter 'filename.'
7421     The user is repsonsible for allocating sufficient space to hold
7422     the file name.  It can be at most H4_MAX_NC_NAME characters in
7423     length.
7424 
7425  RETURNS
7426     Length of the file name, without '\0', on success, and FAIL, otherwise.
7427 
7428  PROGRAMMER
7429     bmribler - 9-06-2005
7430 
7431  MODIFICATION
7432 
7433 ******************************************************************************/
7434 intn
SDgetfilename(int32 fid,char * filename)7435 SDgetfilename(int32 fid,       /* IN:  file ID */
7436               char  *filename  /* OUT: name of the file */)
7437 {
7438     CONSTR(FUNC, "SDgetfilename");    /* for HGOTO_ERROR */
7439     NC     *handle = NULL;
7440     intn    len;
7441     intn    ret_value = SUCCEED;
7442 
7443 #ifdef SDDEBUG
7444     fprintf(stderr, "SDgetfilename: I've been called\n");
7445 #endif
7446 
7447     /* clear error stack */
7448     HEclear();
7449 
7450     /* check that fid is valid */
7451     handle = SDIhandle_from_id(fid, CDFTYPE);
7452     if(handle == NULL)
7453     HGOTO_ERROR(DFE_ARGS, FAIL);
7454 
7455     len = HDstrlen(handle->path);
7456     if(filename != NULL)
7457     {
7458         HDmemcpy(filename, handle->path, len);
7459         filename[len] = '\0';
7460     }
7461     ret_value = len;
7462 
7463 done:
7464     if (ret_value == FAIL)
7465       { /* Failure cleanup */
7466 
7467       }
7468     /* Normal cleanup */
7469 
7470     return ret_value;
7471 } /* SDgetfilename */
7472 
7473 /******************************************************************************
7474  NAME
7475     SDgetnamelen -- retrieves the length of the name of a file, a dataset,
7476             or a dimension.
7477 
7478 DESCRIPTION
7479     Given an id, retrieves the length of its name.
7480 
7481 RETURNS
7482    SUCCEED/FAIL
7483 
7484  PROGRAMMER
7485     bmribler - 9-14-2006
7486 
7487  MODIFICATION
7488 
7489 ******************************************************************************/
7490 intn
SDgetnamelen(int32 id,uint16 * name_len)7491 SDgetnamelen(int32 id,        /* IN:  object ID */
7492              uint16 *name_len    /* OUT: buffer for name's length */)
7493 {
7494     CONSTR(FUNC, "SDgetnamelen");    /* for HGOTO_ERROR */
7495     NC     *handle = NULL;
7496     NC_var *var = NULL;
7497     NC_dim *dim = NULL;
7498     intn   ret_value = SUCCEED;
7499 
7500 #ifdef SDDEBUG
7501     fprintf(stderr, "SDgetnamelen: I've been called\n");
7502 #endif
7503 
7504     /* clear error stack */
7505     HEclear();
7506 
7507     /* Assuming that the id is an SD id, get the file handle */
7508     handle = SDIhandle_from_id(id, CDFTYPE);
7509 
7510     /* If it is, obtain the file name's length */
7511     if(handle != NULL)
7512     *name_len = (uint16)HDstrlen(handle->path);
7513 
7514     /* otherwise, check further... */
7515     else
7516     {
7517     /* Assuming that it is an id of an SDS, get its file handle */
7518     handle = SDIhandle_from_id(id, SDSTYPE);
7519 
7520     /* If it is, get the NC_var record, and obtain the SDS name's length */
7521     if(handle != NULL)
7522     {
7523         var = SDIget_var(handle, id);
7524         if(var == NULL)
7525         HGOTO_ERROR(DFE_ARGS, FAIL);
7526         *name_len = (uint16)var->name->len;
7527     }
7528 
7529     /* otherwise, check if it is a dimension id, or just not valid */
7530     else
7531     {
7532             handle = SDIhandle_from_id(id, DIMTYPE);
7533             if(handle != NULL)
7534         {
7535         dim = SDIget_dim(handle, id);
7536         if(dim == NULL)
7537             HGOTO_ERROR(DFE_ARGS, FAIL);
7538         *name_len = (uint16)dim->name->len;
7539         }
7540         else    /* invalid id */
7541         HGOTO_ERROR(DFE_ARGS, FAIL);
7542         }
7543     }
7544 
7545 done:
7546     if (ret_value == FAIL)
7547       { /* Failure cleanup */
7548 
7549       }
7550     /* Normal cleanup */
7551 
7552     return ret_value;
7553 } /* SDgetnamelen */
7554 
7555 #endif /* HDF */
7556