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 }
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:114
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:1450
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:1454
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:1446
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:621
string get_dap_type(hid_t type, bool is_dap4)
Definition: h5get.cc:272
const int DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:64