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