bes  Updated for version 3.20.8
HDF5Array.cc
Go to the documentation of this file.
1 // This file is part of hdf5_handler a HDF5 file handler for the OPeNDAP
2 // data server.
3 
4 // Author: Hyo-Kyung Lee <hyoklee@hdfgroup.org> and Muqun Yang
5 // <myang6@hdfgroup.org>
6 
7 // Copyright (c) 2009-2016 The HDF Group, Inc. and OPeNDAP, Inc.
8 //
9 // This is H5free_memory software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
25 // Suite 203, Champaign, IL 61820
33 
34 
35 #include "config_hdf5.h"
36 
37 #include <iostream>
38 #include <memory>
39 #include <sstream>
40 #include <algorithm>
41 #include <ctype.h>
42 
43 #include <BESDebug.h>
44 #include <Error.h>
45 #include <InternalErr.h>
46 
47 #include "HDF5Array.h"
48 #include "HDF5Structure.h"
49 #include "HDF5Str.h"
50 
51 using namespace std;
52 using namespace libdap;
53 
55  return new HDF5Array(*this);
56 }
57 
58 HDF5Array::HDF5Array(const string & n, const string &d, BaseType * v) :
59  Array(n, d, v) {
60  d_num_dim = 0;
61  d_num_elm = 0;
62  d_memneed = 0;
63 }
64 
65 HDF5Array::~HDF5Array() {
66 }
67 
68 int HDF5Array::format_constraint(int *offset, int *step, int *count) {
69 
70  // For the 0-length array case, just return 0.
71  if(length() == 0)
72  return 0;
73 
74  //long nels = 1;
75  int nels = 1;
76  int id = 0;
77 
78  Dim_iter p = dim_begin();
79 
80  while (p != dim_end()) {
81 
82  int start = dimension_start(p, true);
83  int stride = dimension_stride(p, true);
84  int stop = dimension_stop(p, true);
85 
86  // Check for empty constraint
87  if (start > stop) {
88  ostringstream oss;
89 
90  oss << "Array/Grid hyperslab start point "<< start <<
91  " is greater than stop point " << stop <<".";
92  throw Error(malformed_expr, oss.str());
93  }
94 
95  offset[id] = start;
96  step[id] = stride;
97  count[id] = ((stop - start) / stride) + 1; // count of elements
98  nels *= count[id]; // total number of values for variable
99 
100  BESDEBUG("h5",
101  "=format_constraint():"
102  << "id=" << id << " offset=" << offset[id]
103  << " step=" << step[id]
104  << " count=" << count[id]
105  << endl);
106 
107  id++;
108  p++;
109  }
110 
111  return nels;
112 }
113 
114 
116 {
117  BESDEBUG("h5",
118  ">read() dataset=" << dataset()
119  << " dimension=" << d_num_dim
120  << " data_size=" << d_memneed << " length=" << length()
121  << endl);
122 
123  hid_t file_id = H5Fopen(dataset().c_str(),H5F_ACC_RDONLY,H5P_DEFAULT);
124 
125  BESDEBUG("h5","after H5Fopen "<<endl);
126  BESDEBUG("h5","variable name is "<<name() <<endl);
127  BESDEBUG("h5","variable path is "<<var_path <<endl);
128 
129  hid_t dset_id = -1;
130 
131  if(true == is_dap4())
132  dset_id = H5Dopen2(file_id,var_path.c_str(),H5P_DEFAULT);
133  else
134  dset_id = H5Dopen2(file_id,name().c_str(),H5P_DEFAULT);
135 
136  BESDEBUG("h5","after H5Dopen2 "<<endl);
137  // Leave the following code. We may replace the struct DS and DSattr(see hdf5_handler.h)
138 #if 0
139  hid_t dspace_id = H5Dget_space(dset_id);
140  if(dspace_id < 0) {
141  H5Dclose(dset_id);
142  H5Fclose(file_id);
143  throw InternalErr(__FILE__,__LINE__, "Fail to obtain the dataspace .");
144  }
145 
146  int num_dim = H5Sget_simple_extent_ndims(dspace_id);
147  if(num_dim < 0) {
148  H5Sclose(dspace_id);
149  H5Dclose(dset_id);
150  H5Fclose(file_id);
151  throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
152  }
153 
154  H5Sclose(dspace_id);
155 #endif
156 
157  hid_t dtype_id = H5Dget_type(dset_id);
158  if(dtype_id < 0) {
159  H5Dclose(dset_id);
160  H5Fclose(file_id);
161  throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
162  }
163 
164 
165  vector<int> offset(d_num_dim);
166  vector<int> count(d_num_dim);
167  vector<int> step(d_num_dim);
168  int nelms = format_constraint(&offset[0], &step[0], &count[0]); // Throws Error.
169  vector<char>values;
170 
171 
172  // We only map the reference to URL when the dataset is an array of reference.
173  if (get_dap_type(dtype_id,is_dap4()) == "Url") {
174  bool ret_ref = false;
175  try {
176  ret_ref = m_array_of_reference(dset_id,dtype_id);
177  H5Tclose(dtype_id);
178  H5Dclose(dset_id);
179  H5Fclose(file_id);
180 
181  }
182  catch(...) {
183  H5Tclose(dtype_id);
184  H5Dclose(dset_id);
185  H5Fclose(file_id);
186  throw;
187 
188  }
189  return ret_ref;
190  }
191 
192  try {
193  do_array_read(dset_id,dtype_id,values,false,0,nelms,&offset[0],&count[0],&step[0]);
194  }
195  catch(...) {
196  H5Tclose(dtype_id);
197  H5Dclose(dset_id);
198  H5Fclose(file_id);
199  throw;
200  }
201 
202  H5Tclose(dtype_id);
203  H5Dclose(dset_id);
204  H5Fclose(file_id);
205 
206  return true;
207 }
208 
209 void HDF5Array::do_array_read(hid_t dset_id,hid_t dtype_id,vector<char>&values,bool has_values,int values_offset,
210  int nelms,int* offset,int* count, int* step)
211 {
212 
213  H5T_class_t tcls = H5Tget_class(dtype_id);
214 
215  if(H5T_COMPOUND == tcls)
216  m_array_of_structure(dset_id,values,has_values,values_offset,nelms,offset,count,step);
217  else if(H5T_INTEGER == tcls || H5T_FLOAT == tcls || H5T_STRING == tcls)
218  m_array_of_atomic(dset_id,dtype_id,nelms,offset,count,step);
219  else {
220  throw InternalErr(__FILE__,__LINE__,"Fail to read the data for Unsupported datatype.");
221  }
222 
223 }
224 
225 void HDF5Array:: m_array_of_atomic(hid_t dset_id, hid_t dtype_id,
226  int nelms,int* offset,int* count, int* step)
227 {
228 
229  hid_t memtype = -1;
230  if((memtype = H5Tget_native_type(dtype_id, H5T_DIR_ASCEND))<0) {
231  throw InternalErr (__FILE__, __LINE__, "Fail to obtain memory datatype.");
232  }
233 
234  // First handle variable-length string
235  if (H5Tis_variable_str(memtype) && H5Tget_class(memtype) == H5T_STRING) {
236 
237  vector<hsize_t> hoffset;
238  vector<hsize_t>hcount;
239  vector<hsize_t>hstep;
240  hoffset.resize(d_num_dim);
241  hcount.resize(d_num_dim);
242  hstep.resize(d_num_dim);
243  for (int i = 0; i <d_num_dim; i++) {
244  hoffset[i] = (hsize_t) offset[i];
245  hcount[i] = (hsize_t) count[i];
246  hstep[i] = (hsize_t) step[i];
247  }
248 
249  vector<string>finstrval;
250  finstrval.resize(nelms);
251  try {
252  read_vlen_string(dset_id, nelms, &hoffset[0], &hstep[0], &hcount[0],finstrval);
253  }
254  catch(...) {
255  H5Tclose(memtype);
256  throw InternalErr(__FILE__,__LINE__,"Fail to read variable-length string.");
257  }
258  set_value(finstrval,nelms);
259  H5Tclose(memtype);
260  return ;
261  }
262 
263  try {
264  if (nelms == d_num_elm) {
265 
266  vector<char> convbuf(d_memneed);
267  get_data(dset_id, (void *) &convbuf[0]);
268 
269  // Check if a Signed Byte to Int16 conversion is necessary, this is only valid for DAP2.
270  if(false == is_dap4()) {
271  if (1 == H5Tget_size(memtype) && H5T_SGN_2 == H5Tget_sign(memtype))
272  {
273  vector<short> convbuf2(nelms);
274  for (int i = 0; i < nelms; i++) {
275  convbuf2[i] = (signed char) (convbuf[i]);
276  BESDEBUG("h5", "convbuf[" << i << "]="
277  << (signed char)convbuf[i] << endl);
278  BESDEBUG("h5", "convbuf2[" << i << "]="
279  << convbuf2[i] << endl)
280  ;
281  }
282  // Libdap will generate the wrong output.
283  m_intern_plain_array_data((char*) &convbuf2[0],memtype);
284  }
285  else
286  m_intern_plain_array_data(&convbuf[0],memtype);
287  }
288  else
289  m_intern_plain_array_data(&convbuf[0],memtype);
290  } // end of "if (nelms == d_num_elm)"
291  else {
292  size_t data_size = nelms * H5Tget_size(memtype);
293  if (data_size == 0) {
294  throw InternalErr(__FILE__, __LINE__, "get_size failed");
295  }
296  vector<char> convbuf(data_size);
297  get_slabdata(dset_id, &offset[0], &step[0], &count[0], d_num_dim, &convbuf[0]);
298 
299  // Check if a Signed Byte to Int16 conversion is necessary.
300  if(false == is_dap4()){
301  if (1 == H5Tget_size(memtype) && H5T_SGN_2 == H5Tget_sign(memtype)) {
302  vector<short> convbuf2(data_size);
303  for (int i = 0; i < (int)data_size; i++) {
304  convbuf2[i] = static_cast<signed char> (convbuf[i]);
305  }
306  m_intern_plain_array_data((char*) &convbuf2[0],memtype);
307  }
308  else {
309  m_intern_plain_array_data(&convbuf[0],memtype);
310  }
311  }
312  else
313  m_intern_plain_array_data(&convbuf[0],memtype);
314 
315  }
316  H5Tclose(memtype);
317  }
318  catch (...) {
319  H5Tclose(memtype);
320  throw;
321  }
322 
323 }
324 
325 bool HDF5Array::m_array_of_structure(hid_t dsetid, vector<char>&values,bool has_values,int values_offset,
326  int nelms,int* offset,int* count, int* step) {
327 
328  BESDEBUG("h5", "=read() Array of Structure length=" << length() << endl);
329 
330  hid_t mspace = -1;
331  hid_t memtype = -1;
332  hid_t dtypeid = -1;
333  size_t ty_size = -1;
334 
335  if((dtypeid = H5Dget_type(dsetid)) < 0)
336  throw InternalErr (__FILE__, __LINE__, "Cannot obtain the datatype.");
337 
338  if((memtype = H5Tget_native_type(dtypeid, H5T_DIR_ASCEND))<0) {
339  H5Tclose(dtypeid);
340  throw InternalErr (__FILE__, __LINE__, "Fail to obtain memory datatype.");
341  }
342 
343  ty_size = H5Tget_size(memtype);
344  if (ty_size == 0) {
345  H5Tclose(memtype);
346  H5Tclose(dtypeid);
347  throw InternalErr (__FILE__, __LINE__,"Fail to obtain the size of HDF5 compound datatype.");
348  }
349 
350  if(false == has_values) {
351 
352  hid_t dspace = -1;
353 
354  if ((dspace = H5Dget_space(dsetid))<0) {
355  H5Tclose(memtype);
356  H5Tclose(dtypeid);
357  throw InternalErr (__FILE__, __LINE__, "Cannot obtain data space.");
358  }
359 
360  d_num_dim = H5Sget_simple_extent_ndims(dspace);
361  if(d_num_dim < 0) {
362  H5Tclose(memtype);
363  H5Tclose(dtypeid);
364  H5Sclose(dspace);
365  throw InternalErr (__FILE__, __LINE__, "Cannot obtain the number of dimensions of the data space.");
366  }
367 
368  vector<hsize_t> hoffset;
369  vector<hsize_t>hcount;
370  vector<hsize_t>hstep;
371  hoffset.resize(d_num_dim);
372  hcount.resize(d_num_dim);
373  hstep.resize(d_num_dim);
374  for (int i = 0; i <d_num_dim; i++) {
375  hoffset[i] = (hsize_t) offset[i];
376  hcount[i] = (hsize_t) count[i];
377  hstep[i] = (hsize_t) step[i];
378  }
379 
380  if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET,
381  &hoffset[0], &hstep[0],
382  &hcount[0], NULL) < 0) {
383  H5Tclose(memtype);
384  H5Tclose(dtypeid);
385  H5Sclose(dspace);
386  throw InternalErr (__FILE__, __LINE__, "Cannot generate the hyperslab of the HDF5 dataset.");
387  }
388 
389  mspace = H5Screate_simple(d_num_dim, &hcount[0],NULL);
390  if (mspace < 0) {
391  H5Sclose(dspace);
392  H5Tclose(memtype);
393  H5Tclose(dtypeid);
394  throw InternalErr (__FILE__, __LINE__, "Cannot create the memory space.");
395  }
396 
397  values.resize(nelms*ty_size);
398  hid_t read_ret = -1;
399  read_ret = H5Dread(dsetid,memtype,mspace,dspace,H5P_DEFAULT,(void*)&values[0]);
400  if (read_ret < 0) {
401  H5Tclose(memtype);
402  H5Tclose(dtypeid);
403  H5Sclose(dspace);
404  throw InternalErr (__FILE__, __LINE__, "Fail to read the HDF5 compound datatype dataset.");
405  }
406 
407  H5Sclose(dspace);
408  has_values = true;
409  } // end of "if(false == has_values)" block
410 
411  HDF5Structure *h5s = NULL;
412  hid_t memb_id = -1;
413  char* memb_name = NULL;
414 
415  try {
416 
417  // Loop through all the elements in this compound datatype array.
418  for (int element = 0; element < nelms; ++element) {
419 
420  h5s = dynamic_cast<HDF5Structure*>(var()->ptr_duplicate());
421  H5T_class_t memb_cls = H5T_NO_CLASS;
422  int nmembs = 0;
423  size_t memb_offset = 0;
424 
425  if((nmembs = H5Tget_nmembers(memtype)) < 0)
426  throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of HDF5 compound datatype.");
427 
428  for(unsigned int u = 0; u < (unsigned)nmembs; u++) {
429 
430  // Get member type ID
431  if((memb_id = H5Tget_member_type(memtype, u)) < 0)
432  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype of an HDF5 compound datatype member.");
433 
434  // Get member type class
435  if((memb_cls = H5Tget_member_class (memtype, u)) < 0)
436  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype class of an HDF5 compound datatype member.");
437 
438  // Get member offset,H5Tget_member_offset only fails
439  // when H5Tget_memeber_class fails. Sinc H5Tget_member_class
440  // is checked above. So no need to check the return value.
441  memb_offset= H5Tget_member_offset(memtype,u);
442 
443  // Get member name
444  memb_name = H5Tget_member_name(memtype,u);
445  if(memb_name == NULL)
446  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the name of an HDF5 compound datatype member.");
447 
448  BaseType *field = h5s->var(memb_name);
449  if (memb_cls == H5T_COMPOUND) {
450  HDF5Structure &memb_h5s = dynamic_cast<HDF5Structure&>(*field);
451  memb_h5s.do_structure_read(dsetid, memb_id,values,has_values,memb_offset+values_offset+ty_size*element);
452  }
453 
454  else if(memb_cls == H5T_ARRAY) {
455 
456  // memb_id, obtain the number of dimensions
457  int at_ndims = H5Tget_array_ndims(memb_id);
458  if(at_ndims <= 0)
459  throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of dimensions of the array datatype.");
460 
461 #if 0
462  //HDF5Array &h5_array_type = dynamic_cast<HDF5Array&>(*h5s->var(memb_name));
463 #endif
464  HDF5Array &h5_array_type = dynamic_cast<HDF5Array&>(*field);
465  vector<int> at_offset(at_ndims,0);
466  vector<int> at_count(at_ndims,0);
467  vector<int> at_step(at_ndims,0);
468 
469  int at_nelms = h5_array_type.format_constraint(&at_offset[0],&at_step[0],&at_count[0]);
470 
471  // Read the array data
472  h5_array_type.do_h5_array_type_read(dsetid,memb_id,values,has_values,memb_offset+values_offset+ty_size*element,
473  at_nelms,&at_offset[0],&at_count[0],&at_step[0]);
474 
475  }
476  else if(memb_cls == H5T_INTEGER || memb_cls == H5T_FLOAT) {
477 
478  if(true == promote_char_to_short(memb_cls,memb_id)) {
479  void *src = (void*)(&values[0] + (element*ty_size) + values_offset +memb_offset);
480  char val_int8;
481  memcpy(&val_int8,src,1);
482  short val_short=(short)val_int8;
483  field->val2buf(&val_short);
484  }
485  else {
486  field->val2buf(&values[0] + (element*ty_size) + values_offset +memb_offset);
487  }
488 
489  }
490  else if(memb_cls == H5T_STRING) {
491 
492  // distinguish between variable length and fixed length
493  if(true == H5Tis_variable_str(memb_id)) {
494  void *src = (void*)(&values[0]+(element*ty_size)+values_offset + memb_offset);
495  string final_str;
496  get_vlen_str_data((char*)src,final_str);
497  field->val2buf(&final_str);
498  }
499  else {// Obtain fixed-size string value
500  void *src = (void*)(&values[0]+(element*ty_size)+values_offset + memb_offset);
501  vector<char> str_val;
502  size_t memb_size = H5Tget_size(memb_id);
503  if (memb_size == 0) {
504  H5Tclose(memb_id);
505  H5free_memory(memb_name);
506  delete h5s;
507  throw InternalErr (__FILE__, __LINE__,"Fail to obtain the size of HDF5 compound datatype.");
508  }
509  str_val.resize(memb_size);
510  memcpy(&str_val[0],src,memb_size);
511  string temp_string(str_val.begin(),str_val.end());
512  field->val2buf(&temp_string);
513  }
514  }
515  else {
516  H5free_memory(memb_name);
517  H5Tclose(memb_id);
518  delete h5s;
519  throw InternalErr (__FILE__, __LINE__,
520  "Only support the field of compound datatype when the field type class is integer, float, string, array or compound..");
521 
522  }
523 
524  // Close member type ID
525  H5Tclose(memb_id);
526  H5free_memory(memb_name);
527  field->set_read_p(true);
528  } // end "for(unsigned u = 0)"
529  h5s->set_read_p(true);
530  set_vec(element,h5s);
531  delete h5s;
532  } // end "for (int element=0"
533 
534  if(true == has_values) {
535  if(-1 == mspace)
536  throw InternalErr(__FILE__, __LINE__, "memory type and memory space for this compound datatype should be valid.");
537 
538  if(H5Dvlen_reclaim(memtype,mspace,H5P_DEFAULT,(void*)&values[0])<0)
539  throw InternalErr(__FILE__, __LINE__, "Unable to reclaim the compound datatype array.");
540  H5Sclose(mspace);
541 
542  }
543 
544  H5Tclose(dtypeid);
545  H5Tclose(memtype);
546 
547  }
548  catch(...) {
549 
550  if(memb_id != -1)
551  H5Tclose(memb_id);
552  if(memb_name != NULL)
553  H5free_memory(memb_name);
554  if(h5s != NULL)
555  delete h5s;
556  if(true == has_values) {
557  if(H5Dvlen_reclaim(memtype,mspace,H5P_DEFAULT,(void*)(&values[0]))<0) {
558  H5Tclose(memtype);
559  H5Sclose(mspace);
560  }
561  H5Sclose(mspace);
562  }
563  H5Tclose(memtype);
564  H5Tclose(dtypeid);
565  throw;
566  }
567 
568  set_read_p(true);
569 
570  return false;
571 }
572 
573 // Haven't checked the codes and comments
574 // Haven't added the close handles routines for error handlings yet. KY 2011-11-18
575 bool HDF5Array::m_array_of_reference(hid_t dset_id,hid_t dtype_id)
576 {
577 
578  hid_t memtype = H5Tget_native_type(dtype_id, H5T_DIR_ASCEND);
579  if (memtype < 0)
580  throw InternalErr(__FILE__, __LINE__, "cannot obtain the memory data type for the dataset.");
581 
582  hid_t d_ty_id = memtype;
583  hid_t d_dset_id = dset_id;
584  hdset_reg_ref_t *rbuf = NULL;
585 
586  try {
587  vector<int> offset(d_num_dim);
588  vector<int> count(d_num_dim);
589  vector<int> step(d_num_dim);
590 
591 
592  int nelms = format_constraint(&offset[0], &step[0], &count[0]); // Throws Error.
593  vector<string> v_str(nelms);
594 
595  BESDEBUG("h5", "=read() URL type is detected. "
596  << "nelms=" << nelms << " full_size=" << d_num_elm << endl);
597 
598  // Handle regional reference.
599  if (H5Tequal(d_ty_id, H5T_STD_REF_DSETREG) < 0) {
600  throw InternalErr(__FILE__, __LINE__, "H5Tequal() failed");
601  }
602 
603  if (H5Tequal(d_ty_id, H5T_STD_REF_DSETREG) > 0) {
604  BESDEBUG("h5", "=read() Got regional reference. " << endl);
605  // Vector doesn't work for this case. somehow it doesn't support the type.
606  rbuf = new hdset_reg_ref_t[d_num_elm];
607  if(rbuf == NULL){
608  throw InternalErr(__FILE__, __LINE__, "new() failed.");
609  }
610  if (H5Dread(d_dset_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, &rbuf[0]) < 0) {
611  throw InternalErr(__FILE__, __LINE__, "H5Dread() failed.");
612  }
613 
614  for (int i = 0; i < nelms; i++) {
615  // Let's assume that URL array is always 1 dimension.
616  BESDEBUG("h5", "=read() rbuf[" << i << "]" <<
617  rbuf[offset[0] + i * step[0]] << endl);
618 
619  if (rbuf[offset[0] + i * step[0]][0] != '\0') {
620  char r_name[DODS_NAMELEN];
621 
622  hid_t did_r = H5RDEREFERENCE(d_dset_id, H5R_DATASET_REGION, rbuf[offset[0] + i * step[0]]);
623  if (did_r < 0) {
624  throw InternalErr(__FILE__, __LINE__, "H5RDEREFERENCE() failed.");
625 
626  }
627 
628  if (H5Iget_name(did_r, (char *) r_name, DODS_NAMELEN) < 0) {
629  throw InternalErr(__FILE__, __LINE__, "H5Iget_name() failed.");
630  }
631  BESDEBUG("h5", "=read() dereferenced name is " << r_name
632  << endl);
633 
634  string varname(r_name);
635  hid_t space_id = H5Rget_region(did_r, H5R_DATASET_REGION, rbuf[offset[0] + i * step[0]]);
636  if (space_id < 0) {
637  throw InternalErr(__FILE__, __LINE__, "H5Rget_region() failed.");
638 
639  }
640 
641  int ndim = H5Sget_simple_extent_ndims(space_id);
642  if (ndim < 0) {
643  throw InternalErr(__FILE__, __LINE__, "H5Sget_simple_extent_ndims() failed.");
644  }
645 
646  BESDEBUG("h5", "=read() dim is " << ndim << endl);
647 
648  string expression;
649  switch (H5Sget_select_type(space_id)) {
650 
651  case H5S_SEL_NONE:
652  BESDEBUG("h5", "=read() None selected." << endl);
653  break;
654 
655  case H5S_SEL_POINTS: {
656  BESDEBUG("h5", "=read() Points selected." << endl);
657  hssize_t npoints = H5Sget_select_npoints(space_id);
658  if (npoints < 0) {
659  throw InternalErr(__FILE__, __LINE__,
660  "Cannot determine number of elements in the dataspace selection");
661  }
662 
663  BESDEBUG("h5", "=read() npoints are " << npoints
664  << endl);
665  vector<hsize_t> buf(npoints * ndim);
666  if (H5Sget_select_elem_pointlist(space_id, 0, npoints, &buf[0]) < 0) {
667  throw InternalErr(__FILE__, __LINE__, "H5Sget_select_elem_pointlist() failed.");
668  }
669 
670 #ifdef DODS_DEBUG
671  for (int j = 0; j < npoints * ndim; j++) {
672  "h5", "=read() npoints buf[0] =" << buf[j] <<endl;
673  }
674 #endif
675 
676  for (int j = 0; j < (int) npoints; j++) {
677  // Name of the dataset.
678  expression.append(varname);
679  for (int k = 0; k < ndim; k++) {
680  ostringstream oss;
681  oss << "[" << (int) buf[j * ndim + k] << "]";
682  expression.append(oss.str());
683  }
684  if (j != (int) (npoints - 1)) {
685  expression.append(",");
686  }
687  }
688  v_str[i].append(expression);
689 
690  break;
691  }
692  case H5S_SEL_HYPERSLABS: {
693  vector<hsize_t> start(ndim);
694  vector<hsize_t> end(ndim);
695 
696  BESDEBUG("h5", "=read() Slabs selected." << endl);
697  BESDEBUG("h5", "=read() nblock is " <<
698  H5Sget_select_hyper_nblocks(space_id) << endl);
699 
700  if (H5Sget_select_bounds(space_id, &start[0], &end[0]) < 0) {
701  throw InternalErr(__FILE__, __LINE__, "H5Sget_select_bounds() failed.");
702  }
703 
704  for (int j = 0; j < ndim; j++) {
705  ostringstream oss;
706  BESDEBUG("h5", "=read() start is " << start[j]
707  << "=read() end is " << end[j] << endl);
708  oss << "[" << (int) start[j] << ":" << (int) end[j] << "]";
709  expression.append(oss.str());
710  BESDEBUG("h5", "=read() expression is "
711  << expression << endl)
712  ;
713  }
714  v_str[i] = varname;
715  if (!expression.empty()) {
716  v_str[i].append(expression);
717  }
718  // Constraint expression. [start:1:end]
719  break;
720  }
721  case H5S_SEL_ALL:
722  BESDEBUG("h5", "=read() All selected." << endl);
723  break;
724 
725  default:
726  BESDEBUG("h5", "Unknown space type." << endl);
727  break;
728  }
729 
730  }
731  else {
732  v_str[i] = "";
733  }
734  }
735  delete[] rbuf;
736  }
737 
738  // Handle object reference.
739  if (H5Tequal(d_ty_id, H5T_STD_REF_OBJ) < 0) {
740  throw InternalErr(__FILE__, __LINE__, "H5Tequal() failed.");
741  }
742 
743  if (H5Tequal(d_ty_id, H5T_STD_REF_OBJ) > 0) {
744  BESDEBUG("h5", "=read() Got object reference. " << endl);
745  vector<hobj_ref_t> orbuf;
746  orbuf.resize(d_num_elm);
747  if (H5Dread(d_dset_id, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, &orbuf[0]) < 0) {
748  throw InternalErr(__FILE__, __LINE__, "H5Dread failed()");
749  }
750 
751  for (int i = 0; i < nelms; i++) {
752  // Let's assume that URL array is always 1 dimension.
753  hid_t did_r = H5RDEREFERENCE(d_dset_id, H5R_OBJECT, &orbuf[offset[0] + i * step[0]]);
754  if (did_r < 0) {
755  throw InternalErr(__FILE__, __LINE__, "H5RDEREFERENCE() failed.");
756  }
757  char r_name[DODS_NAMELEN];
758  if (H5Iget_name(did_r, (char *) r_name, DODS_NAMELEN) < 0) {
759  throw InternalErr(__FILE__, __LINE__, "H5Iget_name() failed.");
760  }
761 
762  // Shorten the dataset name
763  string varname(r_name);
764 
765  BESDEBUG("h5", "=read() dereferenced name is " << r_name <<endl);
766  v_str[i] = varname;
767  }
768  }
769  set_value(&v_str[0], nelms);
770  H5Tclose(memtype);
771  return false;
772  }
773  catch (...) {
774  if(rbuf!= NULL)
775  delete[] rbuf;
776  if(memtype != -1)
777  H5Tclose(memtype);
778  throw;
779  }
780 }
781 
782 void HDF5Array::m_intern_plain_array_data(char *convbuf,hid_t memtype)
783 {
784  if (check_h5str(memtype)) {
785  vector<string> v_str(d_num_elm);
786  size_t elesize = H5Tget_size(memtype);
787  if (elesize == 0) {
788  throw InternalErr(__FILE__, __LINE__, "H5Tget_size() failed.");
789  }
790  vector<char> strbuf(elesize + 1);
791  BESDEBUG("h5", "=read()<check_h5str() element size=" << elesize
792  << " d_num_elm=" << d_num_elm << endl);
793 
794  for (int strindex = 0; strindex < d_num_elm; strindex++) {
795  get_strdata(strindex, &convbuf[0], &strbuf[0], elesize);
796  BESDEBUG("h5", "=read()<get_strdata() strbuf=" << &strbuf[0] << endl);
797  v_str[strindex] = &strbuf[0];
798  }
799  set_read_p(true);
800  val2buf((void *) &v_str[0]);
801  }
802  else {
803  set_read_p(true);
804  val2buf((void *) convbuf);
805  }
806 }
807 
808 
809 bool HDF5Array::do_h5_array_type_read(hid_t dsetid, hid_t memb_id,vector<char>&values,bool has_values,int values_offset,
810  int at_nelms,int* at_offset,int* at_count, int* at_step){
811  //1. Call do array first(datatype must be derived) and the value must be set. We don't support Array datatype
812  // unless it is inside a compound datatype
813  if(has_values != true)
814  throw InternalErr (__FILE__, __LINE__, "Only support the retrieval of HDF5 Array datatype values from the parent compound datatype read.");
815 
816  hid_t at_base_type = H5Tget_super(memb_id);
817  if(at_base_type < 0) {
818  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the basetype of the array datatype.");
819  }
820 
821  // memb_id, obtain the number of dimensions
822  int at_ndims = H5Tget_array_ndims(memb_id);
823  if(at_ndims <= 0) {
824  H5Tclose(at_base_type);
825  throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of dimensions of the array datatype.");
826  }
827 
828  vector<hsize_t>at_dims_h(at_ndims,0);
829 
830  // Obtain the number of elements for each dims
831  if(H5Tget_array_dims(memb_id,&at_dims_h[0])<0) {
832  H5Tclose(at_base_type);
833  throw InternalErr (__FILE__, __LINE__, "Fail to obtain dimensions of the array datatype.");
834  }
835  vector<int>at_dims(at_ndims,0);
836  for(int i = 0;i<at_ndims;i++) {
837  at_dims[i] = (int)at_dims_h[i];
838  }
839  int at_total_nelms = 1;
840  for (int i = 0; i <at_ndims; i++)
841  at_total_nelms = at_total_nelms*at_dims[i];
842 
843  H5T_class_t array_cls = H5Tget_class(at_base_type);
844  if(H5T_NO_CLASS == array_cls) {
845  H5Tclose(at_base_type);
846  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype class of the array base type.");
847  }
848 
849  size_t at_base_type_size = H5Tget_size(at_base_type);
850  if(0 == at_base_type_size){
851  H5Tclose(at_base_type);
852  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the size of the array base type.");
853  }
854 
855  // H5 Array type, the basetype is COMPOUND.
856  if(H5T_COMPOUND == array_cls) {
857 
858  // These vectors are used to handle subset of array datatype
859  vector<int>at_end(at_ndims,0);
860  vector<int>at_pos(at_ndims,0);
861  for (int i = 0; i< at_ndims; i++){
862  at_pos[i] = at_offset[i];
863  at_end[i] = at_offset[i] + (at_count[i] -1)*at_step[i];
864  }
865 
866  int at_orig_index = INDEX_nD_TO_1D(at_dims,at_pos);
867 
868  // To read the array of compound (structure) in DAP, one must read one element each. set_vec is used afterwards.
869  for (int array_index = 0; array_index <at_nelms; array_index++) {
870 
871  // The basetype of the array datatype is compound,-- check if the following line is valid.
872  HDF5Structure *h5s = dynamic_cast<HDF5Structure*>(var()->ptr_duplicate());
873  hid_t child_memb_id;
874  H5T_class_t child_memb_cls;
875  int child_nmembs;
876  size_t child_memb_offset;
877  unsigned child_u;
878 
879  if((child_nmembs = H5Tget_nmembers(at_base_type)) < 0) {
880  H5Tclose(at_base_type);
881  delete h5s;
882  throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of HDF5 compound datatype.");
883  }
884 
885  for(child_u = 0; child_u < (unsigned)child_nmembs; child_u++) {
886 
887  // Get member type ID
888  if((child_memb_id = H5Tget_member_type(at_base_type, child_u)) < 0) {
889  H5Tclose(at_base_type);
890  delete h5s;
891  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype of an HDF5 compound datatype member.");
892  }
893 
894  // Get member type class
895  if((child_memb_cls = H5Tget_member_class (at_base_type, child_u)) < 0) {
896  H5Tclose(child_memb_id);
897  H5Tclose(at_base_type);
898  delete h5s;
899  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype class of an HDF5 compound datatype member.");
900  }
901 
902  // Get member offset
903  child_memb_offset= H5Tget_member_offset(at_base_type,child_u);
904 
905  // Get member name
906  char *child_memb_name = H5Tget_member_name(at_base_type,child_u);
907  if(child_memb_name == NULL) {
908  H5Tclose(child_memb_id);
909  H5Tclose(at_base_type);
910  delete h5s;
911  throw InternalErr (__FILE__, __LINE__, "Fail to obtain the name of an HDF5 compound datatype member.");
912  }
913 
914  BaseType *field = h5s->var(child_memb_name);
915  if (child_memb_cls == H5T_COMPOUND) {
916 
917  HDF5Structure &memb_h5s = dynamic_cast<HDF5Structure&>(*field);
918  //
919  // Call structure read when reading the whole array. sa1{sa2[100]}
920  // sa2[100] is an array datatype.
921  // If reading the whole buffer, just add the buffer.
922  if(at_total_nelms == at_nelms) {
923  memb_h5s.do_structure_read(dsetid,child_memb_id, values,has_values,values_offset+at_base_type_size*array_index+child_memb_offset);
924  }
925  // Subset of sa2, sa2[10:100:2]; sa2[100] is an array datatype. The whole array sa2[100] is to be read into somewhere in buffer values.
926  else {// The subset should be considered. adjust memb_offset+values_offset+???,make sure only the subset is selected.
927  // at_total_nelms is 100 but at_nelms is (100-10)/2+1=46. The starting point of the whole array is values+memb_offset_values_offset
928  // When the datatype is structure, we have to obtain the index one by one.
929 
930  memb_h5s.do_structure_read(dsetid, child_memb_id, values,has_values,values_offset+at_base_type_size*at_orig_index+child_memb_offset);
931 
932  }
933 
934  }
935  else if(child_memb_cls == H5T_ARRAY) {
936 
937  // memb_id, obtain the number of dimensions
938  int child_at_ndims = H5Tget_array_ndims(child_memb_id);
939  if(child_at_ndims <= 0) {
940  H5Tclose(at_base_type);
941  H5Tclose(child_memb_id);
942  H5free_memory(child_memb_name);
943  delete h5s;
944  throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of dimensions of the array datatype.");
945 
946  }
947 
948  HDF5Array &h5_array_type = dynamic_cast<HDF5Array&>(*field);
949  vector<int> child_at_offset(child_at_ndims,0);
950  vector<int> child_at_count(child_at_ndims,0);
951  vector<int> child_at_step(child_at_ndims,0);
952 
953  int child_at_nelms = h5_array_type.format_constraint(&child_at_offset[0],&child_at_step[0],&child_at_count[0]);
954 
955  if(at_total_nelms == at_nelms) {
956  h5_array_type.do_h5_array_type_read(dsetid,child_memb_id,values,has_values,child_memb_offset+values_offset+at_base_type_size*array_index,
957  child_at_nelms,&child_at_offset[0],&child_at_count[0],&child_at_step[0]);
958  }
959  else {// Adjust memb_offset+values_offset, basically change at_base_type_size*array_index
960  h5_array_type.do_h5_array_type_read(dsetid,child_memb_id,values,has_values,child_memb_offset+values_offset+at_base_type_size*at_orig_index,
961  child_at_nelms,&child_at_offset[0],&child_at_count[0],&child_at_step[0]);
962 
963  }
964  }
965 
966  else if(H5T_INTEGER == child_memb_cls || H5T_FLOAT == child_memb_cls){
967 
968  int number_index =((at_total_nelms == at_nelms)?array_index:at_orig_index);
969  if(true == promote_char_to_short(child_memb_cls,child_memb_id)) {
970  void *src = (void*)(&values[0] + (number_index*at_base_type_size) + values_offset +child_memb_offset);
971  char val_int8;
972  memcpy(&val_int8,src,1);
973  short val_short=(short)val_int8;
974  field->val2buf(&val_short);
975  }
976  else
977  field->val2buf(&values[0] + (number_index * at_base_type_size) + values_offset+child_memb_offset);
978 
979 
980  }
981  else if(H5T_STRING == child_memb_cls){
982 
983  int string_index =((at_total_nelms == at_nelms)?array_index:at_orig_index);
984 
985  // distinguish between variable length and fixed length
986  if(true == H5Tis_variable_str(child_memb_id)) {
987 
988  // Need to check if the size of variable length array type is right in HDF5 lib.
989  void *src = (void*)(&values[0]+(string_index *at_base_type_size)+values_offset+child_memb_offset);
990  string final_str;
991  char*temp_bp =(char*)src;
992  get_vlen_str_data(temp_bp,final_str);
993  field->val2buf(&final_str[0]); //field->set_value(final_str);
994 
995  }
996  else {// Obtain string
997  void *src = (void*)(&values[0]+(string_index *at_base_type_size)+values_offset+child_memb_offset);
998  vector<char> str_val;
999  size_t memb_size = H5Tget_size(child_memb_id);
1000  if (memb_size == 0) {
1001  H5Tclose(child_memb_id);
1002  H5Tclose(at_base_type);
1003  H5free_memory(child_memb_name);
1004  delete h5s;
1005  throw InternalErr (__FILE__, __LINE__,"Fail to obtain the size of HDF5 compound datatype.");
1006  }
1007  str_val.resize(memb_size);
1008  memcpy(&str_val[0],src,memb_size);
1009  field->val2buf(&str_val[0]);
1010 
1011  }
1012  }
1013  else {
1014  H5Tclose(child_memb_id);
1015  H5Tclose(at_base_type);
1016  H5free_memory(child_memb_name);
1017  delete h5s;
1018  throw InternalErr (__FILE__, __LINE__, "Unsupported datatype class for the array base type.");
1019 
1020 
1021  }
1022  field->set_read_p(true);
1023  H5free_memory(child_memb_name);
1024  H5Tclose(child_memb_id);
1025 
1026  } // end "for ( child_u = 0)"
1027  h5s->set_read_p(true);
1028 
1029  // Save the value of this element to DAP structure.
1030  set_vec(array_index,h5s);
1031  delete h5s;
1032 
1033  vector<int>at_offsetv(at_pos.size(),0);
1034  vector<int>at_stepv(at_pos.size(),0);
1035  for (unsigned int at_index = 0; at_index<at_pos.size();at_index++){
1036  at_offsetv[at_index] = at_offset[at_index];
1037  at_stepv[at_index] = at_step[at_index];
1038  }
1039  //obtain the next position of the selected point based on the offset,end and step.
1040  obtain_next_pos(at_pos,at_offsetv,at_end,at_stepv,(int)(at_pos.size()));
1041  at_orig_index = INDEX_nD_TO_1D(at_dims,at_pos);
1042  }// end for "(array_index = 0) for array (compound)datatype"
1043 
1044  // Need to check the usage of set_read_p(true);
1045 #if 0
1046  //set_read_p(true);
1047 #endif
1048  }
1049  else if(H5T_INTEGER == array_cls|| H5T_FLOAT == array_cls) {
1050 
1051  // If no subset for the array datatype, just read the whole buffer.
1052  if(at_total_nelms == at_nelms) {
1053 
1054  // For DAP2 char should be mapped to short
1055  if( true == promote_char_to_short(array_cls ,at_base_type)) {
1056  vector<char> val_int8;
1057  val_int8.resize(at_nelms);
1058  void*src = (void*)(&values[0] +values_offset);
1059  memcpy(&val_int8[0],src,at_nelms);
1060 
1061  vector<short> val_short;
1062  for (int i = 0; i<at_nelms; i++)
1063  val_short[i] = (short)val_int8[i];
1064 
1065  val2buf(&val_short[0]);
1066 
1067  }
1068  else // short cut for others
1069  val2buf(&values[0] + values_offset);
1070 
1071  }
1072  else { // Adjust the value for the subset of the array datatype
1073 
1074  // Obtain the correponding DAP type of the HDF5 data type
1075  string dap_type = get_dap_type(at_base_type,is_dap4());
1076 
1077  // The total array type data is read.
1078  void*src = (void*)(&values[0] + values_offset);
1079 
1080  // set the original position to the starting point
1081  vector<int>at_pos(at_ndims,0);
1082  for (int i = 0; i< at_ndims; i++)
1083  at_pos[i] = at_offset[i];
1084 
1085  if( BYTE == dap_type) {
1086 
1087  vector<unsigned char>total_val;
1088  total_val.resize(at_total_nelms);
1089  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1090 
1091  vector<unsigned char>final_val;
1092  subset<unsigned char>(
1093  &total_val[0],
1094  at_ndims,
1095  at_dims,
1096  at_offset,
1097  at_step,
1098  at_count,
1099  &final_val,
1100  at_pos,
1101  0
1102  );
1103 
1104  set_value((dods_byte*)&final_val[0],at_nelms);
1105 
1106 
1107  }
1108  else if( INT16 == dap_type) {
1109 
1110  // promote char to short,DAP2 doesn't have "char" type
1111  if(true == promote_char_to_short(array_cls,at_base_type)) {
1112  vector<char>total_val;
1113  total_val.resize(at_total_nelms);
1114  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1115 
1116  vector<char>final_val;
1117  subset<char>(
1118  &total_val[0],
1119  at_ndims,
1120  at_dims,
1121  at_offset,
1122  at_step,
1123  at_count,
1124  &final_val,
1125  at_pos,
1126  0
1127  );
1128 
1129  vector<short> final_val_short;
1130  final_val_short.resize(at_nelms);
1131  for(int i = 0; i<at_nelms; i++)
1132  final_val_short[i] = final_val[i];
1133 
1134  val2buf(&final_val_short[0]);
1135 
1136  }
1137  else {// short
1138 
1139  vector<short>total_val;
1140  total_val.resize(at_total_nelms);
1141  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1142 
1143  vector<short>final_val;
1144  subset<short>(
1145  &total_val[0],
1146  at_ndims,
1147  at_dims,
1148  at_offset,
1149  at_step,
1150  at_count,
1151  &final_val,
1152  at_pos,
1153  0
1154  );
1155 
1156  val2buf(&final_val[0]);
1157 
1158  }
1159  }
1160  else if( UINT16 == dap_type) {
1161  vector<unsigned short>total_val;
1162  total_val.resize(at_total_nelms);
1163  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1164 
1165  vector<unsigned short>final_val;
1166  subset<unsigned short>(
1167  &total_val[0],
1168  at_ndims,
1169  at_dims,
1170  at_offset,
1171  at_step,
1172  at_count,
1173  &final_val,
1174  at_pos,
1175  0
1176  );
1177 
1178  val2buf(&final_val[0]);
1179 
1180  }
1181  else if(UINT32 == dap_type) {
1182  vector<unsigned int>total_val;
1183  total_val.resize(at_total_nelms);
1184  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1185 
1186  vector<unsigned int>final_val;
1187  subset<unsigned int>(
1188  &total_val[0],
1189  at_ndims,
1190  at_dims,
1191  at_offset,
1192  at_step,
1193  at_count,
1194  &final_val,
1195  at_pos,
1196  0
1197  );
1198  val2buf(&final_val[0]);
1199 
1200 
1201  }
1202  else if(INT32 == dap_type) {
1203  vector<int>total_val;
1204  total_val.resize(at_total_nelms);
1205  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1206 
1207  vector<int>final_val;
1208  subset<int>(
1209  &total_val[0],
1210  at_ndims,
1211  at_dims,
1212  at_offset,
1213  at_step,
1214  at_count,
1215  &final_val,
1216  at_pos,
1217  0
1218  );
1219 
1220  val2buf(&final_val[0]);
1221 
1222  }
1223  else if(FLOAT32 == dap_type) {
1224  vector<float>total_val;
1225  total_val.resize(at_total_nelms);
1226  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1227 
1228  vector<float>final_val;
1229  subset<float>(
1230  &total_val[0],
1231  at_ndims,
1232  at_dims,
1233  at_offset,
1234  at_step,
1235  at_count,
1236  &final_val,
1237  at_pos,
1238  0
1239  );
1240 
1241  val2buf(&final_val[0]);
1242 
1243  }
1244  else if(FLOAT64 == dap_type) {
1245  vector<double>total_val;
1246  total_val.resize(at_total_nelms);
1247  memcpy(&total_val[0],src,at_total_nelms*at_base_type_size);
1248 
1249  vector<double>final_val;
1250  subset<double>(
1251  &total_val[0],
1252  at_ndims,
1253  at_dims,
1254  at_offset,
1255  at_step,
1256  at_count,
1257  &final_val,
1258  at_pos,
1259  0
1260  );
1261 #if 0
1262  //field->val2buf(&final_val[0]);
1263 #endif
1264  val2buf(&final_val[0]);
1265 
1266  }
1267  else {
1268  H5Tclose(at_base_type);
1269  throw InternalErr (__FILE__, __LINE__,
1270  "Non-supported integer or float datatypes");
1271  }
1272 
1273  }
1274  }
1275  else if(H5T_STRING == array_cls) {
1276 
1277  // set the original position to the starting point
1278  vector<int>at_pos(at_ndims,0);
1279  for (int i = 0; i< at_ndims; i++)
1280  at_pos[i] = at_offset[i];
1281 
1282  vector<string>total_strval;
1283  total_strval.resize(at_total_nelms);
1284 
1285  if(true == H5Tis_variable_str(at_base_type)) {
1286  void *src = (void*)(&values[0]+values_offset);
1287  char*temp_bp =(char*)src;
1288  for(int i = 0;i <at_total_nelms; i++){
1289  string tempstrval;
1290  get_vlen_str_data(temp_bp,tempstrval);
1291  total_strval[i] = tempstrval;
1292  temp_bp += at_base_type_size;
1293  }
1294  if(at_total_nelms == at_nelms) {
1295 #if 0
1296  //field->set_value(total_strval,at_total_nelms);
1297 #endif
1298  set_value(total_strval,at_total_nelms);
1299  }
1300  else {// obtain subset for variable-length string.
1301 #if 0
1302  //field->val2buf(&values[0] + values_offset);
1303 #endif
1304  vector<string>final_val;
1305  subset<string>(
1306  &total_strval[0],
1307  at_ndims,
1308  at_dims,
1309  at_offset,
1310  at_step,
1311  at_count,
1312  &final_val,
1313  at_pos,
1314  0
1315  );
1316 
1317  set_value(final_val,at_nelms);
1318 
1319  }
1320 
1321  }
1322  else {// For fixed-size string.
1323  void *src = (void*)(&values[0]+values_offset);
1324  for(int i = 0; i <at_total_nelms; i++)
1325  total_strval[i].resize(at_base_type_size);
1326 
1327  vector<char> str_val;
1328  str_val.resize(at_total_nelms*at_base_type_size);
1329  memcpy((void*)&str_val[0],src,at_total_nelms*at_base_type_size);
1330  string total_in_one_string(str_val.begin(),str_val.end());
1331  for(int i = 0; i<at_total_nelms;i++)
1332  total_strval[i] = total_in_one_string.substr(i*at_base_type_size,at_base_type_size);
1333 
1334  if(at_total_nelms == at_nelms)
1335  set_value(total_strval,at_total_nelms);
1336  else {
1337  vector<string>final_val;
1338  subset<string>(
1339  &total_strval[0],
1340  at_ndims,
1341  at_dims,
1342  at_offset,
1343  at_step,
1344  at_count,
1345  &final_val,
1346  at_pos,
1347  0
1348  );
1349  set_value(final_val,at_nelms);
1350 
1351  }
1352  }
1353 
1354  }
1355  else {
1356  H5Tclose(at_base_type);
1357  throw InternalErr (__FILE__, __LINE__,
1358  "Only support the field of compound datatype when the field type class is integer, float, string, array or compound..");
1359 
1360  }
1361 
1362  H5Tclose(at_base_type);
1363 
1364  return true;
1365 }
1366 
1368 inline int
1369 HDF5Array::INDEX_nD_TO_1D (const std::vector < int > &dims,
1370  const std::vector < int > &pos)
1371 {
1372  //
1373  // "int a[10][20][30] // & a[1][2][3] == a + (20*30+1 + 30*2 + 1 *3)"
1374  // "int b[10][2]; // &b[1][2] == b + (20*1 + 2);"
1375  //
1376  assert (dims.size () == pos.size ());
1377  int sum = 0;
1378  int start = 1;
1379 
1380  for (unsigned int p = 0; p < pos.size (); p++) {
1381  int m = 1;
1382 
1383  for (unsigned int j = start; j < dims.size (); j++)
1384  m *= dims[j];
1385  sum += m * pos[p];
1386  start++;
1387  }
1388  return sum;
1389 }
1390 
1391 // Obtain the dimension index of the next pos. of the point based on the offset, step and end
1392 bool HDF5Array::obtain_next_pos(vector<int>& pos, vector<int>&start,vector<int>&end,vector<int>&step,int rank_change) {
1393 
1394  if((pos[rank_change-1] + step[rank_change-1])<=end[rank_change-1]) {
1395  pos[rank_change-1] = pos[rank_change-1] + step[rank_change-1];
1396  return true;
1397  }
1398  else {
1399  if( 1 == rank_change)
1400  return false;
1401  pos[rank_change-1] = start[rank_change-1];
1402  obtain_next_pos(pos,start,end,step,rank_change-1);
1403  }
1404  return true;
1405 }
1406 
1408 //
1409 // \param input Input variable
1410 // \param dim dimension info of the input
1411 // \param start start indexes of each dim
1412 // \param stride stride of each dim
1413 // \param edge count of each dim
1414 // \param poutput output variable
1415 // \parrm index dimension index
1416 // \return 0 if successful. -1 otherwise.
1417 //
1418 template<typename T>
1419 int HDF5Array::subset(
1420  const T input[],
1421  int rank,
1422  vector<int> & dim,
1423  int start[],
1424  int stride[],
1425  int edge[],
1426  std::vector<T> *poutput,
1427  vector<int>& pos,
1428  int index)
1429 {
1430  for(int k=0; k<edge[index]; k++)
1431  {
1432  pos[index] = start[index] + k*stride[index];
1433  if(index+1<rank)
1434  subset(input, rank, dim, start, stride, edge, poutput,pos,index+1);
1435  if(index==rank-1)
1436  {
1437  poutput->push_back(input[INDEX_nD_TO_1D( dim, pos)]);
1438  }
1439  } // end of for
1440  return 0;
1441 } // end of template<typename T> static int subset
1442 
1443 
1444 // public functions to set all parameters needed in read function.
1445 
1446 
1447 void HDF5Array::set_memneed(size_t need) {
1448  d_memneed = need;
1449 }
1450 
1451 void HDF5Array::set_numdim(int ndims) {
1452  d_num_dim = ndims;
1453 }
1454 
1455 void HDF5Array::set_numelm(int nelms) {
1456  d_num_elm = nelms;
1457 }
1458 
1459 hid_t HDF5Array::mkstr(int size, H5T_str_t pad)
1460 {
1461 
1462  hid_t str_type;
1463 
1464  if ((str_type = H5Tcopy(H5T_C_S1)) < 0)
1465  return -1;
1466  if (H5Tset_size(str_type, (size_t) size) < 0)
1467  return -1;
1468  if (H5Tset_strpad(str_type, pad) < 0)
1469  return -1;
1470 
1471  return str_type;
1472 }
1473 
1474 // We don't inherit libdap Array Class's transform_to_dap4 method since CF option is still using it.
1475 BaseType* HDF5Array::h5dims_transform_to_dap4(D4Group *grp,const vector<string> &dimpath) {
1476 
1477  BESDEBUG("h5", "<h5dims_transform_to_dap4" << endl);
1478 
1479  if(grp == NULL)
1480  return NULL;
1481 
1482  Array *dest = static_cast<HDF5Array*>(ptr_duplicate());
1483 
1484  // If there is just a size, don't make
1485  // a D4Dimension (In DAP4 you cannot share a dimension unless it has
1486  // a name). jhrg 3/18/14
1487 
1488  int k = 0;
1489  for (Array::Dim_iter d = dest->dim_begin(), e = dest->dim_end(); d != e; ++d) {
1490 
1491  if (false == (*d).name.empty()) {
1492  BESDEBUG("h5", "<coming to the dimension loop, has name " << (*d).name<<endl);
1493  BESDEBUG("h5", "<coming to the dimension loop, has dimpath " << dimpath[k] <<endl);
1494  BESDEBUG("h5", "<coming to the dimension loop, has dimpath group " << dimpath[k].substr(0,dimpath[k].find_last_of("/")+1) <<endl);
1495 
1496  D4Group *temp_grp = grp;
1497  D4Dimension *d4_dim = NULL;
1498  bool is_dim_nonc4_grp = false;
1499 
1500  while(temp_grp) {
1501 
1502  BESDEBUG("h5", "<coming to the group has name " << temp_grp->name()<<endl);
1503  BESDEBUG("h5", "<coming to the group has fullpath " << temp_grp->FQN()<<endl);
1504 
1505  //Obtain all the dimensions of this group.
1506  D4Dimensions *temp_dims = temp_grp->dims();
1507 
1508  // Check if this dimension is defined in this group
1509  d4_dim = temp_dims->find_dim((*d).name);
1510 
1511  // Need the full path of the dimension name
1512  string d4_dim_path = dimpath[k].substr(0,dimpath[k].find_last_of("/")+1);
1513  BESDEBUG("h5", "d4_dim_path is " << d4_dim_path<<endl);
1514 
1515  bool ancestor_grp = false;
1516 
1517  // If the dim_path is within this group or its ancestor, this is valid.
1518  if(d4_dim_path.find(temp_grp->FQN())==0 || temp_grp->FQN().find(d4_dim_path)==0)
1519  ancestor_grp = true;
1520 
1521  // If we find this dimension and the dimension is on the ancestral path,
1522  // this follows the netCDF-4/DAP4 dimension model, break.
1523  if(d4_dim && (temp_grp->FQN() == d4_dim_path)) {
1524  BESDEBUG("h5", "<FInd dimension name " << (*d).name<<endl);
1525  (*d).dim = d4_dim;
1526  is_dim_nonc4_grp = false;
1527  break;
1528  }
1529  // If the dimension name is not on the ancestral path, this
1530  // dimension must be on another path, mark it.
1531  //else if( ancestor_grp == false && is_dim_nonc4_grp == false) {
1532  else if( ancestor_grp == false) {
1533  is_dim_nonc4_grp = true;
1534  break;
1535  }
1536  else
1537  d4_dim = NULL;
1538 
1539  if(temp_grp->get_parent())
1540  temp_grp = static_cast<D4Group*>(temp_grp->get_parent());
1541  else
1542  temp_grp = 0;
1543 
1544  }
1545 
1546  // Not find this dimension in any of the ancestor groups, add it to this group.
1547  // The following block is fine, but to avoid the complaint from sonarcloud.
1548  // Use a bool.
1549  if(true == is_dim_nonc4_grp) {
1550  string err= "The variable " + var_path +" has dimension ";
1551  err += dimpath[k] + ". This dimension is not under its ancestor or the current group.";
1552  err += " This is not supported.";
1553  delete dest;
1554  throw InternalErr(__FILE__,__LINE__,err);
1555  }
1556 
1557  bool d4_dim_null = ((d4_dim==NULL)?true:false);
1558  if(d4_dim_null == true) {
1559  d4_dim = new D4Dimension((*d).name, (*d).size);
1560  D4Dimensions * dims = grp->dims();
1561  BESDEBUG("h5", "<Just before adding D4 dimension to group" << endl);
1562  dims->add_dim_nocopy(d4_dim);
1563  (*d).dim = d4_dim;
1564  }
1565  }
1566  k++;
1567  }
1568 
1569  dest->set_is_dap4(true);
1570 
1571  return dest;
1572 
1573 }
A class for handling all types of array in HDF5 for the default option.
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.
virtual libdap::BaseType * ptr_duplicate()
Definition: HDF5Array.cc:54
virtual bool read()
Reads HDF5 array data into local buffer.
Definition: HDF5Array.cc:115
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:1451
HDF5Array(const std::string &n, const std::string &d, libdap::BaseType *v)
Constructor.
Definition: HDF5Array.cc:58
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
int get_slabdata(hid_t dset, int *offset, int *step, int *count, int num_dim, void *buf)
Definition: h5common.cc:144
void get_data(hid_t dset, void *buf)
Definition: h5common.cc:50
void get_strdata(int strindex, char *allbuf, char *buf, int elesize)
Definition: h5common.cc:115
bool check_h5str(hid_t h5type)
Definition: h5get.cc:685
string get_dap_type(hid_t type, bool is_dap4)
Definition: h5get.cc:285
const int DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:65