bes  Updated for version 3.20.8
h5get.cc
Go to the documentation of this file.
1 // data server.
2 
3 // Copyright (c) 2007-2016 The HDF Group, Inc. and OPeNDAP, Inc.
4 //
5 // This is free software; you can redistribute it and/or modify it under the
6 // terms of the GNU Lesser General Public License as published by the Free
7 // Software Foundation; either version 2.1 of the License, or (at your
8 // option) any later version.
9 //
10 // This software is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 // License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //
19 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
20 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
21 // Suite 203, Champaign, IL 61820
22 
35 
36 #include "h5get.h"
37 #include "HDF5Int32.h"
38 #include "HDF5UInt32.h"
39 #include "HDF5UInt16.h"
40 #include "HDF5Int16.h"
41 #include "HDF5Byte.h"
42 #include "HDF5Int8.h"
43 #include "HDF5Int64.h"
44 #include "HDF5UInt64.h"
45 #include "HDF5Array.h"
46 #include "HDF5Str.h"
47 #include "HDF5Float32.h"
48 #include "HDF5Float64.h"
49 #include "HDF5Url.h"
50 #include "HDF5Structure.h"
51 #include "HDF5RequestHandler.h"
52 
53 #include <BESDebug.h>
54 #include <math.h>
55 #include <sstream>
56 
57 using namespace libdap;
58 
59 // H5Ovisit call back function. When finding the dimension scale attributes, return 1.
60 static int
61 visit_obj_cb(hid_t o_id, const char *name, const H5O_info_t *oinfo,
62  void *_op_data);
63 
64 // H5Aiterate2 call back function, check if having the dimension scale attributes.
65 static herr_t attr_info_dimscale(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *opdata);
66 
67 
84 hid_t get_attr_info(hid_t dset, int index, bool is_dap4, DSattr_t * attr_inst_ptr,
85  bool *ignore_attr_ptr)
86 {
87 
88  hid_t attrid = -1;
89 
90  // Always assume that we don't ignore any attributes.
91  *ignore_attr_ptr = false;
92 
93  if ((attrid = H5Aopen_by_idx(dset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,(hsize_t)index, H5P_DEFAULT, H5P_DEFAULT)) < 0) {
94  string msg = "unable to open attribute by index ";
95  throw InternalErr(__FILE__, __LINE__, msg);
96  }
97 
98  // Obtain the size of attribute name.
99  ssize_t name_size = H5Aget_name(attrid, 0, NULL);
100  if (name_size < 0) {
101  H5Aclose(attrid);
102  string msg = "unable to obtain the size of the hdf5 attribute name ";
103  throw InternalErr(__FILE__, __LINE__, msg);
104  }
105 
106  vector<char> attr_name;
107  attr_name.resize(name_size+1);
108  // Obtain the attribute name.
109  if ((H5Aget_name(attrid, name_size+1, &attr_name[0])) < 0) {
110  H5Aclose(attrid);
111  string msg = "unable to obtain the hdf5 attribute name ";
112  throw InternalErr(__FILE__, __LINE__, msg);
113  }
114 
115  // Obtain the type of the attribute.
116  hid_t ty_id = -1;
117  if ((ty_id = H5Aget_type(attrid)) < 0) {
118  string msg = "unable to obtain hdf5 datatype for the attribute ";
119  string attrnamestr(attr_name.begin(),attr_name.end());
120  msg += attrnamestr;
121  H5Aclose(attrid);
122  throw InternalErr(__FILE__, __LINE__, msg);
123  }
124 
125  H5T_class_t ty_class = H5Tget_class(ty_id);
126  if (ty_class < 0) {
127  string msg = "cannot get hdf5 attribute datatype class for the attribute ";
128  string attrnamestr(attr_name.begin(),attr_name.end());
129  msg += attrnamestr;
130  H5Aclose(attrid);
131  throw InternalErr(__FILE__, __LINE__, msg);
132  }
133 
134  // The following datatype will not be supported for mapping to DAS for both DAP2 and DAP4.
135  // Note:DAP4 explicitly states that the data should be defined atomic datatype(int, string).
136  // 1-D variable length of string can also be mapped to both DAS and DDS.
137  // The variable length string class is H5T_STRING rather than H5T_VLEN,
138  // So safe here.
139  // We also ignore the mapping of integer 64 bit for DAP2 since DAP2 doesn't
140  // support 64-bit integer. In theory, DAP2 doesn't support long double
141  // (128-bit or 92-bit floating point type), since this rarely happens
142  // in DAP application, we simply don't consider here.
143  // However, DAP4 supports 64-bit integer.
144  if ((ty_class == H5T_TIME) || (ty_class == H5T_BITFIELD)
145  || (ty_class == H5T_OPAQUE) || (ty_class == H5T_ENUM)
146  || (ty_class == H5T_REFERENCE) ||(ty_class == H5T_COMPOUND)
147  || (ty_class == H5T_VLEN) || (ty_class == H5T_ARRAY)){
148 
149  *ignore_attr_ptr = true;
150  H5Tclose(ty_id);
151  return attrid;
152  }
153 
154  // Ignore 64-bit integer for DAP2.
155  // The nested if is better to understand the code. Don't combine
156  if (false == is_dap4) {
157  if((ty_class == H5T_INTEGER) && (H5Tget_size(ty_id)== 8)) {//64-bit int
158  *ignore_attr_ptr = true;
159  H5Tclose(ty_id);
160  return attrid;
161  }
162  }
163 
164  // Here we ignore netCDF-4 specific attributes for DAP4 to make filenetCDF-4 work
165  if (true == is_dap4 && HDF5RequestHandler::get_default_handle_dimension() == true) {
166  // Remove the NULLTERM etc.
167  string attr_name_str(attr_name.begin(),attr_name.end()-1);
168  if(attr_name_str == "CLASS" || attr_name_str == "NAME" || attr_name_str == "_Netcdf4Dimid"
169  || attr_name_str == "_nc3_strict" || attr_name_str=="_NCProperties" || attr_name_str=="_Netcdf4Coordinates") {
170  *ignore_attr_ptr = true;
171  H5Tclose(ty_id);
172  return attrid;
173  }
174  }
175 
176  hid_t aspace_id = -1;
177  if ((aspace_id = H5Aget_space(attrid)) < 0) {
178  string msg = "cannot get hdf5 dataspace id for the attribute ";
179  string attrnamestr(attr_name.begin(),attr_name.end());
180  msg += attrnamestr;
181  H5Aclose(attrid);
182  throw InternalErr(__FILE__, __LINE__, msg);
183  }
184 
185  // It is better to use the dynamic allocation of the array.
186  // However, since the DODS_MAX_RANK is not big and it is also
187  // used in other location, we still keep the original code.
188  // KY 2011-11-16
189 
190  int ndims = H5Sget_simple_extent_ndims(aspace_id);
191  if (ndims < 0) {
192  string msg = "cannot get hdf5 dataspace number of dimension for attribute ";
193  string attrnamestr(attr_name.begin(),attr_name.end());
194  msg += attrnamestr;
195  H5Sclose(aspace_id);
196  H5Aclose(attrid);
197  throw InternalErr(__FILE__, __LINE__, msg);
198  }
199 
200  // Check if the dimension size exceeds the maximum number of dimension DAP supports
201  if (ndims > DODS_MAX_RANK) {
202  string msg = "number of dimensions exceeds allowed for attribute ";
203  string attrnamestr(attr_name.begin(),attr_name.end());
204  msg += attrnamestr;
205  H5Sclose(aspace_id);
206  H5Aclose(attrid);
207  throw InternalErr(__FILE__, __LINE__, msg);
208  }
209 
210  hsize_t size[DODS_MAX_RANK];
211  hsize_t maxsize[DODS_MAX_RANK];
212 
213  //The HDF5 attribute should not have unlimited dimension,
214  // maxsize is only a place holder.
215  if (H5Sget_simple_extent_dims(aspace_id, size, maxsize)<0){
216  string msg = "cannot obtain the dim. info for the attribute ";
217  string attrnamestr(attr_name.begin(),attr_name.end());
218  msg += attrnamestr;
219  H5Sclose(aspace_id);
220  H5Aclose(attrid);
221  throw InternalErr(__FILE__, __LINE__, msg);
222  }
223 
224  // Return ndims and size[ndims].
225  hsize_t nelmts = 1;
226  if (ndims) {
227  for (int j = 0; j < ndims; j++)
228  nelmts *= size[j];
229  }
230 
231  size_t ty_size = H5Tget_size(ty_id);
232  if (ty_size == 0) {
233  string msg = "cannot obtain the dtype size for the attribute ";
234  string attrnamestr(attr_name.begin(),attr_name.end());
235  msg += attrnamestr;
236  H5Sclose(aspace_id);
237  H5Aclose(attrid);
238  throw InternalErr(__FILE__, __LINE__, msg);
239  }
240 
241  size_t need = nelmts * H5Tget_size(ty_id);
242 
243  // We want to save memory type in the struct.
244  hid_t memtype = H5Tget_native_type(ty_id, H5T_DIR_ASCEND);
245  if (memtype < 0){
246  string msg = "cannot obtain the memory dtype for the attribute ";
247  string attrnamestr(attr_name.begin(),attr_name.end());
248  msg += attrnamestr;
249  H5Sclose(aspace_id);
250  H5Aclose(attrid);
251  throw InternalErr(__FILE__, __LINE__, msg);
252  }
253 
254  // Save the information to the struct
255  (*attr_inst_ptr).type = memtype;
256  (*attr_inst_ptr).ndims = ndims;
257  (*attr_inst_ptr).nelmts = nelmts;
258  (*attr_inst_ptr).need = need;
259  strncpy((*attr_inst_ptr).name, &attr_name[0], name_size+1);
260 
261  for (int j = 0; j < ndims; j++) {
262  (*attr_inst_ptr).size[j] = size[j];
263  }
264 
265  if(H5Sclose(aspace_id)<0) {
266  H5Aclose(attrid);
267  throw InternalErr(__FILE__,__LINE__,"Cannot close HDF5 dataspace ");
268  }
269 
270  return attrid;
271 }
272 
285 string get_dap_type(hid_t type, bool is_dap4)
286 {
287  size_t size = 0;
288  H5T_sign_t sign;
289  BESDEBUG("h5", ">get_dap_type(): type=" << type << endl);
290  H5T_class_t class_t = H5Tget_class(type);
291  if (H5T_NO_CLASS == class_t)
292  throw InternalErr(__FILE__, __LINE__,
293  "The HDF5 datatype doesn't belong to any Class.");
294  switch (class_t) {
295 
296  case H5T_INTEGER:
297 
298  size = H5Tget_size(type);
299  if (size == 0){
300  throw InternalErr(__FILE__, __LINE__,
301  "size of datatype is invalid");
302  }
303 
304  sign = H5Tget_sign(type);
305  if (sign < 0){
306  throw InternalErr(__FILE__, __LINE__,
307  "sign of datatype is invalid");
308  }
309 
310  BESDEBUG("h5", "=get_dap_type(): H5T_INTEGER" <<
311  " sign = " << sign <<
312  " size = " << size <<
313  endl);
314  if (size == 1){
315  // DAP2 doesn't have signed 8-bit integer, so we need map it to INT16.
316  if(true == is_dap4) {
317  if (sign == H5T_SGN_NONE)
318  return BYTE;
319  else
320  return INT8;
321  }
322  else {
323  if (sign == H5T_SGN_NONE)
324  return BYTE;
325  else
326  return INT16;
327  }
328  }
329 
330  if (size == 2) {
331  if (sign == H5T_SGN_NONE)
332  return UINT16;
333  else
334  return INT16;
335  }
336 
337  if (size == 4) {
338  if (sign == H5T_SGN_NONE)
339  return UINT32;
340  else
341  return INT32;
342  }
343 
344  if(size == 8) {
345  // DAP4 supports 64-bit integer.
346  if (true == is_dap4) {
347  if (sign == H5T_SGN_NONE)
348  return UINT64;
349  else
350  return INT64;
351  }
352  else
353  return INT_ELSE;
354  }
355 
356  return INT_ELSE;
357 
358  case H5T_FLOAT:
359  size = H5Tget_size(type);
360  if (size == 0){
361  throw InternalErr(__FILE__, __LINE__,
362  "size of the datatype is invalid");
363  }
364 
365  BESDEBUG("h5", "=get_dap_type(): FLOAT size = " << size << endl);
366  if (size == 4)
367  return FLOAT32;
368  if (size == 8)
369  return FLOAT64;
370 
371  return FLOAT_ELSE;
372 
373  case H5T_STRING:
374  BESDEBUG("h5", "<get_dap_type(): H5T_STRING" << endl);
375  return STRING;
376 
377  case H5T_REFERENCE:
378  BESDEBUG("h5", "<get_dap_type(): H5T_REFERENCE" << endl);
379  return URL;
380  // Note: Currently DAP2 and DAP4 only support defined atomic types.
381  // So the H5T_COMPOUND and H5_ARRAY cases should never be reached for attribute handling.
382  // However, this function may be used for variable handling.
383  case H5T_COMPOUND:
384  BESDEBUG("h5", "<get_dap_type(): COMPOUND" << endl);
385  return COMPOUND;
386 
387  case H5T_ARRAY:
388  return ARRAY;
389 
390  default:
391  BESDEBUG("h5", "<get_dap_type(): Unmappable Type" << endl);
392  return "Unmappable Type";
393  }
394 }
395 
405 hid_t get_fileid(const char *filename)
406 {
407  hid_t fileid = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
408  if (fileid < 0){
409  string msg = "cannot open the HDF5 file ";
410  string filenamestr(filename);
411  msg += filenamestr;
412  throw InternalErr(__FILE__, __LINE__, msg);
413  }
414 
415  return fileid;
416 }
417 
427 void close_fileid(hid_t fid)
428 {
429  if (H5Fclose(fid) < 0)
430  throw Error(unknown_error,
431  string("Could not close the HDF5 file."));
432 
433 }
434 
435 void get_dataset(hid_t pid, const string &dname, DS_t * dt_inst_ptr)
436 {
437 
438  bool is_pure_dim = false;
439  get_dataset(pid,dname,dt_inst_ptr,false,is_pure_dim);
440 }
452 void get_dataset(hid_t pid, const string &dname, DS_t * dt_inst_ptr,bool use_dimscale, bool &is_pure_dim)
453 {
454 
455  BESDEBUG("h5", ">get_dataset()" << endl);
456 
457  // Obtain the dataset ID
458  hid_t dset = -1;
459  if ((dset = H5Dopen(pid, dname.c_str(),H5P_DEFAULT)) < 0) {
460  string msg = "cannot open the HDF5 dataset ";
461  msg += dname;
462  throw InternalErr(__FILE__, __LINE__, msg);
463  }
464 
465  // Obtain the datatype ID
466  hid_t dtype = -1;
467  if ((dtype = H5Dget_type(dset)) < 0) {
468  H5Dclose(dset);
469  string msg = "cannot get the the datatype of HDF5 dataset ";
470  msg += dname;
471  throw InternalErr(__FILE__, __LINE__, msg);
472  }
473 
474  // Obtain the datatype class
475  H5T_class_t ty_class = H5Tget_class(dtype);
476  if (ty_class < 0) {
477  H5Tclose(dtype);
478  H5Dclose(dset);
479  string msg = "cannot get the datatype class of HDF5 dataset ";
480  msg += dname;
481  throw InternalErr(__FILE__, __LINE__, msg);
482  }
483 
484  // These datatype classes are unsupported. Note we do support
485  // variable length string and the variable length string class is
486  // H5T_STRING rather than H5T_VLEN.
487  if ((ty_class == H5T_TIME) || (ty_class == H5T_BITFIELD)
488  || (ty_class == H5T_OPAQUE) || (ty_class == H5T_ENUM) || (ty_class == H5T_VLEN)) {
489  string msg = "unexpected datatype of HDF5 dataset ";
490  msg += dname;
491  throw InternalErr(__FILE__, __LINE__, msg);
492  }
493 
494  hid_t dspace = -1;
495  if ((dspace = H5Dget_space(dset)) < 0) {
496  H5Tclose(dtype);
497  H5Dclose(dset);
498  string msg = "cannot get the the dataspace of HDF5 dataset ";
499  msg += dname;
500  throw InternalErr(__FILE__, __LINE__, msg);
501  }
502 
503  // It is better to use the dynamic allocation of the array.
504  // However, since the DODS_MAX_RANK is not big and it is also
505  // used in other location, we still keep the original code.
506  // KY 2011-11-17
507 
508  int ndims = H5Sget_simple_extent_ndims(dspace);
509  if (ndims < 0) {
510  H5Tclose(dtype);
511  H5Sclose(dspace);
512  H5Dclose(dset);
513  string msg = "cannot get hdf5 dataspace number of dimension for dataset ";
514  msg += dname;
515  throw InternalErr(__FILE__, __LINE__, msg);
516  }
517 
518  // Check if the dimension size exceeds the maximum number of dimension DAP supports
519  if (ndims > DODS_MAX_RANK) {
520  string msg = "number of dimensions exceeds allowed for dataset ";
521  msg += dname;
522  H5Tclose(dtype);
523  H5Sclose(dspace);
524  H5Dclose(dset);
525  throw InternalErr(__FILE__, __LINE__, msg);
526  }
527 
528  hsize_t size[DODS_MAX_RANK];
529  hsize_t maxsize[DODS_MAX_RANK];
530 
531  // Retrieve size. DAP4 doesn't have a convention to support multi-unlimited dimension yet.
532  if (H5Sget_simple_extent_dims(dspace, size, maxsize)<0){
533  string msg = "cannot obtain the dim. info for the dataset ";
534  msg += dname;
535  H5Tclose(dtype);
536  H5Sclose(dspace);
537  H5Dclose(dset);
538  throw InternalErr(__FILE__, __LINE__, msg);
539  }
540 
541  // return ndims and size[ndims].
542  hsize_t nelmts = 1;
543  if (ndims !=0) {
544  for (int j = 0; j < ndims; j++)
545  nelmts *= size[j];
546  }
547 
548  size_t dtype_size = H5Tget_size(dtype);
549  if (dtype_size == 0) {
550  string msg = "cannot obtain the data type size for the dataset ";
551  msg += dname;
552  H5Tclose(dtype);
553  H5Sclose(dspace);
554  H5Dclose(dset);
555  throw InternalErr(__FILE__, __LINE__, msg);
556  }
557 
558  size_t need = nelmts * dtype_size;
559 
560  hid_t memtype = H5Tget_native_type(dtype, H5T_DIR_ASCEND);
561  if (memtype < 0){
562  string msg = "cannot obtain the memory data type for the dataset ";
563  msg += dname;
564  H5Tclose(dtype);
565  H5Sclose(dspace);
566  H5Dclose(dset);
567  throw InternalErr(__FILE__, __LINE__, msg);
568  }
569 
570  (*dt_inst_ptr).type = memtype;
571  (*dt_inst_ptr).ndims = ndims;
572  (*dt_inst_ptr).nelmts = nelmts;
573  (*dt_inst_ptr).need = need;
574  strncpy((*dt_inst_ptr).name, dname.c_str(), dname.length());
575  (*dt_inst_ptr).name[dname.length()] = '\0';
576  for (int j = 0; j < ndims; j++)
577  (*dt_inst_ptr).size[j] = size[j];
578 
579  // For DAP4 when dimension scales are used.
580  if(true == use_dimscale) {
581  BESDEBUG("h5", "<h5get.cc: get_dataset() use dim scale is true." << endl);
582 
583  // Some HDF5 datasets are dimension scale datasets; some are not. We need to distinguish.
584  bool is_dimscale = false;
585 
586  // Dimension scales must be 1-D.
587  if(1 == ndims) {
588 
589  bool has_ds_attr = false;
590 
591  try{
592  has_ds_attr = has_dimscale_attr(dset);
593  }
594  catch(...) {
595  H5Tclose(dtype);
596  H5Sclose(dspace);
597  H5Dclose(dset);
598  throw InternalErr(__FILE__, __LINE__, "Fail to check dim. scale.");
599  }
600 
601  if(true == has_ds_attr) {
602 
603  //int count = 0;
604  //vector<bool>dim_attr_mark;
605  //dim_attr_mark.resize(4);
606  //bool dim_attr_mark[4];
607  int dim_attr_mark[3];
608  for(int i = 0;i<3;i++)
609  dim_attr_mark[i] = 0;
610 
611  // This will check if "NAME" and "REFERENCE_LIST" exists.
612  //herr_t ret = H5Aiterate2(dset, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info, &dim_attr_mark[0]);
613  herr_t ret = H5Aiterate2(dset, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info_dimscale, dim_attr_mark);
614  if(ret < 0) {
615  string msg = "cannot interate the attributes of the dataset ";
616  msg += dname;
617  H5Tclose(dtype);
618  H5Sclose(dspace);
619  H5Dclose(dset);
620  throw InternalErr(__FILE__, __LINE__, msg);
621  }
622 
623  for (int i = 0; i<3;i++)
624  BESDEBUG("h5","dim_attr_mark is "<<dim_attr_mark[i] <<endl);
625  // Find the dimension scale. DIM*SCALE is a must. Then NAME=VARIABLE or (REFERENCE_LIST and not PURE DIM)
626  // Here a little bias towards files created by the netCDF-4 APIs.
627  // If we don't have RERERENCE_LIST in a dataset that has CLASS=DIMENSION_SCALE attribute,
628  // we will ignore this orphage dimension sale since it is not associated with other datasets.
629  // However, it is an orphage dimension scale created by the netCDF-4 APIs, we think
630  // it must have a purpose to do this way by data creator. So keep this as a dimension scale.
631  //
632  if (((dim_attr_mark[0] && !dim_attr_mark[1]) || dim_attr_mark[2]))
633  is_dimscale =true;
634  else if(dim_attr_mark[1])
635  is_pure_dim = true;
636  }
637  }
638 
639  if(true == is_dimscale) {
640  BESDEBUG("h5", "<h5get.cc: dname is " << dname << endl);
641  BESDEBUG("h5", "<h5get.cc: get_dataset() this is dim scale." << endl);
642  BESDEBUG("h5", "<h5get.cc: dataset storage size is: " <<H5Dget_storage_size(dset)<< endl);
643  //if(H5Dget_storage_size(dset)!=0) {
644  // Save the dimension names.We Only need to provide the dimension name(not the full path).
645  // We still need the dimension name fullpath for distinguishing the different dimension that
646  // has the same dimension name but in the different path
647  // TODO; pure dimension doesn't work for all cases. See https://jira.hdfgroup.org/browse/HFVHANDLER-340
648  (*dt_inst_ptr).dimnames.push_back(dname.substr(dname.find_last_of("/")+1));
649  (*dt_inst_ptr).dimnames_path.push_back(dname);
650  //}
651  //else
652  //is_pure_dim = true;
653  is_pure_dim = false;
654  }
655 
656  else if(false == is_pure_dim) // Except pure dimension,we need to save all dimension names in this dimension.
657  obtain_dimnames(dset,ndims,dt_inst_ptr);
658  }
659 
660  if(H5Tclose(dtype)<0) {
661  H5Sclose(dspace);
662  H5Dclose(dset);
663  throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 datatype.");
664  }
665 
666  if(H5Sclose(dspace)<0) {
667  H5Dclose(dset);
668  throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 dataspace.");
669  }
670 
671  if(H5Dclose(dset)<0) {
672  throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 dataset.");
673  }
674 
675 }
676 
685 bool check_h5str(hid_t h5type)
686 {
687  if (H5Tget_class(h5type) == H5T_STRING)
688  return true;
689  else
690  return false;
691 }
692 
693 
706 string print_attr(hid_t type, int loc, void *sm_buf) {
707  union {
708  unsigned char* ucp;
709  char *tcp;
710  short *tsp;
711  unsigned short *tusp;
712  int *tip;
713  unsigned int*tuip;
714  long *tlp;
715  unsigned long*tulp;
716  float *tfp;
717  double *tdp;
718  } gp;
719 
720  vector<char> rep;
721 
722  switch (H5Tget_class(type)) {
723 
724  case H5T_INTEGER: {
725 
726  size_t size = H5Tget_size(type);
727  if (size == 0){
728  throw InternalErr(__FILE__, __LINE__,
729  "size of datatype is invalid");
730  }
731 
732  H5T_sign_t sign = H5Tget_sign(type);
733  if (sign < 0){
734  throw InternalErr(__FILE__, __LINE__,
735  "sign of datatype is invalid");
736  }
737 
738  BESDEBUG("h5", "=get_dap_type(): H5T_INTEGER" <<
739  " sign = " << sign <<
740  " size = " << size <<
741  endl);
742 
743  // change void pointer into the corresponding integer datatype.
744  // 32 should be long enough to hold one integer and one
745  // floating point number.
746  rep.resize(32);
747 
748  if (size == 1){
749 
750  if(sign == H5T_SGN_NONE) {
751  gp.ucp = (unsigned char *) sm_buf;
752  unsigned char tuchar = *(gp.ucp + loc);
753  snprintf(&rep[0], 32, "%u", tuchar);
754  }
755 
756  else {
757  gp.tcp = (char *) sm_buf;
758  snprintf(&rep[0], 32, "%d", *(gp.tcp + loc));
759  }
760  }
761 
762  else if (size == 2) {
763 
764  if(sign == H5T_SGN_NONE) {
765  gp.tusp = (unsigned short *) sm_buf;
766  snprintf(&rep[0], 32, "%hu", *(gp.tusp + loc));
767 
768  }
769  else {
770  gp.tsp = (short *) sm_buf;
771  snprintf(&rep[0], 32, "%hd", *(gp.tsp + loc));
772 
773  }
774  }
775 
776  else if (size == 4) {
777 
778  if(sign == H5T_SGN_NONE) {
779  gp.tuip = (unsigned int *) sm_buf;
780  snprintf(&rep[0], 32, "%u", *(gp.tuip + loc));
781 
782  }
783  else {
784  gp.tip = (int *) sm_buf;
785  snprintf(&rep[0], 32, "%d", *(gp.tip + loc));
786  }
787  }
788  else if (size == 8) {
789 
790  if(sign == H5T_SGN_NONE) {
791  gp.tulp = (unsigned long *) sm_buf;
792  snprintf(&rep[0], 32, "%lu", *(gp.tulp + loc));
793  }
794  else {
795  gp.tlp = (long *) sm_buf;
796  snprintf(&rep[0], 32, "%ld", *(gp.tlp + loc));
797  }
798  }
799  else
800  throw InternalErr(__FILE__, __LINE__,"Unsupported integer type, check the size of datatype.");
801 
802  break;
803  }
804 
805  case H5T_FLOAT: {
806  rep.resize(32);
807  char gps[32];
808 
809  if (H5Tget_size(type) == 4) {
810 
811  float attr_val = *(float*)sm_buf;
812  bool is_a_fin = isfinite(attr_val);
813  // Represent the float number.
814  // Some space may be wasted. But it is okay.
815  gp.tfp = (float *) sm_buf;
816  int ll = snprintf(gps, 30, "%.10g", *(gp.tfp + loc));
817  //int ll = strlen(gps);
818 
819  // Add the dot to assure this is a floating number
820  if (!strchr(gps, '.') && !strchr(gps, 'e') && !strchr(gps,'E')
821  && (true == is_a_fin)){
822  gps[ll++] = '.';
823  }
824 
825  gps[ll] = '\0';
826  snprintf(&rep[0], 32, "%s", gps);
827  }
828  else if (H5Tget_size(type) == 8) {
829 
830  double attr_val = *(double*)sm_buf;
831  bool is_a_fin = isfinite(attr_val);
832  gp.tdp = (double *) sm_buf;
833  int ll = snprintf(gps, 30, "%.17g", *(gp.tdp + loc));
834 #if 0
835  //int ll = strlen(gps);
836 #endif
837  if (!strchr(gps, '.') && !strchr(gps, 'e')&& !strchr(gps,'E')
838  && (true == is_a_fin)) {
839  gps[ll++] = '.';
840  }
841  gps[ll] = '\0';
842  snprintf(&rep[0], 32, "%s", gps);
843  }
844  else if (H5Tget_size(type) == 0){
845  throw InternalErr(__FILE__, __LINE__, "H5Tget_size() failed.");
846  }
847  break;
848  }
849 
850  case H5T_STRING: {
851  int str_size = H5Tget_size(type);
852  if(H5Tis_variable_str(type)>0) {
853  throw InternalErr(__FILE__, __LINE__,
854  "print_attr function doesn't handle variable length string, variable length string should be handled separately.");
855  }
856  if (str_size == 0){
857  throw InternalErr(__FILE__, __LINE__, "H5Tget_size() failed.");
858  }
859  BESDEBUG("h5", "=print_attr(): H5T_STRING sm_buf=" << (char *) sm_buf
860  << " size=" << str_size << endl);
861  char *buf = NULL;
862  // This try/catch block is here to protect the allocation of buf.
863  try {
864  buf = new char[str_size + 1];
865  strncpy(buf, (char *) sm_buf, str_size);
866  buf[str_size] = '\0';
867  // Not necessarily allocate 3 more bytes.
868  rep.resize(str_size+3);
869  snprintf(&rep[0], str_size + 3, "%s", buf);
870  rep[str_size + 2] = '\0';
871  delete[] buf; buf = 0;
872  }
873  catch (...) {
874  if( buf ) delete[] buf;
875  throw;
876  }
877  break;
878  }
879 
880  default:
881  break;
882  } // switch(H5Tget_class(type))
883 
884  string rep_str(rep.begin(),rep.end());
885  return rep_str;
886 }
887 
888 D4AttributeType daptype_strrep_to_dap4_attrtype(std::string s){
889 
890  if (s == "Byte")
891  return attr_byte_c;
892  else if (s == "Int8")
893  return attr_int8_c;
894  else if (s == "UInt8") // This may never be used.
895  return attr_uint8_c;
896  else if (s == "Int16")
897  return attr_int16_c;
898  else if (s == "UInt16")
899  return attr_uint16_c;
900  else if (s == "Int32")
901  return attr_int32_c;
902  else if (s == "UInt32")
903  return attr_uint32_c;
904  else if (s == "Int64")
905  return attr_int64_c;
906  else if (s == "UInt64")
907  return attr_uint64_c;
908  else if (s == "Float32")
909  return attr_float32_c;
910  else if (s == "Float64")
911  return attr_float64_c;
912  else if (s == "String")
913  return attr_str_c;
914  else if (s == "Url")
915  return attr_url_c;
916  else
917  return attr_null_c;
918 
919 
920 }
921 
922 
936 //static BaseType *Get_bt(const string &vname,
937 BaseType *Get_bt(const string &vname,
938  const string &vpath,
939  const string &dataset,
940  hid_t datatype, bool is_dap4)
941 {
942  BaseType *btp = NULL;
943 
944  try {
945 
946  BESDEBUG("h5", ">Get_bt varname=" << vname << " datatype=" << datatype
947  << endl);
948 
949  size_t size = 0;
950  H5T_sign_t sign = H5T_SGN_ERROR;
951  switch (H5Tget_class(datatype)) {
952 
953  case H5T_INTEGER:
954  {
955  size = H5Tget_size(datatype);
956  sign = H5Tget_sign(datatype);
957  BESDEBUG("h5", "=Get_bt() H5T_INTEGER size = " << size << " sign = "
958  << sign << endl);
959 
960  if (sign == H5T_SGN_ERROR) {
961  throw InternalErr(__FILE__, __LINE__, "cannot retrieve the sign type of the integer");
962  }
963  if (size == 0) {
964  throw InternalErr(__FILE__, __LINE__, "cannot return the size of the datatype");
965  }
966  else if (size == 1) { // Either signed char or unsigned char
967  // DAP2 doesn't support signed char, it maps to DAP int16.
968  if (sign == H5T_SGN_2) {
969  if (false == is_dap4) // signed char to DAP2 int16
970  btp = new HDF5Int16(vname, vpath, dataset);
971  else
972  btp = new HDF5Int8(vname,vpath,dataset);
973  }
974  else
975  btp = new HDF5Byte(vname, vpath,dataset);
976  }
977  else if (size == 2) {
978  if (sign == H5T_SGN_2)
979  btp = new HDF5Int16(vname, vpath,dataset);
980  else
981  btp = new HDF5UInt16(vname,vpath, dataset);
982  }
983  else if (size == 4) {
984  if (sign == H5T_SGN_2){
985  btp = new HDF5Int32(vname, vpath,dataset);
986  }
987  else
988  btp = new HDF5UInt32(vname,vpath, dataset);
989  }
990  else if (size == 8) {
991  if(true == is_dap4) {
992  if(sign == H5T_SGN_2)
993  btp = new HDF5Int64(vname,vpath, dataset);
994  else
995  btp = new HDF5UInt64(vname,vpath, dataset);
996  }
997  else {
998  throw
999  InternalErr(__FILE__, __LINE__,
1000  string("Unsupported HDF5 64-bit Integer type:")
1001  + vname);
1002  }
1003  }
1004  }
1005  break;
1006 
1007  case H5T_FLOAT:
1008  {
1009  size = H5Tget_size(datatype);
1010  BESDEBUG("h5", "=Get_bt() H5T_FLOAT size = " << size << endl);
1011 
1012  if (size == 0) {
1013  throw InternalErr(__FILE__, __LINE__, "cannot return the size of the datatype");
1014  }
1015  else if (size == 4) {
1016  btp = new HDF5Float32(vname,vpath, dataset);
1017  }
1018  else if (size == 8) {
1019  btp = new HDF5Float64(vname,vpath, dataset);
1020  }
1021  }
1022  break;
1023 
1024  case H5T_STRING:
1025  btp = new HDF5Str(vname, vpath,dataset);
1026  break;
1027 
1028  // The array datatype is rarely,rarely used. So this
1029  // part of code is not reviewed.
1030 #if 0
1031  case H5T_ARRAY: {
1032  BaseType *ar_bt = 0;
1033  try {
1034  BESDEBUG("h5",
1035  "=Get_bt() H5T_ARRAY datatype = " << datatype
1036  << endl);
1037 
1038  // Get the base datatype of the array
1039  hid_t dtype_base = H5Tget_super(datatype);
1040  ar_bt = Get_bt(vname, dataset, dtype_base);
1041  btp = new HDF5Array(vname, dataset, ar_bt);
1042  delete ar_bt; ar_bt = 0;
1043 
1044  // Set the size of the array.
1045  int ndim = H5Tget_array_ndims(datatype);
1046  size = H5Tget_size(datatype);
1047  int nelement = 1;
1048 
1049  if (dtype_base < 0) {
1050  throw InternalErr(__FILE__, __LINE__, "cannot return the base datatype");
1051  }
1052  if (ndim < 0) {
1053  throw InternalErr(__FILE__, __LINE__, "cannot return the rank of the array datatype");
1054  }
1055  if (size == 0) {
1056  throw InternalErr(__FILE__, __LINE__, "cannot return the size of the datatype");
1057  }
1058  BESDEBUG(cerr
1059  << "=Get_bt()" << " Dim = " << ndim
1060  << " Size = " << size
1061  << endl);
1062 
1063  hsize_t size2[DODS_MAX_RANK];
1064  if(H5Tget_array_dims(datatype, size2) < 0){
1065  throw
1066  InternalErr(__FILE__, __LINE__,
1067  string("Could not get array dims for: ")
1068  + vname);
1069  }
1070 
1071 
1072  HDF5Array &h5_ar = static_cast < HDF5Array & >(*btp);
1073  for (int dim_index = 0; dim_index < ndim; dim_index++) {
1074  h5_ar.append_dim(size2[dim_index]);
1075  BESDEBUG("h5", "=Get_bt() " << size2[dim_index] << endl);
1076  nelement = nelement * size2[dim_index];
1077  }
1078 
1079  h5_ar.set_did(dt_inst.dset);
1080  // Assign the array datatype id.
1081  h5_ar.set_tid(datatype);
1082  h5_ar.set_memneed(size);
1083  h5_ar.set_numdim(ndim);
1084  h5_ar.set_numelm(nelement);
1085  h5_ar.set_length(nelement);
1086  h5_ar.d_type = H5Tget_class(dtype_base);
1087  if (h5_ar.d_type == H5T_NO_CLASS){
1088  throw InternalErr(__FILE__, __LINE__, "cannot return the datatype class identifier");
1089  }
1090  }
1091  catch (...) {
1092  if( ar_bt ) delete ar_bt;
1093  if( btp ) delete btp;
1094  throw;
1095  }
1096  break;
1097  }
1098 #endif
1099 
1100  // Reference map to DAP URL, check the technical note.
1101  case H5T_REFERENCE:
1102  btp = new HDF5Url(vname, vpath,dataset);
1103  break;
1104 
1105  default:
1106  throw InternalErr(__FILE__, __LINE__,
1107  string("Unsupported HDF5 type: ") + vname);
1108  }
1109  }
1110  catch (...) {
1111  if( btp ) delete btp;
1112  throw;
1113  }
1114 
1115  if (!btp)
1116  throw InternalErr(__FILE__, __LINE__,
1117  string("Could not make a DAP variable for: ")
1118  + vname);
1119 
1120  BESDEBUG("h5", "<Get_bt()" << endl);
1121  return btp;
1122 }
1123 
1124 
1141 //static Structure *Get_structure(const string &varname,
1142 Structure *Get_structure(const string &varname,const string &vpath,
1143  const string &dataset,
1144  hid_t datatype,bool is_dap4)
1145 {
1146  HDF5Structure *structure_ptr = NULL;
1147  char* memb_name = NULL;
1148  hid_t memb_type = -1;
1149 
1150  BESDEBUG("h5", ">Get_structure()" << datatype << endl);
1151 
1152  if (H5Tget_class(datatype) != H5T_COMPOUND)
1153  throw InternalErr(__FILE__, __LINE__,
1154  string("Compound-to-structure mapping error for ")
1155  + varname);
1156 
1157  try {
1158  structure_ptr = new HDF5Structure(varname, vpath, dataset);
1159 
1160  // Retrieve member types
1161  int nmembs = H5Tget_nmembers(datatype);
1162  BESDEBUG("h5", "=Get_structure() has " << nmembs << endl);
1163  if (nmembs < 0){
1164  throw InternalErr(__FILE__, __LINE__, "cannot retrieve the number of elements");
1165  }
1166  for (int i = 0; i < nmembs; i++) {
1167  memb_name = H5Tget_member_name(datatype, i);
1168  H5T_class_t memb_cls = H5Tget_member_class(datatype, i);
1169  memb_type = H5Tget_member_type(datatype, i);
1170  if (memb_name == NULL){
1171  throw InternalErr(__FILE__, __LINE__, "cannot retrieve the name of the member");
1172  }
1173  if ((memb_cls < 0) || (memb_type < 0)) {
1174  throw InternalErr(__FILE__, __LINE__,
1175  string("Type mapping error for ")
1176  + string(memb_name) );
1177  }
1178 
1179  if (memb_cls == H5T_COMPOUND) {
1180  Structure *s = Get_structure(memb_name, memb_name, dataset, memb_type,is_dap4);
1181  structure_ptr->add_var(s);
1182  delete s; s = 0;
1183  }
1184  else if(memb_cls == H5T_ARRAY) {
1185 
1186  BaseType *ar_bt = 0;
1187  BaseType *btp = 0;
1188  Structure *s = 0;
1189  hid_t dtype_base = 0;
1190 
1191  try {
1192 
1193  // Get the base memb_type of the array
1194  dtype_base = H5Tget_super(memb_type);
1195 
1196  // Set the size of the array.
1197  int ndim = H5Tget_array_ndims(memb_type);
1198  size_t size = H5Tget_size(memb_type);
1199  int nelement = 1;
1200 
1201  if (dtype_base < 0) {
1202  throw InternalErr(__FILE__, __LINE__, "cannot return the base memb_type");
1203  }
1204  if (ndim < 0) {
1205  throw InternalErr(__FILE__, __LINE__, "cannot return the rank of the array memb_type");
1206  }
1207  if (size == 0) {
1208  throw InternalErr(__FILE__, __LINE__, "cannot return the size of the memb_type");
1209  }
1210 
1211  hsize_t size2[DODS_MAX_RANK];
1212  if(H5Tget_array_dims(memb_type, size2) < 0){
1213  throw
1214  InternalErr(__FILE__, __LINE__,
1215  string("Could not get array dims for: ")
1216  + string(memb_name));
1217  }
1218 
1219  H5T_class_t array_memb_cls = H5Tget_class(dtype_base);
1220  if(array_memb_cls == H5T_NO_CLASS) {
1221  throw InternalErr(__FILE__, __LINE__,
1222  string("cannot get the correct class for compound type member")
1223  + string(memb_name));
1224  }
1225  if(H5T_COMPOUND == array_memb_cls) {
1226 
1227  s = Get_structure(memb_name, memb_name,dataset, dtype_base,is_dap4);
1228  HDF5Array *h5_ar = new HDF5Array(memb_name, dataset, s);
1229 
1230  for (int dim_index = 0; dim_index < ndim; dim_index++) {
1231  h5_ar->append_dim(size2[dim_index]);
1232  nelement = nelement * size2[dim_index];
1233  }
1234 
1235  h5_ar->set_memneed(size);
1236  h5_ar->set_numdim(ndim);
1237  h5_ar->set_numelm(nelement);
1238  h5_ar->set_length(nelement);
1239 
1240  structure_ptr->add_var(h5_ar);
1241  delete h5_ar;
1242 
1243  }
1244  else if (H5T_INTEGER == array_memb_cls || H5T_FLOAT == array_memb_cls || H5T_STRING == array_memb_cls) {
1245  ar_bt = Get_bt(memb_name, memb_name,dataset, dtype_base,is_dap4);
1246  HDF5Array *h5_ar = new HDF5Array(memb_name,dataset,ar_bt);
1247 
1248  for (int dim_index = 0; dim_index < ndim; dim_index++) {
1249  h5_ar->append_dim(size2[dim_index]);
1250  nelement = nelement * size2[dim_index];
1251  }
1252 
1253  h5_ar->set_memneed(size);
1254  h5_ar->set_numdim(ndim);
1255  h5_ar->set_numelm(nelement);
1256  h5_ar->set_length(nelement);
1257 
1258  structure_ptr->add_var(h5_ar);
1259  delete h5_ar;
1260  }
1261  if( ar_bt ) delete ar_bt;
1262  if( btp ) delete btp;
1263  if(s) delete s;
1264  H5Tclose(dtype_base);
1265 
1266  }
1267  catch (...) {
1268  if( ar_bt ) delete ar_bt;
1269  if( btp ) delete btp;
1270  if(s) delete s;
1271  H5Tclose(dtype_base);
1272  throw;
1273  }
1274 
1275  }
1276  else if (memb_cls == H5T_INTEGER || memb_cls == H5T_FLOAT || memb_cls == H5T_STRING) {
1277  BaseType *bt = Get_bt(memb_name, memb_name,dataset, memb_type,is_dap4);
1278  structure_ptr->add_var(bt);
1279  delete bt; bt = 0;
1280  }
1281  else {
1282  free(memb_name);
1283  memb_name = NULL;
1284  throw InternalErr(__FILE__, __LINE__, "unsupported field datatype inside a compound datatype");
1285  }
1286  // Caller needs to free the memory allocated by the library for memb_name.
1287  if(memb_name != NULL)
1288  free(memb_name);
1289  }
1290  }
1291  catch (...) {
1292  if( structure_ptr )
1293  delete structure_ptr;
1294  if(memb_name!= NULL)
1295  free(memb_name);
1296  if(memb_type != -1)
1297  H5Tclose(memb_type);
1298  throw;
1299  }
1300 
1301  BESDEBUG("h5", "<Get_structure()" << endl);
1302 
1303  return structure_ptr;
1304 }
1305 
1322 
1323 // Function to use H5Ovisit to check if dimension scale attributes exist.
1324 bool check_dimscale(hid_t fileid) {
1325 
1326  bool ret_value = false;
1327  herr_t ret_o= H5Ovisit(fileid, H5_INDEX_NAME, H5_ITER_INC, visit_obj_cb, NULL);
1328  if(ret_o < 0)
1329  throw InternalErr(__FILE__, __LINE__, "H5Ovisit fails");
1330  else
1331  ret_value =(ret_o >0)?true:false;
1332 
1333  return ret_value;
1334 }
1335 
1336 static int
1337 visit_obj_cb(hid_t group_id, const char *name, const H5O_info_t *oinfo,
1338  void *_op_data)
1339 {
1340 
1341  int ret_value = 0;
1342  if(oinfo->type == H5O_TYPE_DATASET) {
1343 
1344  hid_t dataset = -1;
1345  dataset = H5Dopen2(group_id,name,H5P_DEFAULT);
1346  if(dataset <0)
1347  throw InternalErr(__FILE__, __LINE__, "H5Dopen2 fails in the H5Ovisit call back function.");
1348 
1349  hid_t dspace = -1;
1350  dspace = H5Dget_space(dataset);
1351  if(dspace <0) {
1352  H5Dclose(dataset);
1353  throw InternalErr(__FILE__, __LINE__, "H5Dget_space fails in the H5Ovisit call back function.");
1354  }
1355 
1356  // We only support netCDF-4 like dimension scales, that is the dimension scale dataset is 1-D dimension.
1357  if(H5Sget_simple_extent_ndims(dspace) == 1) {
1358  try {
1359  if(true == has_dimscale_attr(dataset))
1360  ret_value = 1;
1361  }
1362  catch(...) {
1363  H5Sclose(dspace);
1364  H5Dclose(dataset);
1365  throw;
1366  }
1367 
1368 #if 0
1369  //vector<bool>dim_attr_mark;
1370  //dim_attr_mark.resize(4);
1371  //bool dim_attr_mark[4];
1372  int dim_attr_mark[4];
1373  for(int i =0;i<4;i++)
1374  dim_attr_mark[i] = 0;
1375  //int count = 0;
1376  // Check if having "class = DIMENSION_SCALE" and REFERENCE_LIST attributes.
1377  //herr_t ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info, &count);
1378  //herr_t ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info, &dim_attr_mark[0]);
1379  herr_t ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_info, dim_attr_mark);
1380  if(ret < 0) {
1381  H5Sclose(dspace);
1382  H5Dclose(dataset);
1383  throw InternalErr(__FILE__, __LINE__, "H5Aiterate2 fails in the H5Ovisit call back function.");
1384  }
1385 
1386  BESDEBUG("h5", "<dset name is " << name <<endl);
1387  //BESDEBUG("h5", "<count is " << count <<endl);
1388  // Find it.
1389  if (dim_attr_mark[0] && dim_attr_mark[1]){
1390  //if (2==count || 3==count) {
1391  if(dspace != -1)
1392  H5Sclose(dspace);
1393  if(dataset != -1)
1394  H5Dclose(dataset);
1395  return 1;
1396  //}
1397  }
1398 #endif
1399  }
1400  if(dspace != -1)
1401  H5Sclose(dspace);
1402  if(dataset != -1)
1403  H5Dclose(dataset);
1404  }
1405  return ret_value;
1406 }
1407 
1408 bool has_dimscale_attr(hid_t dataset) {
1409 
1410  bool ret_value = false;
1411  string dimscale_attr_name="CLASS";
1412  string dimscale_attr_value="DIMENSION_SCALE";
1413  htri_t dimscale_attr_exist = H5Aexists_by_name(dataset,".",dimscale_attr_name.c_str(),H5P_DEFAULT);
1414  if(dimscale_attr_exist <0)
1415  throw InternalErr(__FILE__, __LINE__, "H5Aexists_by_name fails when checking the CLASS attribute.");
1416  else if(dimscale_attr_exist > 0) {//Attribute CLASS exists
1417 
1418  hid_t attr_id = -1;
1419  hid_t atype_id = -1;
1420 
1421  // Open the attribute
1422  attr_id = H5Aopen(dataset,dimscale_attr_name.c_str(), H5P_DEFAULT);
1423  if(attr_id < 0)
1424  throw InternalErr(__FILE__, __LINE__, "H5Aopen fails in the attr_info call back function.");
1425 
1426  // Get attribute datatype and dataspace
1427  atype_id = H5Aget_type(attr_id);
1428  if(atype_id < 0) {
1429  H5Aclose(attr_id);
1430  throw InternalErr(__FILE__, __LINE__, "H5Aget_type fails in the attr_info call back function.");
1431  }
1432 
1433  try {
1434  // Check if finding the attribute CLASS and the value is "DIMENSION_SCALE".
1435  if (H5T_STRING == H5Tget_class(atype_id))
1436  ret_value = check_str_attr_value(attr_id,atype_id,dimscale_attr_value,false);
1437  }
1438  catch(...) {
1439  if(atype_id != -1)
1440  H5Tclose(atype_id);
1441  if(attr_id != -1)
1442  H5Aclose(attr_id);
1443  throw;
1444  }
1445  // Close IDs.
1446  if(atype_id != -1)
1447  H5Tclose(atype_id);
1448  if(attr_id != -1)
1449  H5Aclose(attr_id);
1450  }
1451  return ret_value;
1452 
1453 }
1454 #if 0
1467 
1468 static herr_t
1469 attr_info_dimscale(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *opdata)
1470 {
1471  int *countp = (int*)opdata;
1472 
1473  hid_t attr_id = -1;
1474  hid_t atype_id = -1;
1475 
1476  // Open the attribute
1477  attr_id = H5Aopen(loc_id, name, H5P_DEFAULT);
1478  if(attr_id < 0)
1479  throw InternalErr(__FILE__, __LINE__, "H5Aopen fails in the attr_info call back function.");
1480 
1481  // Get attribute datatype and dataspace
1482  atype_id = H5Aget_type(attr_id);
1483  if(atype_id < 0) {
1484  H5Aclose(attr_id);
1485  throw InternalErr(__FILE__, __LINE__, "H5Aget_type fails in the attr_info call back function.");
1486  }
1487 
1488  try {
1489 
1490 #if 0
1491  // If finding the "REFERENCE_LIST", increases the countp.
1492  if ((H5T_COMPOUND == H5Tget_class(atype_id)) && (strcmp(name,"REFERENCE_LIST")==0)) {
1493  //(*countp)++;
1494  *dimattr_p = 1;
1495  //*dimattr_p = true;
1496  }
1497 #endif
1498  // Check if finding the attribute CLASS and the value is "DIMENSION_SCALE".
1499  if (H5T_STRING == H5Tget_class(atype_id)) {
1500  if (strcmp(name,"CLASS") == 0) {
1501  string dim_scale_mark = "DIMENSION_SCALE";
1502  bool is_dim_scale = check_str_attr_value(attr_id,atype_id,dim_scale_mark,false);
1503  if(true == is_dim_scale)
1504  (*countp)++;
1505  }
1506  }
1507  }
1508  catch(...) {
1509  if(atype_id != -1)
1510  H5Tclose(atype_id);
1511  if(attr_id != -1)
1512  H5Aclose(attr_id);
1513  throw;
1514  }
1515 
1516  // Close IDs.
1517  if(atype_id != -1)
1518  H5Tclose(atype_id);
1519  if(attr_id != -1)
1520  H5Aclose(attr_id);
1521 
1522  return 0;
1523 }
1524 
1525 #endif
1538 
1539 static herr_t
1540 attr_info_dimscale(hid_t loc_id, const char *name, const H5A_info_t *ainfo, void *opdata)
1541 {
1542  //bool *countp = (bool*)opdata;
1543  //bool *dimattr_p = (bool*)opdata;
1544  int *dimattr_p = (int*)opdata;
1545 
1546 #if 0
1547  bool has_reference_list = false;
1548  bool has_dimscale = false;
1549  bool has_name_as_var = false;
1550  bool has_name_as_nc4_purdim = false;
1551 #endif
1552 
1553 
1554  hid_t attr_id = -1;
1555  hid_t atype_id = -1;
1556 
1557  // Open the attribute
1558  attr_id = H5Aopen(loc_id, name, H5P_DEFAULT);
1559  if(attr_id < 0)
1560  throw InternalErr(__FILE__, __LINE__, "H5Aopen fails in the attr_info call back function.");
1561 
1562  // Get attribute datatype and dataspace
1563  atype_id = H5Aget_type(attr_id);
1564  if(atype_id < 0) {
1565  H5Aclose(attr_id);
1566  throw InternalErr(__FILE__, __LINE__, "H5Aget_type fails in the attr_info call back function.");
1567  }
1568 
1569  try {
1570 
1571 //#if 0
1572  // If finding the "REFERENCE_LIST", increases the countp.
1573  if ((H5T_COMPOUND == H5Tget_class(atype_id)) && (strcmp(name,"REFERENCE_LIST")==0)) {
1574  //(*countp)++;
1575  *dimattr_p = 1;
1576  //*dimattr_p = true;
1577  }
1578 //#endif
1579  // Check if finding the CLASS attribute.
1580  if (H5T_STRING == H5Tget_class(atype_id)) {
1581  if (strcmp(name,"NAME") == 0) {
1582 
1583  string pure_dimname_mark = "This is a netCDF dimension but not a netCDF variable";
1584  bool is_pure_dim = check_str_attr_value(attr_id,atype_id,pure_dimname_mark,true);
1585 
1586  BESDEBUG("h5","pure dimension name yes" << is_pure_dim <<endl);
1587  if(true == is_pure_dim)
1588  *(dimattr_p+1) =1;
1589  //*(dimattr_p+2) =true;
1590  else {
1591  // netCDF save the variable name in the "NAME" attribute.
1592  // We need to retrieve the variable name first.
1593  ssize_t objnamelen = -1;
1594  if ((objnamelen= H5Iget_name(loc_id,NULL,0))<=0) {
1595  string msg = "Cannot obtain the variable name length." ;
1596  throw InternalErr(__FILE__,__LINE__,msg);
1597  }
1598  vector<char> objname;
1599  objname.resize(objnamelen+1);
1600  if ((objnamelen= H5Iget_name(loc_id,&objname[0],objnamelen+1))<=0) {
1601  string msg = "Cannot obtain the variable name." ;
1602  throw InternalErr(__FILE__,__LINE__,msg);
1603  }
1604 
1605  string objname_str = string(objname.begin(),objname.end());
1606 
1607  // Must trim the string delimter.
1608  objname_str = objname_str.substr(0,objnamelen);
1609  // Remove the path
1610  string normal_dimname_mark = objname_str.substr(objname_str.find_last_of("/")+1);
1611  bool is_normal_dim = check_str_attr_value(attr_id,atype_id,normal_dimname_mark,false);
1612  if(true == is_normal_dim)
1613  *(dimattr_p+2) = 1;
1614  //*(dimattr_p+3) = true;
1615  }
1616  }
1617  }
1618 
1619 #if 0
1620  H5T_str_t str_pad = H5Tget_strpad(atype_id);
1621 
1622  hid_t aspace_id = -1;
1623  aspace_id = H5Aget_space(attr_id);
1624  if(aspace_id < 0)
1625  throw InternalErr(__FILE__, __LINE__, "H5Aget_space fails in the attr_info call back function.");
1626 
1627  // CLASS is a variable-length string
1628  int ndims = H5Sget_simple_extent_ndims(aspace_id);
1629  hsize_t nelmts = 1;
1630 
1631  // if it is a scalar attribute, just define number of elements to be 1.
1632  if (ndims != 0) {
1633 
1634  vector<hsize_t> asize;
1635  vector<hsize_t> maxsize;
1636  asize.resize(ndims);
1637  maxsize.resize(ndims);
1638 
1639  // DAP applications don't care about the unlimited dimensions
1640  // since the applications only care about retrieving the data.
1641  // So we don't check the maxsize to see if it is the unlimited dimension
1642  // attribute.
1643  if (H5Sget_simple_extent_dims(aspace_id, &asize[0], &maxsize[0])<0) {
1644  H5Sclose(aspace_id);
1645  throw InternalErr(__FILE__, __LINE__, "Cannot obtain the dim. info in the H5Aiterate2 call back function.");
1646  }
1647 
1648  // Return ndims and size[ndims].
1649  for (int j = 0; j < ndims; j++)
1650  nelmts *= asize[j];
1651  } // if(ndims != 0)
1652 
1653  size_t ty_size = H5Tget_size(atype_id);
1654  if (0 == ty_size) {
1655  H5Sclose(aspace_id);
1656  throw InternalErr(__FILE__, __LINE__, "Cannot obtain the type size in the H5Aiterate2 call back function.");
1657  }
1658 
1659  size_t total_bytes = nelmts * ty_size;
1660  string total_vstring ="";
1661  if(H5Tis_variable_str(atype_id) > 0) {
1662 
1663  // Variable length string attribute values only store pointers of the actual string value.
1664  vector<char> temp_buf;
1665  temp_buf.resize(total_bytes);
1666 
1667  if (H5Aread(attr_id, atype_id, &temp_buf[0]) < 0){
1668  H5Sclose(aspace_id);
1669  throw InternalErr(__FILE__,__LINE__,"Cannot read the attribute in the H5Aiterate2 call back function");
1670  }
1671 
1672  char *temp_bp = NULL;
1673  temp_bp = &temp_buf[0];
1674  char* onestring = NULL;
1675 
1676  for (unsigned int temp_i = 0; temp_i <nelmts; temp_i++) {
1677 
1678  // This line will assure that we get the real variable length string value.
1679  onestring =*(char **)temp_bp;
1680 
1681  if(onestring!= NULL)
1682  total_vstring +=string(onestring);
1683 
1684  // going to the next value.
1685  temp_bp +=ty_size;
1686  }
1687 
1688  if ((&temp_buf[0]) != NULL) {
1689  // Reclaim any VL memory if necessary.
1690  if (H5Dvlen_reclaim(atype_id,aspace_id,H5P_DEFAULT,&temp_buf[0]) < 0) {
1691  H5Sclose(aspace_id);
1692  throw InternalErr(__FILE__,__LINE__,"Cannot reclaim VL memory in the H5Aiterate2 call back function.");
1693  }
1694  }
1695 
1696  }
1697  else {// Fixed-size string, need to retrieve the string value.
1698 
1699  // string attribute values
1700  vector<char> temp_buf;
1701  temp_buf.resize(total_bytes);
1702  if (H5Aread(attr_id, atype_id, &temp_buf[0]) < 0){
1703  H5Sclose(aspace_id);
1704  throw InternalErr(__FILE__,__LINE__,"Cannot read the attribute in the H5Aiterate2 call back function");
1705  }
1706  string temp_buf_string(temp_buf.begin(),temp_buf.end());
1707  total_vstring = temp_buf_string.substr(0,total_bytes);
1708 
1709  // Note: we need to remove the string pad or term to find DIMENSION_SCALE.
1710  if(str_pad != H5T_STR_ERROR)
1711  total_vstring = total_vstring.substr(0,total_vstring.size()-1);
1712  }
1713 
1714  // Close attribute data space ID.
1715  if(aspace_id != -1)
1716  H5Sclose(aspace_id);
1717  if(total_vstring == "DIMENSION_SCALE"){
1718  (*countp)++;
1719  }
1720 #endif
1721 
1722  }
1723  catch(...) {
1724  if(atype_id != -1)
1725  H5Tclose(atype_id);
1726  if(attr_id != -1)
1727  H5Aclose(attr_id);
1728  throw;
1729  }
1730 
1731  // Close IDs.
1732  if(atype_id != -1)
1733  H5Tclose(atype_id);
1734  if(attr_id != -1)
1735  H5Aclose(attr_id);
1736 
1737  return 0;
1738 }
1739 
1740 
1748 void obtain_dimnames(hid_t dset,int ndims, DS_t *dt_inst_ptr) {
1749 
1750  htri_t has_dimension_list = -1;
1751 
1752  string dimlist_name = "DIMENSION_LIST";
1753  has_dimension_list = H5Aexists(dset,dimlist_name.c_str());
1754 
1755  if(has_dimension_list > 0 && ndims > 0) {
1756 
1757  hobj_ref_t rbuf;
1758  vector<hvl_t> vlbuf;
1759  vlbuf.resize(ndims);
1760 
1761  hid_t attr_id = -1;
1762  hid_t atype_id = -1;
1763  hid_t amemtype_id = -1;
1764  hid_t aspace_id = -1;
1765  hid_t ref_dset = -1;
1766 
1767  try {
1768  attr_id = H5Aopen(dset,dimlist_name.c_str(),H5P_DEFAULT);
1769  if (attr_id <0 ) {
1770  string msg = "Cannot open the attribute " + dimlist_name + " of HDF5 dataset "+ string(dt_inst_ptr->name);
1771  throw InternalErr(__FILE__, __LINE__, msg);
1772  }
1773 
1774  atype_id = H5Aget_type(attr_id);
1775  if (atype_id <0) {
1776  string msg = "Cannot get the datatype of the attribute " + dimlist_name + " of HDF5 dataset "+ string(dt_inst_ptr->name);
1777  throw InternalErr(__FILE__, __LINE__, msg);
1778  }
1779 
1780  amemtype_id = H5Tget_native_type(atype_id, H5T_DIR_ASCEND);
1781  if (amemtype_id < 0) {
1782  string msg = "Cannot get the memory datatype of the attribute " + dimlist_name + " of HDF5 dataset "+ string(dt_inst_ptr->name);
1783  throw InternalErr(__FILE__, __LINE__, msg);
1784 
1785  }
1786 
1787  if (H5Aread(attr_id,amemtype_id,&vlbuf[0]) <0) {
1788  string msg = "Cannot obtain the referenced object for the variable " + string(dt_inst_ptr->name);
1789  throw InternalErr(__FILE__, __LINE__, msg);
1790  }
1791 
1792  vector<char> objname;
1793 
1794  // The dimension names of variables will be the HDF5 dataset names dereferenced from the DIMENSION_LIST attribute.
1795  for (int i = 0; i < ndims; i++) {
1796 
1797  if(vlbuf[i].p == NULL) {
1798  stringstream sindex ;
1799  sindex <<i;
1800  string msg = "For variable " + string(dt_inst_ptr->name) + "; ";
1801  msg = msg + "the dimension of which the index is "+ sindex.str() + " doesn't exist. ";
1802  throw InternalErr(__FILE__, __LINE__, msg);
1803  }
1804 
1805  rbuf =((hobj_ref_t*)vlbuf[i].p)[0];
1806 
1807  // Note: TODO: H5Rget_name may be used to replace H5RDEREFERENCE and H5Iget_name in the future. KY 2016-06-28
1808  if ((ref_dset = H5RDEREFERENCE(attr_id, H5R_OBJECT, &rbuf)) < 0) {
1809  string msg = "Cannot dereference from the DIMENSION_LIST attribute for the variable " + string(dt_inst_ptr->name);
1810  throw InternalErr(__FILE__, __LINE__, msg);
1811  }
1812 
1813  ssize_t objnamelen = -1;
1814  if ((objnamelen= H5Iget_name(ref_dset,NULL,0))<=0) {
1815  string msg = "Cannot obtain the dimension name length for the variable " + string(dt_inst_ptr->name);
1816  throw InternalErr(__FILE__,__LINE__,msg);
1817  }
1818 
1819  objname.resize(objnamelen+1);
1820  if ((objnamelen= H5Iget_name(ref_dset,&objname[0],objnamelen+1))<=0) {
1821  H5Dclose(ref_dset);
1822  string msg = "Cannot obtain the dimension name for the variable " + string(dt_inst_ptr->name);
1823  throw InternalErr(__FILE__,__LINE__,msg);
1824  }
1825 
1826  string objname_str = string(objname.begin(),objname.end());
1827 
1828  // Must trim the string delimter.
1829  string trim_objname = objname_str.substr(0,objnamelen);
1830  // Need to save the dimension names without the path
1831 
1832  dt_inst_ptr->dimnames.push_back(trim_objname.substr(trim_objname.find_last_of("/")+1));
1833  dt_inst_ptr->dimnames_path.push_back(trim_objname);
1834 
1835  if(H5Dclose(ref_dset)<0) {
1836  throw InternalErr(__FILE__,__LINE__,"Cannot close the HDF5 dataset in the function obtain_dimnames().");
1837  }
1838  objname.clear();
1839  }// for (vector<Dimension *>::iterator ird is var->dims.begin()
1840  if(vlbuf.empty()== false) {
1841 
1842  if ((aspace_id = H5Aget_space(attr_id)) < 0) {
1843  string msg = "Cannot close the HDF5 attribute space successfully for <DIMENSION_LIST> of the variable "+string(dt_inst_ptr->name);
1844  throw InternalErr(__FILE__,__LINE__,msg);
1845  }
1846 
1847  if (H5Dvlen_reclaim(amemtype_id,aspace_id,H5P_DEFAULT,(void*)&vlbuf[0])<0) {
1848  throw InternalErr(__FILE__,__LINE__,"Cannot reclaim the variable length memory in the function obtain_dimnames()");
1849  }
1850 
1851  H5Sclose(aspace_id);
1852 
1853  }
1854 
1855  H5Tclose(atype_id);
1856  H5Tclose(amemtype_id);
1857  H5Aclose(attr_id);
1858 
1859  }
1860 
1861  catch(...) {
1862 
1863  if(atype_id != -1)
1864  H5Tclose(atype_id);
1865 
1866  if(amemtype_id != -1)
1867  H5Tclose(amemtype_id);
1868 
1869  if(aspace_id != -1)
1870  H5Sclose(aspace_id);
1871 
1872  if(attr_id != -1)
1873  H5Aclose(attr_id);
1874 
1875  throw;
1876  }
1877 
1878  }
1879  return ;
1880 }
1881 
1882 void write_vlen_str_attrs(hid_t attr_id,hid_t ty_id, DSattr_t * attr_inst_ptr,D4Attribute *d4_attr, AttrTable* d2_attr,bool is_dap4){
1883 
1884  BESDEBUG("h5","attribute name " << attr_inst_ptr->name <<endl);
1885  BESDEBUG("h5","attribute size " <<attr_inst_ptr->need <<endl);
1886  BESDEBUG("h5","attribute type size " <<(int)(H5Tget_size(ty_id))<<endl);
1887 
1888  hid_t temp_space_id = H5Aget_space(attr_id);
1889  BESDEBUG("h5","attribute calculated size "<<(int)(H5Tget_size(ty_id)) *(int)(H5Sget_simple_extent_npoints(temp_space_id)) <<endl);
1890  if(temp_space_id <0) {
1891  H5Tclose(ty_id);
1892  H5Aclose(attr_id);
1893  if(d4_attr)
1894  delete d4_attr;
1895  throw InternalErr(__FILE__, __LINE__, "unable to read HDF5 attribute data");
1896  }
1897 
1898  vector<char> temp_buf;
1899  // Variable length string attribute values only store pointers of the actual string value.
1900  temp_buf.resize((size_t)attr_inst_ptr->need);
1901 
1902  if (H5Aread(attr_id, ty_id, &temp_buf[0]) < 0) {
1903  H5Tclose(ty_id);
1904  H5Aclose(attr_id);
1905  H5Sclose(temp_space_id);
1906  if(d4_attr)
1907  delete d4_attr;
1908  throw InternalErr(__FILE__, __LINE__, "unable to read HDF5 attribute data");
1909  }
1910 
1911  char *temp_bp;
1912  temp_bp = &temp_buf[0];
1913  char* onestring;
1914  for (unsigned int temp_i = 0; temp_i <attr_inst_ptr->nelmts; temp_i++) {
1915 
1916  // This line will assure that we get the real variable length string value.
1917  onestring =*(char **)temp_bp;
1918 
1919  // Change the C-style string to C++ STD string just for easy appending the attributes in DAP.
1920  if (onestring !=NULL) {
1921  string tempstring(onestring);
1922  if(true == is_dap4)
1923  d4_attr->add_value(tempstring);
1924  else
1925  d2_attr->append_attr(attr_inst_ptr->name,"String",tempstring);
1926  }
1927 
1928  temp_bp +=H5Tget_size(ty_id);
1929  }
1930  if (temp_buf.empty() != true) {
1931 
1932  // Reclaim any VL memory if necessary.
1933  herr_t ret_vlen_claim;
1934  ret_vlen_claim = H5Dvlen_reclaim(ty_id,temp_space_id,H5P_DEFAULT,&temp_buf[0]);
1935  if(ret_vlen_claim < 0){
1936  H5Tclose(ty_id);
1937  H5Aclose(attr_id);
1938  H5Sclose(temp_space_id);
1939  if(d4_attr)
1940  delete d4_attr;
1941  throw InternalErr(__FILE__, __LINE__, "Cannot reclaim the memory buffer of the HDF5 variable length string.");
1942  }
1943 
1944  temp_buf.clear();
1945  }
1946  H5Sclose(temp_space_id);
1947 }
1948 
1949 bool check_str_attr_value(hid_t attr_id,hid_t atype_id,const string & value_to_compare,bool check_substr) {
1950 
1951  bool ret_value = false;
1952 
1953  H5T_str_t str_pad = H5Tget_strpad(atype_id);
1954  if(str_pad == H5T_STR_ERROR)
1955  throw InternalErr(__FILE__, __LINE__, "Fail to obtain string pad.");
1956 
1957  hid_t aspace_id = -1;
1958  aspace_id = H5Aget_space(attr_id);
1959  if(aspace_id < 0)
1960  throw InternalErr(__FILE__, __LINE__, "Fail to obtain attribute space.");
1961 
1962  int ndims = H5Sget_simple_extent_ndims(aspace_id);
1963  if(ndims < 0) {
1964  H5Sclose(aspace_id);
1965  throw InternalErr(__FILE__, __LINE__, "Fail to obtain number of dimensions.");
1966  }
1967 
1968  hsize_t nelmts = 1;
1969 
1970  // if it is a scalar attribute, just define number of elements to be 1.
1971  if (ndims != 0) {
1972 
1973  vector<hsize_t> asize;
1974  asize.resize(ndims);
1975  if (H5Sget_simple_extent_dims(aspace_id, &asize[0], NULL)<0) {
1976  H5Sclose(aspace_id);
1977  throw InternalErr(__FILE__, __LINE__, "Fail to obtain the dimension info.");
1978  }
1979 
1980  // Return ndims and size[ndims].
1981  for (int j = 0; j < ndims; j++)
1982  nelmts *= asize[j];
1983  } // if(ndims != 0)
1984 
1985  size_t ty_size = H5Tget_size(atype_id);
1986  if (0 == ty_size) {
1987  H5Sclose(aspace_id);
1988  throw InternalErr(__FILE__, __LINE__, "Fail to obtain the type size.");
1989  }
1990 
1991  size_t total_bytes = nelmts * ty_size;
1992  string total_vstring ="";
1993  if(H5Tis_variable_str(atype_id) > 0) {
1994 
1995  // Variable length string attribute values only store pointers of the actual string value.
1996  vector<char> temp_buf;
1997  temp_buf.resize(total_bytes);
1998 
1999  if (H5Aread(attr_id, atype_id, &temp_buf[0]) < 0){
2000  H5Sclose(aspace_id);
2001  throw InternalErr(__FILE__,__LINE__,"Fail to read the attribute.");
2002  }
2003 
2004  char *temp_bp = NULL;
2005  temp_bp = &temp_buf[0];
2006  char* onestring = NULL;
2007 
2008  for (unsigned int temp_i = 0; temp_i <nelmts; temp_i++) {
2009 
2010  // This line will assure that we get the real variable length string value.
2011  onestring =*(char **)temp_bp;
2012 
2013  if(onestring!= NULL)
2014  total_vstring +=string(onestring);
2015 
2016  // going to the next value.
2017  temp_bp +=ty_size;
2018  }
2019 
2020  if ((&temp_buf[0]) != NULL) {
2021  // Reclaim any VL memory if necessary.
2022  if (H5Dvlen_reclaim(atype_id,aspace_id,H5P_DEFAULT,&temp_buf[0]) < 0) {
2023  H5Sclose(aspace_id);
2024  throw InternalErr(__FILE__,__LINE__,"Fail to reclaim VL memory.");
2025  }
2026  }
2027 
2028  }
2029  else {// Fixed-size string, need to retrieve the string value.
2030 
2031  // string attribute values
2032  vector<char> temp_buf;
2033  temp_buf.resize(total_bytes);
2034  if (H5Aread(attr_id, atype_id, &temp_buf[0]) < 0){
2035  H5Sclose(aspace_id);
2036  throw InternalErr(__FILE__,__LINE__,"Fail to read the attribute.");
2037  }
2038  string temp_buf_string(temp_buf.begin(),temp_buf.end());
2039  total_vstring = temp_buf_string.substr(0,total_bytes);
2040 
2041  // Note: we need to remove the string pad or term to find DIMENSION_SCALE.
2042  if(str_pad != H5T_STR_ERROR)
2043  total_vstring = total_vstring.substr(0,total_vstring.size()-1);
2044  }
2045 
2046  // Close attribute data space ID.
2047  if(aspace_id != -1)
2048  H5Sclose(aspace_id);
2049 
2050  if(false == check_substr) {
2051  if(total_vstring == value_to_compare)
2052  ret_value = true;
2053  }
2054  else {
2055  if(total_vstring.size()>=value_to_compare.size()) {
2056  if( 0 == total_vstring.compare(0,value_to_compare.size(),value_to_compare))
2057  ret_value = true;
2058  }
2059  }
2060  return ret_value;
2061 }
A class for handling all types of array in HDF5 for the default option.
This class provides a way to map HDF5 byte to DAP Byte for the default option.
A class for mapping HDF5 32-bit float to DAP for the default option.
A class for mapping HDF5 64-bit float to DAP for the default option.
A class for HDF5 signed 16 bit integer type.
This class provides a way to map HDF5 32 bit integer to DAP Int32 for the default option.
This class provides a way to map HDF5 Int64 to DAP Int64 for the default option.
This class provides a way to map HDF5 int8 to DAP Int8 for the default option.
include the entry functions to execute the handlers
This class that translates HDF5 string into DAP string for the default option.
This class converts HDF5 compound type into DAP structure for the default option.
This class provides a way to map unsigned HDF5 16 bit integer to DAP UInt16 for the default option.
This class provides a way to map unsigned HDF5 32 bit integer to DAP UInt32.
This class provides a way to map HDF5 uint64 to DAP UInt64 for the default option.
This class generates DAP URL type for the default option.
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:1451
void set_numelm(int nelms)
remembers number of elements in this array.
Definition: HDF5Array.cc:1455
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:1447
string print_attr(hid_t type, int loc, void *sm_buf)
Definition: h5get.cc:706
bool check_h5str(hid_t h5type)
Definition: h5get.cc:685
hid_t get_fileid(const char *filename)
Definition: h5get.cc:405
string get_dap_type(hid_t type, bool is_dap4)
Definition: h5get.cc:285
void close_fileid(hid_t fid)
Definition: h5get.cc:427
void obtain_dimnames(hid_t dset, int ndims, DS_t *dt_inst_ptr)
Definition: h5get.cc:1748
void get_dataset(hid_t pid, const string &dname, DS_t *dt_inst_ptr)
Definition: h5get.cc:435
hid_t get_attr_info(hid_t dset, int index, bool is_dap4, DSattr_t *attr_inst_ptr, bool *ignore_attr_ptr)
Definition: h5get.cc:84
const int DODS_MAX_RANK
Maximum number of dimensions in an array(default option only).
Definition: hdf5_handler.h:63
A structure for DDS generation.
Definition: hdf5_handler.h:71
char name[DODS_NAMELEN]
Name of HDF5 group or dataset.
Definition: hdf5_handler.h:73
A structure for DAS generation.
Definition: hdf5_handler.h:94
char name[DODS_NAMELEN]
Name of HDF5 group or dataset.
Definition: hdf5_handler.h:96
hsize_t nelmts
Number of elements.
Definition: hdf5_handler.h:104
hsize_t need
Memory space needed to hold nelmts type.
Definition: hdf5_handler.h:106