OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDF5CF.cc
Go to the documentation of this file.
1 // This file is part of the hdf5_handler implementing for the CF-compliant
2 // Copyright (c) 2011-2013 The HDF Group, Inc. and OPeNDAP, Inc.
3 //
4 // This is free software; you can redistribute it and/or modify it under the
5 // terms of the GNU Lesser General Public License as published by the Free
6 // Software Foundation; either version 2.1 of the License, or (at your
7 // option) any later version.
8 //
9 // This software is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 // License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 //
18 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
19 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
20 // Suite 203, Champaign, IL 61820
21 
36 
37 #include <sstream>
38 #include <algorithm>
39 #include <functional>
40 #include <climits>
41 #include "HDF5CF.h"
42 
43 
44 using namespace HDF5CF;
45 
46 
48 {
49 
50  if (this->fileid >= 0) {
51  if (this->rootid >= 0) {
52  for_each (this->groups.begin (), this->groups.end (),
53  delete_elem ());
54  for_each (this->vars.begin (), this->vars.end (),
55  delete_elem ());
56  for_each (this->root_attrs.begin (), this->root_attrs.end (),
57  delete_elem ());
58  H5Gclose(rootid);
59  }
60  //H5Fclose(fileid);
61  }
62 }
63 
65 {
66  for_each (this->attrs.begin (), this->attrs.end (),
67  delete_elem ());
68 }
69 
71 {
72  for_each (this->dims.begin (), this->dims.end (),
73  delete_elem ());
74  for_each (this->attrs.begin (), this->attrs.end (),
75  delete_elem ());
76 }
77 
79 {
80 }
81 
82 void
83 File::Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr)
84 throw(Exception) {
85 
86  // cerr <<"coming to Retrieve_H5_Info "<<endl;
87  hid_t root_id;
88  if ((root_id = H5Gopen(file_id,"/",H5P_DEFAULT))<0){
89  throw1 ("Cannot open the HDF5 root group " );
90  }
91  this->rootid =root_id;
92  try {
93  this->Retrieve_H5_Obj(root_id,"/",include_attr);
94  }
95  catch(...) {
96  throw;
97  }
98 
99  if (true == include_attr) {
100 
101  // Find the file(root group) attribute
102 
103  // Obtain the object type, such as group or dataset.
104  H5O_info_t oinfo;
105  int num_attrs = 0;
106 
107  if (H5Oget_info(root_id,&oinfo) < 0)
108  throw1( "Error obtaining the info for the root group");
109 
110  num_attrs = oinfo.num_attrs;
111  bool temp_unsup_attr_atype = false;
112 
113  for (int j = 0; j < num_attrs; j ++) {
114  Attribute * attr = new Attribute();
115  try {
116  this->Retrieve_H5_Attr_Info(attr,root_id,j, temp_unsup_attr_atype);
117  }
118  catch(...) {
119  delete attr;
120  throw;
121 
122  }
123  this->root_attrs.push_back(attr);
124  }
125 
126  this->unsupported_attr_dtype = temp_unsup_attr_atype;
127  }
128 }
129 
130 void
131 File::Retrieve_H5_Obj(hid_t grp_id,const char*gname, bool include_attr)
132 throw(Exception) {
133 
134  // Iterate through the file to see the members of the group from the root.
135  H5G_info_t g_info;
136  hsize_t nelems = 0;
137 
138  if (H5Gget_info(grp_id,&g_info) <0)
139  throw2 ("Counting hdf5 group elements error for ", gname);
140  nelems = g_info.nlinks;
141 
142  ssize_t oname_size = 0;
143  for (hsize_t i = 0; i < nelems; i++) {
144 
145  hid_t cgroup = -1;
146  hid_t cdset = -1;
147  //char *oname = NULL;
148  Group *group = NULL;
149  Var *var = NULL;
150  Attribute *attr = NULL;
151 
152  try {
153 
154  size_t dummy_name_len = 1;
155  // Query the length of object name.
156  oname_size =
157  H5Lget_name_by_idx(grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,NULL,
158  dummy_name_len, H5P_DEFAULT);
159  if (oname_size <= 0)
160  throw2("Error getting the size of the hdf5 object from the group: ", gname);
161 
162  // Obtain the name of the object
163  vector<char> oname;
164  oname.resize((size_t)oname_size+1);
165  //oname = new char[(size_t) oname_size + 1];
166 
167 
168  if (H5Lget_name_by_idx(grp_id,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,&oname[0],
169  (size_t)(oname_size+1), H5P_DEFAULT) < 0)
170  throw2("Error getting the hdf5 object name from the group: ",gname);
171 
172  // Check if it is the hard link or the soft link
173  H5L_info_t linfo;
174  if (H5Lget_info(grp_id,&oname[0],&linfo,H5P_DEFAULT)<0)
175  throw2 ("HDF5 link name error from ", gname);
176 
177  // We ignore soft link and external links in this release
178  if(H5L_TYPE_SOFT == linfo.type || H5L_TYPE_EXTERNAL == linfo.type)
179  continue;
180 
181  // Obtain the object type, such as group or dataset.
182  H5O_info_t oinfo;
183 
184  if (H5Oget_info_by_idx(grp_id, ".", H5_INDEX_NAME, H5_ITER_NATIVE,
185  i, &oinfo, H5P_DEFAULT)<0)
186  throw2( "Error obtaining the info for the object ",string(oname.begin(),oname.end()));
187 
188  H5O_type_t obj_type = oinfo.type;
189 
190  switch (obj_type) {
191 
192  case H5O_TYPE_GROUP: {
193 
194  // Obtain the full path name
195  string full_path_name;
196  string temp_oname(oname.begin(),oname.end());
197 
198 
199  full_path_name = ((string(gname) != "/")
200  ?(string(gname)+"/"+temp_oname.substr(0,temp_oname.size()-1)):("/"+temp_oname.substr(0,temp_oname.size()-1)));
201 
202  // cerr <<"Group full_path_name " <<full_path_name <<endl;
203 
204  cgroup = H5Gopen(grp_id, full_path_name.c_str(),H5P_DEFAULT);
205  if (cgroup < 0)
206  throw2( "Error opening the group ",full_path_name);
207 
208  group = new Group();
209  group->path = full_path_name;
210  group->newname = full_path_name;
211 
212 
213  if (true == include_attr) {
214 
215  int num_attrs = oinfo.num_attrs;
216  bool temp_unsup_attr_dtype = false;
217 
218  for (int j = 0; j < num_attrs; j ++) {
219 
220  attr = new Attribute();
221  Retrieve_H5_Attr_Info(attr,cgroup,j, temp_unsup_attr_dtype);
222  group->attrs.push_back(attr);
223  attr = NULL;
224  }
225 
226  group->unsupported_attr_dtype = temp_unsup_attr_dtype;
227  }
228  this->groups.push_back(group);
229  Retrieve_H5_Obj(cgroup,full_path_name.c_str(),include_attr);
230  H5Gclose(cgroup);
231  }
232 
233  break;
234  case H5O_TYPE_DATASET:{
235 
236  // cerr<<"Coming to the dataset full_path " <<endl;
237  // Obtain the absolute path of the HDF5 dataset
238 
239  // string full_path_name = ((string(gname) != "/")
240  // ?(string(gname)+"/"+string(oname)):("/"+string(oname)));
241  // string full_path_name = string(gname) + "/" + string(oname);
242  //cerr<<"dataset full_path "<<full_path_name <<endl;
243  string temp_oname(oname.begin(),oname.end());
244  string full_path_name = ((string(gname) != "/")
245  ?(string(gname)+"/"+temp_oname.substr(0,temp_oname.size()-1)):("/"+temp_oname.substr(0,temp_oname.size()-1)));
246 
247 
248  var = new Var();
249  var->name = temp_oname.substr(0,temp_oname.size()-1);
250  var->fullpath = full_path_name;
251  var->newname = full_path_name;
252 
253  //cerr<<"variable path" <<var->fullpath <<endl;
254 
255  cdset = H5Dopen(grp_id, full_path_name.c_str(),H5P_DEFAULT);
256  if (cdset < 0){
257  throw2( "Error opening the HDF5 dataset ",full_path_name);
258  }
259 
260  bool temp_unsup_var_dtype = false;
261  Retrieve_H5_VarType(var,cdset,full_path_name,temp_unsup_var_dtype);
262 
263  if (!this->unsupported_var_dtype && temp_unsup_var_dtype)
264  this->unsupported_var_dtype = true;
265 
266  bool temp_unsup_var_dspace = false;
267 
268  Retrieve_H5_VarDim(var,cdset,full_path_name,temp_unsup_var_dspace);
269 
270  if (!this->unsupported_var_dspace && temp_unsup_var_dspace)
271  this->unsupported_var_dspace = true;
272 
273  if (true == include_attr) {
274 
275  int num_attrs = oinfo.num_attrs;
276  bool temp_unsup_attr_dtype = false;
277 
278  for (int j = 0; j < num_attrs; j ++) {
279 
280  attr = new Attribute();
281 
282  Retrieve_H5_Attr_Info(attr,cdset,j, temp_unsup_attr_dtype);
283  var->attrs.push_back(attr);
284  attr = NULL;
285  }
286 
287  var->unsupported_attr_dtype = temp_unsup_attr_dtype;
288  }
289 
290  this->vars.push_back(var);
291  H5Dclose(cdset);
292  }
293  break;
294 
295  case H5O_TYPE_NAMED_DATATYPE:
296 
297  // ignore the named datatype
298  break;
299  default:
300  break;
301  }
302  } // try
303  catch(...) {
304 
305  if (attr != NULL) {
306  delete attr;
307  attr = NULL;
308  }
309 
310  if (var != NULL) {
311  delete var;
312  var = NULL;
313  }
314 
315  if (group != NULL) {
316  delete group;
317  group = NULL;
318  }
319 
320  if (cgroup !=-1)
321  H5Gclose(cgroup);
322 
323  if (cdset != -1)
324  H5Dclose(cdset);
325 
326  throw;
327 
328  } // catch
329  } // for (hsize_t i = 0; i < nelems; i++)
330 
331 }
332 
333 void
334 File:: Retrieve_H5_VarType(Var *var, hid_t dset_id, const string & varname,bool &unsup_var_dtype)
335 throw(Exception){
336 
337  hid_t ty_id = -1;
338 
339  // Obtain the data type of the variable.
340  if ((ty_id = H5Dget_type(dset_id)) < 0)
341  throw2("unable to obtain hdf5 datatype for the dataset ",varname);
342 
343  // The following datatype class and datatype will not be supported for the CF option.
344  // H5T_TIME, H5T_BITFIELD
345  // H5T_OPAQUE, H5T_ENUM
346  // H5T_REFERENCE, H5T_COMPOUND
347  // H5T_VLEN,H5T_ARRAY
348  // 64-bit integer
349 
350  // Note: H5T_REFERENCE H5T_COMPOUND and H5T_ARRAY can be mapped to DAP2 DDS for the default option.
351  // H5T_COMPOUND, H5T_ARRAY can be mapped to DAP2 DAS for the default option.
352  // 1-D variable length of string can also be mapped for the CF option..
353  // The variable length string class is H5T_STRING rather than H5T_VLEN,
354  // We also ignore the mapping of integer 64 bit since DAP2 doesn't
355  // support 64-bit integer. In theory, DAP2 doesn't support long double
356  // (128-bit or 92-bit floating point type).
357  //
358 
359  var->dtype = HDF5CFUtil::H5type_to_H5DAPtype(ty_id);
360  if (false == HDF5CFUtil::cf_strict_support_type(var->dtype))
361  unsup_var_dtype = true;
362 
363  H5Tclose(ty_id);
364 }
365 
366 void
367 File:: Retrieve_H5_VarDim(Var *var, hid_t dset_id, const string & varname, bool &unsup_var_dspace)
368 throw(Exception){
369 
370 
371  vector<hsize_t> dsize;
372  vector<hsize_t> maxsize;
373 
374  hid_t dspace_id = -1;
375  hid_t ty_id = -1;
376 
377  try {
378  if ((dspace_id = H5Dget_space(dset_id)) < 0)
379  throw2("Cannot get hdf5 dataspace id for the variable ",varname);
380 
381  H5S_class_t space_class = H5S_NO_CLASS;
382  if ((space_class = H5Sget_simple_extent_type(dspace_id)) < 0)
383  throw2("Cannot obtain the HDF5 dataspace class for the variable ",varname);
384 
385  if (H5S_NULL == space_class)
386  unsup_var_dspace = true;
387  else {
388  // Note: currently we only support the string scalar space dataset.
389  // In the future, other atomic datatype should be supported. KY 2012-5-21
390  if (H5S_SCALAR == space_class) {
391 
392  // Obtain the data type of the variable.
393  if ((ty_id = H5Dget_type(dset_id)) < 0)
394  throw2("unable to obtain the hdf5 datatype for the dataset ",varname);
395 
396  if (H5T_STRING != H5Tget_class(ty_id))
397  unsup_var_dspace = true;
398 
399  H5Tclose(ty_id);
400  }
401 
402  if (false == unsup_var_dspace) {
403 
404  int ndims = H5Sget_simple_extent_ndims(dspace_id);
405  if (ndims < 0)
406  throw2("Cannot get the hdf5 dataspace number of dimension for the variable ",varname);
407 
408  var->rank = ndims;
409  if (ndims !=0) {
410  //dsize = new hsize_t[ndims];
411  //maxsize = new hsize_t[ndims];
412  dsize.resize(ndims);
413  maxsize.resize(ndims);
414  }
415 
416  // DAP applications don't care about the unlimited dimensions
417  // since the applications only care about retrieving the data.
418  // So we don't check the maxsize to see if it is the unlimited dimension
419  // variable.
420  if (H5Sget_simple_extent_dims(dspace_id, &dsize[0], &maxsize[0])<0)
421  throw2("Cannot obtain the dim. info for the variable ", varname);
422 
423  // dsize can be 0. Currently DAP2 doesn't support this. So ignore now. KY 2012-5-21
424  for (int i = 0; i < ndims; i++) {
425  if (0 == dsize[i]) {
426  unsup_var_dspace = true;
427  break;
428  }
429  }
430 
431  if (false == unsup_var_dspace) {
432  for (int i=0; i<ndims; i++) {
433  Dimension * dim = new Dimension(dsize[i]);
434  var->dims.push_back(dim);
435  }
436  }
437  }
438  }
439 
440  var->unsupported_dspace = unsup_var_dspace;
441 
442  H5Sclose(dspace_id);
443  }
444 
445  catch (...) {
446 
447  if (dspace_id != -1)
448  H5Sclose(dspace_id);
449 
450  if (ty_id != -1)
451  H5Tclose(ty_id);
452 
453  throw;
454  //throw2("Cannot obtain the dimension information for the dataset ",varname);
455  }
456 
457 }
458 
459 
460 void
461 File:: Retrieve_H5_Attr_Info(Attribute * attr, hid_t obj_id,const int j, bool &unsup_attr_dtype)
462 throw(Exception)
463 
464 {
465 
466  hid_t attrid = -1;
467  hid_t ty_id = -1;
468  hid_t aspace_id = -1;
469  hid_t memtype = -1;
470 
471 
472  try {
473 
474  // Obtain the attribute ID.
475  if ((attrid = H5Aopen_by_idx(obj_id, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,(hsize_t)j, H5P_DEFAULT, H5P_DEFAULT)) < 0)
476  throw1("Unable to open attribute by index " );
477 
478 
479  // Obtain the size of attribute name.
480  ssize_t name_size = H5Aget_name(attrid, 0, NULL);
481  if (name_size < 0)
482  throw1("Unable to obtain the size of the hdf5 attribute name " );
483 
484  //attr_name = new char[name_size+1];
485  string attr_name;
486  attr_name.resize(name_size+1);
487 
488  // Obtain the attribute name.
489  if ((H5Aget_name(attrid, name_size+1, &attr_name[0])) < 0)
490  throw1("unable to obtain the hdf5 attribute name ");
491 
492  // Obtain the type of the attribute.
493  if ((ty_id = H5Aget_type(attrid)) < 0)
494  throw2("unable to obtain hdf5 datatype for the attribute ",attr_name);
495 
496  // The following datatype class and datatype will not be supported for the CF option.
497  // H5T_TIME, H5T_BITFIELD
498  // H5T_OPAQUE, H5T_ENUM
499  // H5T_REFERENCE, H5T_COMPOUND
500  // H5T_VLEN,H5T_ARRAY
501  // 64-bit integer
502 
503  // Note: H5T_REFERENCE H5T_COMPOUND and H5T_ARRAY can be mapped to DAP2 DDS for the default option.
504  // H5T_COMPOUND, H5T_ARRAY can be mapped to DAP2 DAS for the default option.
505  // 1-D variable length of string can also be mapped for the CF option..
506  // The variable length string class is H5T_STRING rather than H5T_VLEN,
507  // We also ignore the mapping of integer 64 bit since DAP2 doesn't
508  // support 64-bit integer. In theory, DAP2 doesn't support long double
509  // (128-bit or 92-bit floating point type).
510  //
511  attr->dtype = HDF5CFUtil::H5type_to_H5DAPtype(ty_id);
512  if (false == HDF5CFUtil::cf_strict_support_type(attr->dtype))
513  unsup_attr_dtype = true;
514 
515  if ((aspace_id = H5Aget_space(attrid)) < 0)
516  throw2("Cannot get hdf5 dataspace id for the attribute ",attr_name);
517 
518  int ndims = H5Sget_simple_extent_ndims(aspace_id);
519  if (ndims < 0)
520  throw2("Cannot get the hdf5 dataspace number of dimension for attribute ",attr_name);
521 
522  hsize_t nelmts = 1;
523  // if it is a scalar attribute, just define number of elements to be 1.
524  if (ndims != 0) {
525 
526  vector<hsize_t> asize;
527  vector<hsize_t> maxsize;
528  asize.resize(ndims);
529  maxsize.resize(ndims);
530 
531  // DAP applications don't care about the unlimited dimensions
532  // since the applications only care about retrieving the data.
533  // So we don't check the maxsize to see if it is the unlimited dimension
534  // attribute.
535  if (H5Sget_simple_extent_dims(aspace_id, &asize[0], &maxsize[0])<0)
536  throw2("Cannot obtain the dim. info for the attribute ", attr_name);
537 
538  // Return ndims and size[ndims].
539  for (int j = 0; j < ndims; j++)
540  nelmts *= asize[j];
541  } // if(ndims != 0)
542 
543  size_t ty_size = H5Tget_size(ty_id);
544  if (0 == ty_size )
545  throw2("Cannot obtain the dtype size for the attribute ",attr_name);
546 
547 
548  memtype = H5Tget_native_type(ty_id, H5T_DIR_ASCEND);
549  if (memtype < 0)
550  throw2("Cannot obtain the memory datatype for the attribute ",attr_name);
551 
552  //attr->attr_mtypeid = memtype;
553  // Store the name and the count
554  string temp_aname(attr_name.begin(),attr_name.end());
555  attr->name = temp_aname.substr(0,temp_aname.size()-1);
556  attr->newname = attr->name;
557  attr->count = nelmts;
558 
559 
560  // Release HDF5 resources.
561  H5Tclose(ty_id);
562  H5Tclose(memtype);
563  H5Sclose(aspace_id);
564  H5Aclose(attrid);
565 
566 
567  } // try
568  catch(...) {
569 
570  if(ty_id != -1)
571  H5Tclose(ty_id);
572 
573  if(memtype != -1)
574  H5Tclose(memtype);
575 
576  if(aspace_id != -1)
577  H5Sclose(aspace_id);
578 
579  if(attrid != -1)
580  H5Aclose(attrid);
581 
582  throw;
583  }
584 
585 }
586 
587 void
589 {
590 
591  for (vector<Attribute *>::iterator ira = this->root_attrs.begin();
592  ira != this->root_attrs.end(); ++ira)
593  Retrieve_H5_Attr_Value(*ira,"/");
594 
595  for (vector<Group *>::iterator irg = this->groups.begin();
596  irg != this->groups.end(); ++irg) {
597  for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin();
598  ira != (*irg)->attrs.end(); ++ira) {
599  Retrieve_H5_Attr_Value(*ira,(*irg)->path);
600  }
601  }
602 
603  for (vector<Var *>::iterator irv = this->vars.begin();
604  irv != this->vars.end(); ++irv) {
605  for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin();
606  ira != (*irv)->attrs.end(); ++ira) {
607  Retrieve_H5_Attr_Value(*ira,(*irv)->fullpath);
608  }
609  }
610 }
611 
612 
613 void
614 File::Retrieve_H5_Attr_Value( Attribute *attr,string obj_name)
615 throw(Exception)
616 {
617 
618  // Define HDF5 object Ids.
619  hid_t obj_id = -1;
620  hid_t attr_id = -1;
621  hid_t ty_id = -1;
622  hid_t memtype_id = -1;
623  hid_t aspace_id = -1;
624 
625 
626  try {
627 
628  // Open the object that hold this attribute
629  obj_id = H5Oopen(this->fileid,obj_name.c_str(),H5P_DEFAULT);
630  if (obj_id < 0)
631  throw2("Cannot open the object ",obj_name);
632 
633  attr_id = H5Aopen(obj_id,(attr->name).c_str(),H5P_DEFAULT);
634  if (attr_id <0 )
635  throw4("Cannot open the attribute ",attr->name," of object ",obj_name);
636 
637  ty_id = H5Aget_type(attr_id);
638  if (ty_id <0)
639  throw4("Cannot obtain the datatype of the attribute ",attr->name," of object ",obj_name);
640 
641  memtype_id = H5Tget_native_type(ty_id, H5T_DIR_ASCEND);
642 
643  if (memtype_id < 0)
644  throw2("Cannot obtain the memory datatype for the attribute ",attr->name);
645 
646 
647  size_t ty_size = H5Tget_size(memtype_id);
648  if (0 == ty_size )
649  throw4("Cannot obtain the dtype size for the attribute ",attr->name, " of object ",obj_name);
650 
651  size_t total_bytes = attr->count * ty_size;
652 
653  // We have to handle variable length string differently.
654  if (H5VSTRING == attr->dtype) {
655 
656  // Variable length string attribute values only store pointers of the actual string value.
657  vector<char> temp_buf;
658  temp_buf.resize(total_bytes);
659 
660  if (H5Aread(attr_id, memtype_id, &temp_buf[0]) < 0)
661  throw4("Cannot obtain the dtype size for the attribute ",attr->name, " of object ",obj_name);
662 
663  char *temp_bp = NULL;
664  temp_bp = &temp_buf[0];
665  char* onestring = NULL;
666  string total_vstring ="";
667 
668  attr->strsize.resize(attr->count);
669 
670  for (unsigned int temp_i = 0; temp_i <attr->count; temp_i++) {
671 
672  // This line will assure that we get the real variable length string value.
673  onestring =*(char **)temp_bp;
674  if(onestring!= NULL) {
675  total_vstring +=string(onestring);
676  attr->strsize[temp_i] = (string(onestring)).size();
677  }
678  else attr->strsize[temp_i] = 0;
679 
680  // going to the next value.
681  temp_bp +=ty_size;
682  }
683  if (&temp_buf[0] != NULL) {
684 
685  aspace_id = H5Aget_space(attr_id);
686  if (aspace_id < 0)
687  throw4("Cannot obtain space id for ",attr->name, " of object ",obj_name);
688 
689  // Reclaim any VL memory if necessary.
690  if (H5Dvlen_reclaim(memtype_id,aspace_id,H5P_DEFAULT,&temp_buf[0]) < 0)
691  throw4("Cannot reclaim VL memory for ",attr->name, " of object ",obj_name);
692 
693  H5Sclose(aspace_id);
694  }
695 
697  throw4("Error to obtain the VL string type for attribute ",attr->name, " of object ",obj_name);
698 
699  attr->value.resize(total_vstring.size());
700 
701  copy(total_vstring.begin(),total_vstring.end(),attr->value.begin());
702 
703  }
704  else {
705 
706  if (attr->dtype == H5FSTRING) {
707  attr->fstrsize = ty_size;
708  }
709 
710  attr->value.resize(total_bytes);
711 
712  // Read HDF5 attribute data.
713  if (H5Aread(attr_id, memtype_id, (void *) &attr->value[0]) < 0)
714  throw4("Cannot obtain the dtype size for the attribute ",attr->name, " of object ",obj_name);
715 
716  if (attr->dtype == H5FSTRING) {
717 
718  size_t sect_size = ty_size;
719  int num_sect = (total_bytes%sect_size==0)?(total_bytes/sect_size)
720  :(total_bytes/sect_size+1);
721  vector<size_t>sect_newsize;
722  sect_newsize.resize(num_sect);
723 
724  string total_fstring = string(attr->value.begin(),attr->value.end());
725 
726  string new_total_fstring = HDF5CFUtil::trim_string(memtype_id,total_fstring,
727  num_sect,sect_size,sect_newsize);
728  // cerr <<"The first new sect size is "<<sect_newsize[0] <<endl;
729  attr->value.resize(new_total_fstring.size());
730  copy(new_total_fstring.begin(),new_total_fstring.end(),attr->value.begin());
731  attr->strsize.resize(num_sect);
732  for (int temp_i = 0; temp_i <num_sect; temp_i ++)
733  attr->strsize[temp_i] = sect_newsize[temp_i];
734 
735  // cerr <<"new string value " <<string(attr->value.begin(), attr->value.end()) <<endl;
736 #if 0
737 for (int temp_i = 0; temp_i <num_sect; temp_i ++)
738  cerr <<"string new section size = " << attr->strsize[temp_i] <<endl;
739 #endif
740  }
741  }
742 
743  H5Tclose(memtype_id);
744  H5Tclose(ty_id);
745  H5Aclose(attr_id);
746  H5Oclose(obj_id);
747 
748  }
749 
750  catch(...) {
751 
752  if (memtype_id !=-1)
753  H5Tclose(memtype_id);
754 
755  if (ty_id != -1)
756  H5Tclose(ty_id);
757 
758  if (aspace_id != -1)
759  H5Sclose(aspace_id);
760 
761  if (attr_id != -1)
762  H5Aclose(attr_id);
763 
764  if (obj_id != -1)
765  H5Oclose(obj_id);
766 
767 
768  //throw1("Error in method File::Retrieve_H5_Attr_Value");
769  throw;
770  }
771 
772 }
773 
774 
775 
776 void File::Handle_Unsupported_Dtype(bool include_attr) throw(Exception) {
777 
778  // First the root attributes
779  if (true == include_attr) {
780  if (false == this->root_attrs.empty()) {
781  if (true == this->unsupported_attr_dtype) {
782  for (vector<Attribute *>::iterator ira = this->root_attrs.begin();
783  ira != this->root_attrs.end(); ++ira) {
784  H5DataType temp_dtype = (*ira)->getType();
785  if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype)) {
786  delete (*ira);
787  this->root_attrs.erase(ira);
788  ira--;
789  }
790  }
791  }
792  }
793 
794  // Then the group attributes
795  if (false == this->groups.empty()) {
796  for (vector<Group *>::iterator irg = this->groups.begin();
797  irg != this->groups.end(); ++irg) {
798  if (false == (*irg)->attrs.empty()) {
799  if (true == (*irg)->unsupported_attr_dtype) {
800  for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin();
801  ira != (*irg)->attrs.end(); ++ira) {
802  H5DataType temp_dtype = (*ira)->getType();
803  if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype)) {
804  delete (*ira);
805  (*irg)->attrs.erase(ira);
806  ira--;
807  }
808  }
809  }
810  }
811  }
812  }
813  }
814 
815  // Then the variable(HDF5 dataset) and the correponding attributes.
816  if (false == this->vars.empty()) {
817  if (true == include_attr) {
818  for (vector<Var *>::iterator irv = this->vars.begin();
819  irv != this->vars.end(); ++irv) {
820  if (false == (*irv)->attrs.empty()) {
821  if (true == (*irv)->unsupported_attr_dtype) {
822  for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin();
823  ira != (*irv)->attrs.end(); ++ira) {
824  H5DataType temp_dtype = (*ira)->getType();
825  if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype)) {
826  delete (*ira);
827  (*irv)->attrs.erase(ira);
828  ira--;
829  }
830  }
831  }
832  }
833  }
834  }
835  if (true == this->unsupported_var_dtype) {
836  // cerr <<"having unsupported variable datatype" <<endl;
837  for (vector<Var *>::iterator irv = this->vars.begin();
838  irv != this->vars.end(); ++irv) {
839  H5DataType temp_dtype = (*irv)->getType();
840  if (false == HDF5CFUtil::cf_strict_support_type(temp_dtype)) {
841  delete (*irv);
842  this->vars.erase(irv);
843  irv--;
844  }
845  }
846  }
847  }
848 }
849 
851 
852  // Then the variable(HDF5 dataset) and the correponding attributes.
853  if (false == this->vars.empty()) {
854  if (true == this->unsupported_var_dspace) {
855  for (vector<Var *>::iterator irv = this->vars.begin();
856  irv != this->vars.end(); ++irv) {
857  if (true == (*irv)->unsupported_dspace) {
858  delete (*irv);
859  this->vars.erase(irv);
860  irv--;
861  }
862  }
863  }
864  }
865 }
866 void File::Flatten_Obj_Name(bool include_attr) throw(Exception) {
867 
868  for (vector<Var *>::iterator irv = this->vars.begin();
869  irv != this->vars.end(); ++irv) {
870  (*irv)->newname = get_CF_string((*irv)->newname);
871 
872 //cerr<<"CF variable new name "<< (*irv)->newname <<endl;
873 
874  for (vector<Dimension *>::iterator ird = (*irv)->dims.begin();
875  ird != (*irv)->dims.end(); ++ird) {
876  (*ird)->newname = get_CF_string((*ird)->newname);
877  }
878  }
879 
880  if (true == include_attr) {
881 
882  for (vector<Attribute *>::iterator ira = this->root_attrs.begin();
883  ira != this->root_attrs.end(); ++ira){
884  (*ira)->newname = get_CF_string((*ira)->newname);
885  }
886 
887  for (vector<Group *>::iterator irg = this->groups.begin();
888  irg != this->groups.end(); ++irg) {
889  (*irg)->newname = get_CF_string((*irg)->newname);
890  for (vector<Attribute *>::iterator ira = (*irg)->attrs.begin();
891  ira != (*irg)->attrs.end(); ++ira) {
892  (*ira)->newname = get_CF_string((*ira)->newname);
893  }
894  }
895 
896  for (vector<Var *>::iterator irv = this->vars.begin();
897  irv != this->vars.end(); ++irv) {
898  for (vector<Attribute *>::iterator ira = (*irv)->attrs.begin();
899  ira != (*irv)->attrs.end(); ++ira) {
900  (*ira)->newname = get_CF_string((*ira)->newname);
901  }
902  }
903  } // if (true == include_attr)
904 }
905 
906 void File::Handle_Var_NameClashing(set<string>&objnameset ) throw(Exception) {
907 
908  Handle_General_NameClashing(objnameset,this->vars);
909 }
910 
911 void File::Handle_RootGroup_NameClashing(set<string> &objnameset ) throw(Exception) {
912 
913 
914  pair<set<string>::iterator,bool> setret;
915 
916 
917  // Now for DAS, we need to handle name clashings for
918  // DAS tables. Namely we need to make sure the global attribute
919  // table(HDF5_GLOBAL) and the attribute tables mapped from
920  // HDF5 groups will not have name clashings with the variable name
921  // lists. If having the name clashings, the global attribute table and the
922  // the attribute tables generated from the groups will be changed.
923  // The file attribute name clashing
924 
925  setret = objnameset.insert(FILE_ATTR_TABLE_NAME);
926  if (false == setret.second) {
927 
928  int clash_index = 1;
929  string fa_clash_name = FILE_ATTR_TABLE_NAME;
930  HDF5CFUtil::gen_unique_name(fa_clash_name,objnameset,clash_index);
931  FILE_ATTR_TABLE_NAME = fa_clash_name;
932  }
933 
934  // The group attribute name clashing
935  Handle_General_NameClashing(objnameset,this->groups);
936 
937 }
938 
940 
941  // Now handling the possible name clashings for attributes
942  // For attribute clashings, we only need to resolve the name clashings
943  // for attributes within each variable, file attributes and attributes
944  // within each group. The name clashings for attributes should be very rare.
945  // Potentially the checking and the correcting may be costly.
946  // This is another reason for special products, we may not even need to check
947  // the name clashings. KY 2011-12-24
948 
949  set<string>objnameset;
950 
951  // For root attributes
952  Handle_General_NameClashing(objnameset,this->root_attrs);
953 
954  // For group attributes
955  for (vector<Group *>::iterator irg = this->groups.begin();
956  irg != this->groups.end(); ++irg) {
957  objnameset.clear();
958  Handle_General_NameClashing(objnameset,(*irg)->attrs);
959  }
960 
961  // For variable attributes
962  for (vector<Var *>::iterator irv = this->vars.begin();
963  irv != this->vars.end(); ++irv) {
964  objnameset.clear();
965  Handle_General_NameClashing(objnameset,(*irv)->attrs);
966  }
967 }
968 
969 //class T must have member string newname
970 template<class T> void
971 File::Handle_General_NameClashing(set <string>&objnameset, vector<T*>& objvec) throw(Exception){
972 
973 
974 // set<string> objnameset;
975  pair<set<string>::iterator,bool> setret;
976  set<string>::iterator iss;
977 
978  vector<string> clashnamelist;
979  vector<string>::iterator ivs;
980 
981  map<int,int> cl_to_ol;
982  int ol_index = 0;
983  int cl_index = 0;
984 
985  /*class*/
986  typename vector<T*>::iterator irv;
987 
988  for (irv = objvec.begin(); irv != objvec.end(); ++irv) {
989  setret = objnameset.insert((*irv)->newname);
990  if (false == setret.second) {
991  clashnamelist.insert(clashnamelist.end(), (*irv)->newname);
992  cl_to_ol[cl_index] = ol_index;
993  cl_index++;
994  }
995  ol_index++;
996  }
997 
998  // Now change the clashed elements to unique elements;
999  // Generate the set which has the same size as the original vector.
1000  for (ivs=clashnamelist.begin(); ivs!=clashnamelist.end(); ivs++) {
1001  int clash_index = 1;
1002  string temp_clashname = *ivs +'_';
1003  HDF5CFUtil::gen_unique_name(temp_clashname,objnameset,clash_index);
1004  *ivs = temp_clashname;
1005  }
1006 
1007  // Now go back to the original vector, make it unique.
1008  for (unsigned int i =0; i <clashnamelist.size(); i++)
1009  objvec[cl_to_ol[i]]->newname = clashnamelist[i];
1010 
1011 }
1012 
1013 
1014 
1015 
1016 void File::Handle_GeneralObj_NameClashing(bool include_attr,set<string>& objnameset ) throw(Exception) {
1017 
1018  Handle_Var_NameClashing(objnameset);
1019  if (true == include_attr) {
1020  Handle_RootGroup_NameClashing(objnameset );
1021  Handle_Obj_AttrNameClashing();
1022  }
1023 }
1024 
1025 string
1027 {
1028 
1029  if(""==s) return s;
1030  string insertString(1,'_');
1031 
1032  // Always start with _ if the first character is not a letter
1033  if (true == isdigit(s[0]))
1034  s.insert(0,insertString);
1035 
1036  for(unsigned int i=0; i < s.length(); i++)
1037  if((false == isalnum(s[i])) && (s[i]!='_'))
1038  s[i]='_';
1039 
1040  return s;
1041 
1042 }
1043 void
1044 File:: Insert_One_NameSizeMap_Element( string name,hsize_t size) throw(Exception)
1045 {
1046  pair<map<string,hsize_t>::iterator,bool>mapret;
1047  mapret = dimname_to_dimsize.insert(pair<string,hsize_t>(name,size));
1048  if (false == mapret.second)
1049  throw4("The dimension name ",name," should map to ",size);
1050 
1051 }
1052 
1053 void
1054 File:: Insert_One_NameSizeMap_Element2(map<string,hsize_t>& name_to_size, string name,hsize_t size) throw(Exception)
1055 {
1056  pair<map<string,hsize_t>::iterator,bool>mapret;
1057  mapret = name_to_size.insert(pair<string,hsize_t>(name,size));
1058  if (false == mapret.second)
1059  throw4("The dimension name ",name," should map to ",size);
1060 
1061 }
1062 
1063 // For dimension names added by the handlers, by default,
1064 // Each dimension will have a unique dimension name. For example,
1065 // Int foo[100][200] will be Int foo[Fakedim1][Fakedim2]
1066 // If you have many variables, the dimension names may be too many.
1067 // To reduce numbers, we ASSUME that the dimension having the same
1068 // size shares the same dimension. In this way, the number of dimension names
1069 // will be reduced.
1070 // For example, Int foo2[100][300] will be Int foo2[Fakedim1][Fakedim3]
1071 // instead of foo2[Fakedim3][Fakedim4]. However, that may impose
1072 // another problem. Suppose Int Foosame[100][100] becomes
1073 // Int Foosame[FakeDim1][FakeDim1]. This doesn't make sense for some
1074 // applications. The fuction Adjust_Duplicate_FakeDim_Name will make sure
1075 // this case will not happen.
1076 void
1078 
1079  stringstream sfakedimindex;
1080  string fakedimstr = "FakeDim";
1081  pair<set<string>::iterator,bool> setret;
1082  map<hsize_t,string>::iterator im;
1083  pair<map<hsize_t,string>::iterator,bool>mapret;
1084 
1085  sfakedimindex << addeddimindex;
1086  string added_dimname = fakedimstr + sfakedimindex.str();
1087 
1088  // Build up the size to fakedim map.
1089  mapret = dimsize_to_fakedimname.insert(pair<hsize_t,string>(dim->size,added_dimname));
1090  if (false == mapret.second) { //The dim size exists, use the corresponding name.
1091  dim->name = dimsize_to_fakedimname[dim->size];
1092  dim->newname = dim->name;
1093  }
1094  else { // Insert this (dimsize,dimname) pair to dimsize_to_fakedimname map successfully.
1095  //First make sure this new dim name doesn't have name clashing
1096  // with previous dim names, after the checking, inserting to the
1097  // dimname list set.
1098  // dimnamelist is a private memeber of File.
1099  setret = dimnamelist.insert(added_dimname);
1100  if (false == setret.second) {
1101  int clash_index =1;
1102  string temp_clashname=added_dimname+'_';
1103  HDF5CFUtil::gen_unique_name(temp_clashname,dimnamelist,clash_index);
1104  dim->name = temp_clashname;
1105  dim->newname = dim->name;
1106  setret = dimnamelist.insert(dim->name);
1107  if(false == setret.second)
1108  throw2("Fail to insert the unique dimsizede name ", dim->name);
1109 
1110  // We have to adjust the dim. name of the dimsize_to_fakedimname map, since the
1111  // dimname has been updated for this size.
1112  dimsize_to_fakedimname.erase(dim->size);
1113  mapret = dimsize_to_fakedimname.insert(pair<hsize_t,string>(dim->size,dim->name));
1114  if (false == mapret.second)
1115  throw4("The dimension size ",dim->size," should map to ",dim->name);
1116  }// if(false == setret.second)
1117 
1118  // New dim name is inserted successfully, update the dimname_to_dimsize map.
1119  dim->name = added_dimname;
1120  dim->newname = dim->name;
1121  Insert_One_NameSizeMap_Element(dim->name,dim->size);
1122 
1123  // Increase the dimindex since the new dimname has been inserted.
1124  addeddimindex++;
1125  }// else
1126 }
1127 
1128 
1129 void
1131 
1132  // No need to adjust the dimsize_to_fakedimname map, only create a new Fakedim
1133  // The simplest way is to increase the dim index and resolve any name clashings with other dim names.
1134  // Note: No need to update the dimsize_to_dimname map since the original "FakeDim??" of this size
1135  // can be used as a dimension name of other variables. But we need to update the dimname_to_dimsize map
1136  // since this is a new dim name.
1137  stringstream sfakedimindex;
1138  pair<set<string>::iterator,bool> setret;
1139 
1140  addeddimindex++;
1141  sfakedimindex << addeddimindex;
1142  string added_dimname = "FakeDim" + sfakedimindex.str();
1143  setret = dimnamelist.insert(added_dimname);
1144  if (false == setret.second) {
1145  int clash_index =1;
1146  string temp_clashname=added_dimname+'_';
1147  HDF5CFUtil::gen_unique_name(temp_clashname,dimnamelist,clash_index);
1148  dim->name = temp_clashname;
1149  dim->newname = dim->name;
1150  setret = dimnamelist.insert(dim->name);
1151  if(false == setret.second)
1152  throw2("Fail to insert the unique dimsizede name ", dim->name);
1153  }
1154  dim->name = added_dimname;
1155  dim->newname = dim->name;
1156  Insert_One_NameSizeMap_Element(dim->name,dim->size);
1157 
1158  // Need to prepare for the next unique FakeDim.
1159  addeddimindex++;
1160 }
1161 
1162 void
1163 File:: Add_Str_Attr(Attribute* attr,const string &attrname, const string& strvalue) throw(Exception){
1164 
1165  attr->name = attrname;
1166  attr->newname = attr->name;
1167  attr->dtype = H5FSTRING;
1168  attr->count = 1;
1169  attr->fstrsize = strvalue.size();
1170  attr->strsize.resize(1);
1171  attr->strsize[0] = attr->fstrsize;
1172  attr->value.resize(strvalue.size());
1173  copy(strvalue.begin(),strvalue.end(),attr->value.begin());
1174 }
1175 
1176 void
1177 File:: Add_One_Float_Attr(Attribute* attr,const string &attrname, float float_value) throw(Exception){
1178  attr->name = attrname;
1179  attr->newname = attr->name;
1180  attr->dtype = H5FLOAT32;
1181  attr->count = 1;
1182  attr->value.resize(sizeof(float));
1183  memcpy(&(attr->value[0]),(void*)(&float_value),sizeof(float));
1184 }
1185 
1186 void
1188 
1189 
1190  char *pEnd;
1191  // string to long int number.
1192  long int num_sli = 0;
1193  if(attr->dtype != H5FSTRING)
1194  throw2("Currently we only convert fixed-size string to other datatypes. ", attr->name);
1195  if(attr->count != 1)
1196  throw4("The fixed-size string count must be 1 and the current count is ",attr->count, " for the attribute ",attr->name);
1197 
1198  Retrieve_H5_Attr_Value(attr,var->fullpath);
1199  string attr_value;
1200  attr_value.resize(attr->value.size());
1201  copy(attr->value.begin(),attr->value.end(),attr_value.begin());
1202 
1203  switch(var->dtype) {
1204 
1205  case H5UCHAR:
1206  {
1207  num_sli = strtol(&(attr->value[0]),&pEnd,10);
1208  if(num_sli <0 || num_sli >UCHAR_MAX)
1209  throw5("Attribute type is unsigned char, the current attribute ",attr->name, " has the value ",num_sli, ". It is overflowed. ");
1210  else {
1211  unsigned char num_suc =(unsigned char)num_sli;
1212  attr->dtype = H5UCHAR;
1213  //attr->count = 1;
1214  attr->value.resize(sizeof(unsigned char));
1215  memcpy(&(attr->value[0]),(void*)(&num_suc),sizeof(unsigned char));
1216  }
1217 
1218  }
1219  break;
1220  case H5CHAR:
1221  {
1222  num_sli = strtol(&(attr->value[0]),&pEnd,10);
1223  if(num_sli <SCHAR_MIN || num_sli >SCHAR_MAX)
1224  throw5("Attribute type is signed char, the current attribute ",attr->name, " has the value ",num_sli, ". It is overflowed. ");
1225  else {
1226  char num_sc = (char)num_sli;
1227  attr->dtype = H5CHAR;
1228  //attr->count = 1;
1229  attr->value.resize(sizeof(char));
1230  memcpy(&(attr->value[0]),(void*)(&num_sc),sizeof(char));
1231  }
1232 
1233  }
1234  break;
1235  case H5INT16:
1236  {
1237  num_sli = strtol(&(attr->value[0]),&pEnd,10);
1238  if(num_sli <SHRT_MIN || num_sli >SHRT_MAX)
1239  throw5("Attribute type is 16-bit integer, the current attribute ",attr->name, " has the value ",num_sli, ". It is overflowed. ");
1240  else {
1241  short num_ss = (short)num_sli;
1242  attr->dtype = H5INT16;
1243  //attr->count = 1;
1244  attr->value.resize(sizeof(short));
1245  memcpy(&(attr->value[0]),(void*)(&num_ss),sizeof(short));
1246  }
1247 
1248 
1249  }
1250  break;
1251  case H5UINT16:
1252  {
1253  num_sli = strtol(&(attr->value[0]),&pEnd,10);
1254  if(num_sli <0 || num_sli >USHRT_MAX)
1255  throw5("Attribute type is unsigned 16-bit integer, the current attribute ",attr->name, " has the value ",num_sli, ". It is overflowed. ");
1256  else {
1257  unsigned short num_uss = (unsigned short)num_sli;
1258  attr->dtype = H5UINT16;
1259  //attr->count = 1;
1260  attr->value.resize(sizeof(unsigned short));
1261  memcpy(&(attr->value[0]),(void*)(&num_uss),sizeof(unsigned short));
1262  }
1263  }
1264  break;
1265  case H5INT32:
1266  {
1267  num_sli = strtol(&(attr->value[0]),&pEnd,10);
1268  if(num_sli <LONG_MIN || num_sli >LONG_MAX)
1269  throw5("Attribute type is 32-bit integer, the current attribute ",attr->name, " has the value ",num_sli, ". It is overflowed. ");
1270  else {
1271  attr->dtype = H5INT32;
1272  //attr->count = 1;
1273  attr->value.resize(sizeof(long int));
1274  memcpy(&(attr->value[0]),(void*)(&num_sli),sizeof(long int));
1275  }
1276 
1277  }
1278  break;
1279  case H5UINT32:
1280  {
1281  unsigned long int num_suli = strtoul(&(attr->value[0]),&pEnd,10);
1282  if(num_suli >ULONG_MAX)
1283  throw5("Attribute type is 32-bit unsigned integer, the current attribute ",attr->name, " has the value ",num_suli, ". It is overflowed. ");
1284  else {
1285  attr->dtype = H5UINT32;
1286  //attr->count = 1;
1287  attr->value.resize(sizeof(unsigned long int));
1288  memcpy(&(attr->value[0]),(void*)(&num_suli),sizeof(unsigned long int));
1289  }
1290  }
1291  break;
1292  case H5FLOAT32:
1293  {
1294  float num_sf = strtof(&(attr->value[0]),NULL);
1295  // Don't think it is necessary to check if floating-point is oveflowed for this routine. ignore it now. KY 2014-09-22
1296  attr->dtype = H5FLOAT32;
1297  //attr->count = 1;
1298  attr->value.resize(sizeof(float));
1299  memcpy(&(attr->value[0]),(void*)(&num_sf),sizeof(float));
1300  }
1301  break;
1302  case H5FLOAT64:
1303  {
1304  double num_sd = strtod(&(attr->value[0]),NULL);
1305  // Don't think it is necessary to check if floating-point is oveflowed for this routine. ignore it now. KY 2014-09-22
1306  attr->dtype = H5FLOAT64;
1307  //attr->count = 1;
1308  attr->value.resize(sizeof(double));
1309  memcpy(&(attr->value[0]),(void*)(&num_sd),sizeof(double));
1310  }
1311  break;
1312 
1313  default:
1314  throw4("Unsupported HDF5 datatype that the string is converted to for the attribute ",attr->name, " of the variable ",var->fullpath);
1315  } // switch(var->dtype)
1316 
1317 
1318 }
1319 
1320 
1321 void
1323 
1324  if (false == add_path)
1325  return;
1326 
1327  // Adding variable original name(origname) and full path(fullpath)
1328  for (vector<Var *>::iterator irv = this->vars.begin();
1329  irv != this->vars.end(); ++irv) {
1330  Attribute * attr = new Attribute();
1331  const string varname = (*irv)->name;
1332  const string attrname = "origname";
1333  Add_Str_Attr(attr,attrname,varname);
1334  (*irv)->attrs.push_back(attr);
1335  }
1336 
1337  for (vector<Var *>::iterator irv = this->vars.begin();
1338  irv != this->vars.end(); ++irv) {
1339  Attribute * attr = new Attribute();
1340  const string varname = (*irv)->fullpath;
1341  const string attrname = "fullnamepath";
1342  Add_Str_Attr(attr,attrname,varname);
1343  (*irv)->attrs.push_back(attr);
1344  }
1345 
1346  // Adding group path
1347  for (vector<Group *>::iterator irg = this->groups.begin();
1348  irg != this->groups.end(); ++irg) {
1349  // Only when this group has attributes, the original path of the group has some values. So add it.
1350  if (false == (*irg)->attrs.empty()) {
1351 
1352  Attribute * attr = new Attribute();
1353  const string varname = (*irg)->path;
1354  const string attrname = "fullnamepath";
1355  Add_Str_Attr(attr,attrname,varname);
1356  (*irg)->attrs.push_back(attr);
1357  }
1358  }
1359 
1360 }
1361 
1362 // Variable target will not be deleted, but rather its contents are replaced.
1363 // We may make this as an operator = in the future.
1364 void
1366 
1367 
1368 #if 0
1369  for_each (target->dims.begin (), target->dims.end (),
1370  delete_elem ());
1371  for_each (target->attrs.begin (), target->attrs.end (),
1372  delete_elem ());
1373 #endif
1374 
1375  target->newname = src->newname;
1376  target->name = src->name;
1377  target->fullpath = src->fullpath;
1378  target->rank = src->rank;
1379  target->dtype = src->dtype;
1381  target->unsupported_dspace = src->unsupported_dspace;
1382 #if 0
1383  for (vector<Attribute*>::iterator ira = target->attrs.begin();
1384  ira!=target->attrs.end(); ++ira) {
1385  delete (*ira);
1386  target->attrs.erase(ira);
1387  ira--;
1388  }
1389 #endif
1390  for (vector<Dimension*>::iterator ird = target->dims.begin();
1391  ird!=target->dims.end(); ++ird) {
1392  delete (*ird);
1393  target->dims.erase(ird);
1394  ird--;
1395  }
1396 
1397  // Somehow attributes cannot be replaced.
1398 #if 0
1399  for (vector<Attribute*>::iterator ira = src->attrs.begin();
1400  ira!=src->attrs.end(); ++ira) {
1401  Attribute* attr= new Attribute();
1402  attr->name = (*ira)->name;
1403  attr->newname = (*ira)->newname;
1404  attr->dtype =(*ira)->dtype;
1405  attr->count =(*ira)->count;
1406  attr->strsize = (*ira)->strsize;
1407  attr->fstrsize = (*ira)->fstrsize;
1408  attr->value =(*ira)->value;
1409  target->attrs.push_back(attr);
1410  }
1411 #endif
1412 
1413  for (vector<Dimension*>::iterator ird = src->dims.begin();
1414  ird!=src->dims.end(); ++ird) {
1415  Dimension *dim = new Dimension((*ird)->size);
1416  dim->name = (*ird)->name;
1417  dim->newname = (*ird)->newname;
1418  target->dims.push_back(dim);
1419  }
1420 
1421 }
1422 
1423  void
1425 
1426 
1427 #if 0
1428  for_each (target->dims.begin (), target->dims.end (),
1429  delete_elem ());
1430  for_each (target->attrs.begin (), target->attrs.end (),
1431  delete_elem ());
1432 #endif
1433 
1434  for (vector<Attribute*>::iterator ira = target->attrs.begin();
1435  ira!=target->attrs.end(); ++ira) {
1436  delete (*ira);
1437  target->attrs.erase(ira);
1438  ira--;
1439  }
1440  for (vector<Attribute*>::iterator ira = src->attrs.begin();
1441  ira!=src->attrs.end(); ++ira) {
1442  Attribute* attr= new Attribute();
1443  attr->name = (*ira)->name;
1444  attr->newname = (*ira)->newname;
1445  attr->dtype =(*ira)->dtype;
1446  attr->count =(*ira)->count;
1447  attr->strsize = (*ira)->strsize;
1448  attr->fstrsize = (*ira)->fstrsize;
1449  attr->value =(*ira)->value;
1450  target->attrs.push_back(attr);
1451  }
1452 
1453 }
Definition: HDF5CF.h:60
void Retrieve_H5_Attr_Value(Attribute *attr, string)
Definition: HDF5CF.cc:614
#define throw5(a1, a2, a3, a4, a5)
Definition: HDFSP.cc:84
vector< Dimension * > dims
Definition: HDF5CF.h:320
std::string newname
Definition: HDF5CF.h:310
size_t fstrsize
Definition: HDF5CF.h:236
This class represents one HDF5 dataset(CF variable)
Definition: HDF5CF.h:251
string path
Definition: HDF5CF.h:494
virtual void Replace_Var_Info(Var *src, Var *target)
Definition: HDF5CF.cc:1365
void Handle_GeneralObj_NameClashing(bool, set< string > &objnameset)
Definition: HDF5CF.cc:1016
std::string name
Definition: HDF5CF.h:311
hid_t fileid
Definition: HDF5CF.h:635
virtual void Retrieve_H5_Info(const char *path, hid_t file_id, bool include_attr)
Retrieve DDS information from the HDF5 file. The reason to separate reading DDS from DAS is: DAP need...
Definition: HDF5CF.cc:83
void Handle_RootGroup_NameClashing(set< string > &objnameset)
Definition: HDF5CF.cc:911
vector< size_t > strsize
Definition: HDF5CF.h:235
vector< char > value
Definition: HDF5CF.h:237
void Add_One_FakeDim_Name(Dimension *dim)
Definition: HDF5CF.cc:1077
virtual void Handle_Unsupported_Dtype(bool)
Handle unsupported HDF5 datatypes.
Definition: HDF5CF.cc:776
void Retrieve_H5_VarType(Var *, hid_t dset_id, const string &varname, bool &unsup_var_dtype)
Definition: HDF5CF.cc:334
int rank
Definition: HDF5CF.h:314
string newname
Definition: HDF5CF.h:232
string newname
Definition: HDF5CF.h:493
virtual void Retrieve_H5_Supported_Attr_Values()
Retrieve attribute values for the supported HDF5 datatypes.
Definition: HDF5CF.cc:588
H5DataType
Definition: HDF5CFUtil.h:54
static void gen_unique_name(std::string &str, std::set< std::string > &namelist, int &clash_index)
Definition: HDF5CFUtil.cc:191
virtual void Add_Supplement_Attrs(bool)
Add supplemental attributes such as fullpath and original name.
Definition: HDF5CF.cc:1322
bool unsupported_dspace
Definition: HDF5CF.h:316
vector< Var * > vars
Var vectors.
Definition: HDF5CF.h:639
virtual string get_CF_string(string)
Definition: HDF5CF.cc:1026
void Add_Str_Attr(Attribute *attr, const string &attrname, const string &strvalue)
Definition: HDF5CF.cc:1163
bool unsupported_attr_dtype
Definition: HDF5CF.h:497
void Adjust_Duplicate_FakeDim_Name(Dimension *dim)
Definition: HDF5CF.cc:1130
#define NULL
Definition: wcsUtil.h:65
virtual void Handle_Unsupported_Dspace()
Handle unsupported HDF5 dataspaces for datasets.
Definition: HDF5CF.cc:850
#define throw1(a1)
The followings are convenient functions to throw exceptions with different.
Definition: HDFSP.cc:80
void Change_Attr_One_Str_to_Others(Attribute *attr, Var *var)
Definition: HDF5CF.cc:1187
void Retrieve_H5_Attr_Info(Attribute *, hid_t obj_id, const int j, bool &unsup_attr_dtype)
Definition: HDF5CF.cc:461
H5DataType dtype
Definition: HDF5CF.h:233
hsize_t count
Definition: HDF5CF.h:234
H5DataType dtype
Definition: HDF5CF.h:313
void Handle_Obj_AttrNameClashing()
Definition: HDF5CF.cc:939
virtual ~File()
Definition: HDF5CF.cc:47
virtual void Replace_Var_Attrs(Var *src, Var *target)
Definition: HDF5CF.cc:1424
void Retrieve_H5_VarDim(Var *, hid_t dset_id, const string &varname, bool &unsup_var_dspace)
Definition: HDF5CF.cc:367
vector< Attribute * > attrs
Definition: HDF5CF.h:319
This class represents one attribute.
Definition: HDF5CF.h:184
void Insert_One_NameSizeMap_Element2(map< string, hsize_t > &, string name, hsize_t size)
Definition: HDF5CF.cc:1054
string newname
Definition: HDF5CF.h:171
void Add_One_Float_Attr(Attribute *attr, const string &attrname, float float_value)
Definition: HDF5CF.cc:1177
void Retrieve_H5_Obj(hid_t grp_id, const char *gname, bool include_attr)
Definition: HDF5CF.cc:131
std::string fullpath
Definition: HDF5CF.h:312
bool unsupported_attr_dtype
Definition: HDF5CF.h:315
#define throw2(a1, a2)
Definition: HDFSP.cc:81
This class repersents one dimension of an HDF5 dataset(variable).
Definition: HDF5CF.h:145
void Handle_Var_NameClashing(set< string > &objnameset)
Definition: HDF5CF.cc:906
void Insert_One_NameSizeMap_Element(string name, hsize_t size)
Definition: HDF5CF.cc:1044
bool unsupported_var_dspace
Definition: HDF5CF.h:650
static bool cf_strict_support_type(H5DataType dtype)
Definition: HDF5CFUtil.cc:106
hid_t rootid
Definition: HDF5CF.h:636
static std::string trim_string(hid_t dtypeid, const std::string s, int num_sect, size_t section_size, std::vector< size_t > &sect_newsize)
Trim the string with many NULL terms or garbage characters to simply a string with a NULL terminator...
Definition: HDF5CFUtil.cc:125
#define throw4(a1, a2, a3, a4)
Definition: HDFSP.cc:83
virtual void Flatten_Obj_Name(bool)
Flatten the object name.
Definition: HDF5CF.cc:866
This class represents an HDF5 group. The group will be flattened according to the CF conventions...
Definition: HDF5CF.h:464
static H5DataType H5type_to_H5DAPtype(hid_t h5_type_id)
Map HDF5 Datatype to the intermediate H5DAPtype for the future use.
Definition: HDF5CFUtil.cc:41
vector< Attribute * > attrs
Definition: HDF5CF.h:496
vector< Group * > groups
Non-root group vectors.
Definition: HDF5CF.h:645
This class specifies the core engineering of mapping HDF5 to DAP by following CF. ...
void Handle_General_NameClashing(set< string > &objnameset, vector< T * > &objvec)
Definition: HDF5CF.cc:971
vector< Attribute * > root_attrs
Root attribute vectors.
Definition: HDF5CF.h:642