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