OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
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-2013 The HDF Group, Inc. and OPeNDAP, Inc.
8 //
9 // This is free 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 <debug.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 
54  return new HDF5Array(*this);
55 }
56 
57 HDF5Array::HDF5Array(const string & n, const string &d, BaseType * v) :
58  Array(n, d, v) {
59 }
60 
62  // Here we should release the resource for dataset and datatype
63  // It doesn't work. Strangely even generating DDS calls this function.
64  // Need to understand. KY 2011-11-17
65 
66  // H5Tclose(d_ty_id);
67  //cerr <<"coming to array destructor \n" <<endl;
68  // H5Dclose(d_dset_id);
69 }
70 
71 int HDF5Array::format_constraint(int *offset, int *step, int *count) {
72  long nels = 1;
73  int id = 0;
74 
75  Dim_iter p = dim_begin();
76 
77  while (p != dim_end()) {
78 
79  int start = dimension_start(p, true);
80  int stride = dimension_stride(p, true);
81  int stop = dimension_stop(p, true);
82 
83  // Check for empty constraint
84  if (stride <= 0 || start < 0 || stop < 0 || start > stop) {
85  ostringstream oss;
86 
87  oss << "Array/Grid hyperslab indices are bad: [" << start <<
88  ":" << stride << ":" << stop << "]";
89  throw Error(malformed_expr, oss.str());
90  }
91 
92  offset[id] = start;
93  step[id] = stride;
94  count[id] = ((stop - start) / stride) + 1; // count of elements
95  nels *= count[id]; // total number of values for variable
96 
97  DBG(cerr
98  << "=format_constraint():"
99  << "id=" << id << " offset=" << offset[id]
100  << " step=" << step[id]
101  << " count=" << count[id]
102  << endl);
103 
104  id++;
105  p++;
106  }
107 
108  return nels;
109 }
110 
111 bool HDF5Array::m_array_of_structure() {
112  DBG(cerr << "=read() Array of Structure length=" << length() << endl);
113 
114  vector<int> offset(d_num_dim);
115  vector<int> count(d_num_dim);
116  vector<int> step(d_num_dim);
117  int nelms = format_constraint(&offset[0], &step[0], &count[0]);
118 
119  // Honor constraint evaluation here.
120  vector<int> picks(nelms);
121  int total_elems =
122  linearize_multi_dimensions(&offset[0], &step[0], &count[0], &picks[0]);
123 
124  HDF5Structure *p = static_cast < HDF5Structure * >(var());
125  if (!p) {
126  throw InternalErr(__FILE__, __LINE__, "Not a HDF5Structure");
127  }
128 
129  p->set_array_size(nelms);
130  p->set_entire_array_size(total_elems);
131 
132  // Set the vector.
133  for (int i = 0; i < p->get_array_size(); i++) {
134  p->set_array_index(picks[i]);
135  set_vec(i, p);
136  }
137 
138  set_read_p(true);
139 
140  // Release the handles will cause problems. Need to understand. KY 2011-11-17
141 #if 0
142  if (H5Tclose(d_ty_id) < 0) {
143  throw InternalErr(__FILE__, __LINE__, "Unable to close the datatype.");
144  }
145  if (H5Dclose(d_dset_id) < 0) {
146  throw InternalErr(__FILE__, __LINE__, "Unable to close the dset.");
147  }
148 #endif
149 
150 
151 
152 //cerr <<"before reading "<<endl;
153  return false;
154 }
155 
156 // This private method makes a simple array and inserts it into the
157 // H5T_COMPOUND variable/object that was made at the start of
158 // m_array_in_structure(). This method is run for side effect only.
159 void HDF5Array::m_insert_simple_array(hid_t s1_tid, hsize_t *size2) {
160  int size = d_memneed / length();
161  hid_t s1_array2 = -1;
162  if (d_type == H5T_INTEGER) {
163  if (size == 1) {
164  s1_array2
165  = H5Tarray_create(H5T_NATIVE_CHAR, d_num_dim,
166  size2);
167  }
168  if (size == 2) {
169  s1_array2 = H5Tarray_create(H5T_NATIVE_SHORT,
170  d_num_dim, size2);
171  }
172  if (size == 4) {
173  s1_array2
174  = H5Tarray_create(H5T_NATIVE_INT, d_num_dim,
175  size2);
176  }
177  if(s1_array2 < 0){
178  throw InternalErr(__FILE__, __LINE__,
179  "H5Tarray_create failed for H5T_INTEGER.");
180  }
181  }
182 
183  if (d_type == H5T_FLOAT) {
184  if (size == 4) {
185  s1_array2 = H5Tarray_create(H5T_NATIVE_FLOAT,
186  d_num_dim, size2);
187  }
188  if (size == 8) {
189  s1_array2 = H5Tarray_create(H5T_NATIVE_DOUBLE,
190  d_num_dim, size2);
191  }
192  if(s1_array2 < 0){
193  throw InternalErr(__FILE__, __LINE__,
194  "H5Tarray_create failed for H5T_FLOAT.");
195  }
196 
197  }
198 
199  if (d_type == H5T_STRING) {
200  DBG(cerr << "string array is detected" << endl);
201  hid_t str_type = mkstr(size, H5T_STR_SPACEPAD);
202  s1_array2 = H5Tarray_create(str_type, d_num_dim, size2);
203  if(s1_array2 < 0){
204  throw InternalErr(__FILE__, __LINE__,
205  "H5Tarray_create failed for H5T_STRING.");
206  }
207  }
208 
209  if(H5Tinsert(s1_tid, name().c_str(), 0, s1_array2) < 0){
210  throw InternalErr(__FILE__, __LINE__,
211  "H5Tinsert failed for " + name());
212  }
213  if(H5Tclose(s1_array2) < 0){
214  throw InternalErr(__FILE__, __LINE__,
215  "H5Tclose failed for " + name());
216  }
217 }
218 
219 // This method proceeds in two steps. First it builds a simple array and
220 // links it into a chain of H5 Compund objects, recording information about
221 // the size of that simple array. Then it reads the data for that array and
222 // loads it into this instance of HDF5Array.
223 bool HDF5Array::m_array_in_structure()
224 {
225  DBG(cerr << "=read() Array in Structure of length=" << length() << endl);
226 
227  int array_index = 0, array_size = 0, entire_array_size = 0;
228  hid_t s1_tid = H5Tcreate(H5T_COMPOUND, d_memneed);
229  if (s1_tid < 0) {
230  throw InternalErr(__FILE__, __LINE__, "H5Tcreate failed.");
231  }
232  // Build the simple array and record its size.
233 
234  // Construct an array read from the structure.
235  vector<hsize_t> size2(d_num_dim);
236  if (H5Tget_array_dims(d_ty_id, &size2[0]) < 0) {
237  H5Tclose(s1_tid);
238  throw InternalErr(__FILE__, __LINE__, "H5Tget_array_ndims failed.");
239  }
240 
241  // Grab the BaseType to this object's parent. If it's a constructor
242  // type, then look at the type of this array and insert a H5 array of
243  // the matching type in the H5 Compound object made above. Record
244  // information about the size of the array and its index, then go up
245  // to q's parent.
246  string parent_name;
247  BaseType *q = get_parent();
248  if (q && q->is_constructor_type()) { // Grid, structure or sequence
249 
250  m_insert_simple_array(s1_tid, &size2[0]);
251 
252  // Remember the last parent name.
253  parent_name = q->name();
254 
255  HDF5Structure &p = static_cast<HDF5Structure &> (*q);
256  // Remember the index of array from the parent.
257  array_index = p.get_array_index();
258  array_size = p.get_array_size();
259  entire_array_size = p.get_entire_array_size();
260 
261  q = q->get_parent();
262  }
263 
264  // Now iterate up the hierarchy of BaseTypes to the top (when we hit
265  // the top of the dataset get_parent() returns NULL). This code builds
266  // a chain of H5 Compound objects which ultimately link the stuff we
267  // just built to the top of the dataset.
268  while (q && q->is_constructor_type()) {
269  DBG(cerr << ": parent_name=" << parent_name << endl);
270 
271  hid_t stemp_tid = H5Tcreate(H5T_COMPOUND, d_memneed);
272  if (stemp_tid < 0) {
273  throw InternalErr(__FILE__, __LINE__, "H5Tcreate failed.");
274  }
275  if (H5Tinsert(stemp_tid, parent_name.c_str(), 0, s1_tid) < 0) {
276  H5Tclose(stemp_tid);
277  throw InternalErr(__FILE__, __LINE__, "H5Tinsert failed.");
278  }
279  s1_tid = stemp_tid;
280 
281  // Remember the last parent name.
282  parent_name = q->name();
283 
284  HDF5Structure &p = static_cast<HDF5Structure &> (*q);
285  // Remember the index of array from the parent.
286  array_index = p.get_array_index();
287  array_size = p.get_array_size();
288  entire_array_size = p.get_entire_array_size();
289 
290  q = q->get_parent();
291  }
292 
293  DBG(cerr << "=read() parent's element count=" << array_size << endl);
294  DBG(cerr << "=read() parent's entire element count=" << entire_array_size << endl);
295  DBG(cerr << "=read() parent's index=" << array_index << endl);
296 
297  // Read data from the HDF5 file and load those values into this instance.
298  // Allocate enough buffer for entire array to be read.
299  if (!entire_array_size){
300  H5Tclose(s1_tid);
301  throw InternalErr(__FILE__, __LINE__, "entire_array_size is zero.");
302  }
303  vector<char> buf(entire_array_size * d_memneed);
304 
305  if (H5Dread(d_dset_id, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, static_cast<void*> (&buf[0])) < 0){
306  H5Tclose(s1_tid);
307  H5Dclose(d_dset_id);
308  throw InternalErr(__FILE__, __LINE__, "H5Dread failed.");
309  }
310 
311  if (H5Tclose(s1_tid) < 0)
312  throw InternalErr(__FILE__, __LINE__, "H5Tclose failed.");
313 
314  // Originally, this code used entire_array_size, but it looks like
315  // array_size will do. jhrg 4/15/08
316  if (!array_size) {
317  throw InternalErr(__FILE__, __LINE__, "array_size is zero");
318  }
319  vector<char> convbuf(array_size * d_memneed);
320 
321  for (int l = 0; l < array_size; l++) {
322  for (int i = 0; i < (int) d_memneed; i++) {
323  convbuf[l * d_memneed + i] = buf[array_index * d_memneed + i];
324  }
325  }
326 
327  // Treat string differently with vector of strings.
328  if (d_type == H5T_STRING) {
329  vector<string> v_str(d_num_elm);
330  int size = d_memneed / length();
331  vector<char> strbuf(size + 1);
332  for (int strindex = 0; strindex < d_num_elm; strindex++) {
333  get_strdata(strindex, &convbuf[0], &strbuf[0], size);
334  DBG(cerr << "=read()<get_strdata() strbuf=" << &strbuf[0] << endl);
335  v_str[strindex] = &strbuf[0];
336  }
337  set_read_p(true);
338  val2buf((void *) &v_str[0]);
339  }
340  else {
341  set_read_p(true);
342  val2buf((void *) &convbuf[0]);
343  }
344 
345  return false;
346 }
347 
348 // Haven't checked the codes and comments
349 // Haven't added the close handles routines for error handlings yet. KY 2011-11-18
350 bool HDF5Array::m_array_of_reference()
351 {
352  try {
353  vector<int> offset(d_num_dim);
354  vector<int> count(d_num_dim);
355  vector<int> step(d_num_dim);
356 
357 
358  int nelms = format_constraint(&offset[0], &step[0], &count[0]); // Throws Error.
359  vector<string> v_str(nelms);
360 
361  DBG(cerr << "=read() URL type is detected. "
362  << "nelms=" << nelms << " full_size=" << d_num_elm << endl);
363 
364  // Handle regional reference.
365  if (H5Tequal(d_ty_id, H5T_STD_REF_DSETREG) < 0) {
366  throw InternalErr(__FILE__, __LINE__, "H5Tequal() failed");
367  }
368 
369  if (H5Tequal(d_ty_id, H5T_STD_REF_DSETREG) > 0) {
370  DBG(cerr << "=read() Got regional reference. " << endl);
371  // FIXME rbuf leaked
372  // Vector doesn't work for this case. somehow it doesn't support the type.
373  hdset_reg_ref_t *rbuf = new hdset_reg_ref_t[d_num_elm];
374 // vector<hdset_reg_ref_t> rbuf;
375  // rbuf.resize(d_num_elm);
376  if(rbuf == NULL){
377  throw InternalErr(__FILE__, __LINE__, "new() failed.");
378  }
379  if (H5Dread(d_dset_id, H5T_STD_REF_DSETREG, H5S_ALL, H5S_ALL, H5P_DEFAULT, &rbuf[0]) < 0) {
380  throw InternalErr(__FILE__, __LINE__, "H5Dread() failed.");
381  }
382 
383  for (int i = 0; i < nelms; i++) {
384  // Let's assume that URL array is always 1 dimension.
385  DBG(cerr << "=read() rbuf[" << i << "]" <<
386  rbuf[offset[0] + i * step[0]] << endl);
387 
388  if (rbuf[offset[0] + i * step[0]][0] != '\0') {
389  char name[DODS_NAMELEN];
390 
391  hid_t did_r = H5Rdereference(d_dset_id, H5R_DATASET_REGION, rbuf[offset[0] + i * step[0]]);
392  if (did_r < 0) {
393  throw InternalErr(__FILE__, __LINE__, "H5Rdereference() failed.");
394 
395  }
396 
397  if (H5Iget_name(did_r, (char *) name, DODS_NAMELEN) < 0) {
398  throw InternalErr(__FILE__, __LINE__, "H5Iget_name() failed.");
399  }
400  DBG(cerr << "=read() dereferenced name is " << name
401  << endl);
402 
403  string varname(name);
404  hid_t space_id = H5Rget_region(did_r, H5R_DATASET_REGION, rbuf[offset[0] + i * step[0]]);
405  if (space_id < 0) {
406  throw InternalErr(__FILE__, __LINE__, "H5Rget_region() failed.");
407 
408  }
409 
410  int ndim = H5Sget_simple_extent_ndims(space_id);
411  if (ndim < 0) {
412  throw InternalErr(__FILE__, __LINE__, "H5Sget_simple_extent_ndims() failed.");
413  }
414 
415  DBG(cerr << "=read() dim is " << ndim << endl);
416 
417  string expression;
418  switch (H5Sget_select_type(space_id)) {
419 
420  case H5S_SEL_NONE:
421  DBG(cerr << "=read() None selected." << endl);
422  break;
423 
424  case H5S_SEL_POINTS: {
425  DBG(cerr << "=read() Points selected." << endl);
426  hssize_t npoints = H5Sget_select_npoints(space_id);
427  if (npoints < 0) {
428  throw InternalErr(__FILE__, __LINE__,
429  "Cannot determine number of elements in the dataspace selection");
430  }
431 
432  DBG(cerr << "=read() npoints are " << npoints
433  << endl);
434  vector<hsize_t> buf(npoints * ndim);
435  if (H5Sget_select_elem_pointlist(space_id, 0, npoints, &buf[0]) < 0) {
436  throw InternalErr(__FILE__, __LINE__, "H5Sget_select_elem_pointlist() failed.");
437  }
438 
439 #ifdef DODS_DEBUG
440  for (int j = 0; j < npoints * ndim; j++) {
441  cerr << "=read() npoints buf[0] =" << buf[j] <<endl;
442  }
443 #endif
444 
445  for (int j = 0; j < (int) npoints; j++) {
446  // Name of the dataset.
447  expression.append(varname);
448  for (int k = 0; k < ndim; k++) {
449  ostringstream oss;
450  oss << "[" << (int) buf[j * ndim + k] << "]";
451  expression.append(oss.str());
452  }
453  if (j != (int) (npoints - 1)) {
454  expression.append(",");
455  }
456  }
457  v_str[i].append(expression);
458 
459  break;
460  }
461  case H5S_SEL_HYPERSLABS: {
462  vector<hsize_t> start(ndim);
463  vector<hsize_t> end(ndim);
464 
465  DBG(cerr << "=read() Slabs selected." << endl);
466  DBG(cerr << "=read() nblock is " <<
467  H5Sget_select_hyper_nblocks(space_id) << endl);
468 
469  if (H5Sget_select_bounds(space_id, &start[0], &end[0]) < 0) {
470  throw InternalErr(__FILE__, __LINE__, "H5Sget_select_bounds() failed.");
471  }
472 
473  for (int j = 0; j < ndim; j++) {
474  ostringstream oss;
475  DBG(cerr << "=read() start is " << start[j]
476  << "=read() end is " << end[j] << endl);
477  oss << "[" << (int) start[j] << ":" << (int) end[j] << "]";
478  expression.append(oss.str());
479  DBG(cerr << "=read() expression is "
480  << expression << endl)
481  ;
482  }
483  v_str[i] = varname;
484  if (!expression.empty()) {
485  v_str[i].append(expression);
486  }
487  // Constraint expression. [start:1:end]
488  break;
489  }
490  case H5S_SEL_ALL:
491  DBG(cerr << "=read() All selected." << endl);
492  break;
493 
494  default:
495  DBG(cerr << "Unknown space type." << endl);
496  break;
497  }
498 
499  }
500  else {
501  v_str[i] = "";
502  }
503  }
504  delete[] rbuf;
505  }
506 
507  // Handle object reference.
508  if (H5Tequal(d_ty_id, H5T_STD_REF_OBJ) < 0) {
509  throw InternalErr(__FILE__, __LINE__, "H5Tequal() failed.");
510  }
511 
512  if (H5Tequal(d_ty_id, H5T_STD_REF_OBJ) > 0) {
513  DBG(cerr << "=read() Got object reference. " << endl);
514  vector<hobj_ref_t> rbuf;
515  rbuf.resize(d_num_elm);
516  if (H5Dread(d_dset_id, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, &rbuf[0]) < 0) {
517  throw InternalErr(__FILE__, __LINE__, "H5Dread failed()");
518  }
519 
520  for (int i = 0; i < nelms; i++) {
521  // Let's assume that URL array is always 1 dimension.
522  hid_t did_r = H5Rdereference(d_dset_id, H5R_OBJECT, &rbuf[offset[0] + i * step[0]]);
523  if (did_r < 0) {
524  throw InternalErr(__FILE__, __LINE__, "H5Rdereference() failed.");
525  }
526  char name[DODS_NAMELEN];
527  if (H5Iget_name(did_r, (char *) name, DODS_NAMELEN) < 0) {
528  throw InternalErr(__FILE__, __LINE__, "H5Iget_name() failed.");
529  }
530 
531  // Shorten the dataset name
532  string varname(name);
533 
534  DBG(cerr << "=read() dereferenced name is " << name <<endl);
535  v_str[i] = varname;
536  }
537  }
538  set_value(&v_str[0], nelms);
539  return false;
540  }
541  catch (...) {
542  throw;
543  }
544 }
545 
546 void HDF5Array::m_intern_plain_array_data(char *convbuf)
547 {
548  if (check_h5str(d_ty_id)) {
549  vector<string> v_str(d_num_elm);
550  size_t elesize = H5Tget_size(d_ty_id);
551  if (elesize == 0) {
552  throw InternalErr(__FILE__, __LINE__, "H5Tget_size() failed.");
553  }
554  vector<char> strbuf(elesize + 1);
555  DBG(cerr << "=read()<check_h5str() element size=" << elesize
556  << " d_num_elm=" << d_num_elm << endl);
557 
558  for (int strindex = 0; strindex < d_num_elm; strindex++) {
559  get_strdata(strindex, &convbuf[0], &strbuf[0], elesize);
560  DBG(cerr << "=read()<get_strdata() strbuf=" << &strbuf[0] << endl);
561  v_str[strindex] = &strbuf[0];
562  }
563  // They are supposed to be released at the HDF5Array destructor
564  // For some reason, it doesn't work. Release them at the end
565  // of the read function. KY 2011-11-17
566 #if 0
567  if(H5Tclose(d_ty_id) <0) {
568  throw InternalErr(__FILE__,__LINE__, "H5Tclose() failed.");
569 
570  }
571 
572  if (H5Dclose(d_dset_id) < 0) {
573  throw InternalErr(__FILE__, __LINE__, "H5Dclose() failed.");
574  };
575 #endif
576  set_read_p(true);
577  val2buf((void *) &v_str[0]);
578  }
579  else {
580  set_read_p(true);
581  val2buf((void *) convbuf);
582  }
583 }
584 
585 // SHOULD CHECK COMMENTS,CODES KY 2011-11-18
587 {
588  DBG(cerr
589  << ">read() dataset=" << dataset()
590  << " data_type_id=" << d_ty_id << " name=" << name()
591  << " get_dap_type=" << get_dap_type(d_ty_id)
592  << " dimension=" << d_num_dim
593  << " data_size=" << d_memneed << " length=" << length()
594  << endl);
595 
596  if (get_dap_type(d_ty_id) == "Structure") {
597  return m_array_of_structure();
598  }
599 
600  // This "Array" datatype is the HDF5 "Array" datatype. It should not be confused
601  // as the normal DAP way to handle a data array although essentially it is doing the same thing.
602  // If the "Array" datatype is never defined, this part of the code will never be executed.
603  // HDF5 "Array" datatype is defined inside an HDF5 compound datatype for very
604  // rare cases. It means that this part of code may never be used by most (99.9%) applications.
605  // Kyang 2009/11/23
606  if (get_dap_type(d_ty_id) == "Array") {
607  return m_array_in_structure();
608  }
609 
610  if (get_dap_type(d_ty_id) == "Url") {
611  return m_array_of_reference();
612  }
613  vector<int> offset(d_num_dim);
614  vector<int> count(d_num_dim);
615  vector<int> step(d_num_dim);
616  int nelms = format_constraint(&offset[0], &step[0], &count[0]); // Throws Error.
617 
618  if (H5Tis_variable_str(d_ty_id) && H5Tget_class(d_ty_id) == H5T_STRING) {
619 
620  bool status = read_vlen_string(d_dset_id, d_ty_id, nelms, &offset[0], &step[0], &count[0]);
621  return status;
622  }
623 
624  if (H5Tis_variable_str(d_ty_id) < 0) {
625  throw InternalErr(__FILE__, __LINE__, "H5Tis_variable_str() failed.");
626  }
627  if (H5Tget_class(d_ty_id) < 0) {
628  throw InternalErr(__FILE__, __LINE__, "H5Tget_class() failed.");
629  }
630 
631  if (nelms == d_num_elm) {
632  vector<char> convbuf(d_memneed);
633  get_data(d_dset_id, (void *) &convbuf[0]);
634 
635  // Check if a Signed Byte to Int16 conversion is necessary.
636 
637  if (1 == H5Tget_size(d_ty_id) && H5T_SGN_2 == H5Tget_sign(d_ty_id))
638  {
639  vector<short> convbuf2(nelms);
640  for (int i = 0; i < nelms; i++) {
641  convbuf2[i] = (signed char) (convbuf[i]);
642  DBG(cerr << "convbuf[" << i << "]="
643  << (signed char)convbuf[i] << endl);
644  DBG(cerr << "convbuf2[" << i << "]="
645  << convbuf2[i] << endl)
646  ;
647  }
648  // Libdap will generate the wrong output.
649  m_intern_plain_array_data((char*) &convbuf2[0]);
650  //delete[] convbuf2;
651  }
652  else
653  m_intern_plain_array_data(&convbuf[0]);
654  } // if (nelms == d_num_elm)
655  else {
656  size_t data_size = nelms * H5Tget_size(d_ty_id);
657  if (data_size == 0)
658  throw InternalErr(__FILE__, __LINE__, "get_size failed");
659  vector<char> convbuf(data_size);
660  get_slabdata(d_dset_id, &offset[0], &step[0], &count[0], d_num_dim, &convbuf[0]);
661 
662  // Check if a Signed Byte to Int16 conversion is necessary.
663  if (get_dap_type(d_ty_id) == "Int8") {
664  vector<short> convbuf2(data_size);
665  for (int i = 0; i < (int)data_size; i++) {
666  convbuf2[i] = static_cast<signed char> (convbuf[i]);
667  }
668  m_intern_plain_array_data((char*) &convbuf2[0]);
669  //delete[] convbuf2;
670  }
671  else {
672  m_intern_plain_array_data(&convbuf[0]);
673  }
674 
675  //delete[] convbuf;
676  }
677 
678  // release the handlers
679  H5Dclose(d_dset_id);
680  H5Tclose(d_ty_id);
681  return true;
682 }
683 
684 // public functions to set all parameters needed in read function.
685 
686 void HDF5Array::set_did(hid_t dset) {
687  d_dset_id = dset;
688 }
689 
690 void HDF5Array::set_tid(hid_t type) {
691  d_ty_id = type;
692 }
693 
694 void HDF5Array::set_memneed(size_t need) {
695  d_memneed = need;
696 }
697 
698 void HDF5Array::set_numdim(int ndims) {
699  d_num_dim = ndims;
700 }
701 
702 void HDF5Array::set_numelm(int nelms) {
703  d_num_elm = nelms;
704 }
705 
707  return d_dset_id;
708 }
709 
711  return d_ty_id;
712 }
713 
714 int HDF5Array::linearize_multi_dimensions(int *start, int *stride, int *count, int *picks)
715 {
716  DBG(cerr << ">linearize_multi_dimensions()" << endl);
717  int total = 1;
718  int id = 0;
719  vector<int> dim(d_num_dim);
720  Dim_iter p2 = dim_begin();
721 
722  while (p2 != dim_end()) {
723  int a_size = dimension_size(p2, false); // unconstrained size
724  DBG(cerr << "dimension[" << id << "] = " << a_size << endl);
725  dim[id] = a_size;
726  total = total * a_size;
727  ++id;
728  ++p2;
729  }
730 
731  vector<int> temp_count(d_num_dim);
732  int temp_index;
733  int i;
734  int array_index = 0;
735  int temp_count_dim = 0; // This variable changes when dim. is added.
736  int temp_dim = 1;
737 
738  for (i = 0; i < d_num_dim; i++)
739  temp_count[i] = 1;
740 
741  int num_ele_so_far = 0;
742  int total_ele = 1;
743  for (i = 0; i < d_num_dim; i++)
744  total_ele = total_ele * count[i];
745 
746  while (num_ele_so_far < total_ele) {
747  // loop through the index
748 
749  while (temp_count_dim < d_num_dim) {
750  temp_index = (start[d_num_dim - 1 - temp_count_dim] + (temp_count[d_num_dim - 1 - temp_count_dim] - 1)
751  * stride[d_num_dim - 1 - temp_count_dim]) * temp_dim;
752  array_index = array_index + temp_index;
753  temp_dim = temp_dim * dim[d_num_dim - 1 - temp_count_dim];
754  temp_count_dim++;
755  }
756 
757  picks[num_ele_so_far] = array_index;
758 
759  num_ele_so_far++;
760  // index can be added
761  DBG(cerr << "number of element looped so far = " <<
762  num_ele_so_far << endl);
763  for (i = 0; i < d_num_dim; i++) {
764  DBG(cerr << "temp_count[" << i << "]=" << temp_count[i] <<
765  endl)
766  ;
767  }
768  DBG(cerr << "index so far " << array_index << endl);
769 
770  temp_dim = 1;
771  temp_count_dim = 0;
772  array_index = 0;
773 
774  for (i = 0; i < d_num_dim; i++) {
775  if (temp_count[i] < count[i]) {
776  temp_count[i]++;
777  break;
778  }
779  else { // We reach the end of the dimension, set it to 1 and
780  // increase the next level dimension.
781  temp_count[i] = 1;
782  }
783  }
784  }
785 
786  DBG(cerr << "<linearize_multi_dimensions()" << endl);
787  return total;
788 }
789 
790 hid_t HDF5Array::mkstr(int size, H5T_str_t pad)
791 {
792 
793  hid_t type;
794 
795  if ((type = H5Tcopy(H5T_C_S1)) < 0)
796  return -1;
797  if (H5Tset_size(type, (size_t) size) < 0)
798  return -1;
799  if (H5Tset_strpad(type, pad) < 0)
800  return -1;
801 
802  return type;
803 }
804 
805 // Need checking code, comments KY-2011-11-18
806 bool HDF5Array::read_vlen_string(hid_t d_dset_id, hid_t d_ty_id, int nelms, int *offset, int *step, int *count)
807 {
808  DBG(cerr <<
809  "=read_vlen_string(): variable string is detected with nelms = "
810  << nelms << endl);
811  vector<char*> convbuf2(d_num_elm);
812  if (H5Dread(d_dset_id, d_ty_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, &convbuf2[0]) < 0) {
813  throw InternalErr(__FILE__, __LINE__, "H5Dread failed()");
814  }
815 
816  // Find the maximum size of the strings in convbuf2.
817  int size_max = 0;
818  for (int strindex = 0; strindex < d_num_elm; strindex++) {
819  if (convbuf2[strindex] != '\0') {
820  size_max = max(size_max, (int) strlen(convbuf2[strindex]));
821  }
822  }
823 
824  vector<char> strbuf(size_max + 1);
825  vector<string> v_str(d_num_elm);
826 
827  for (int strindex = 0; strindex < nelms; strindex++) {
828  memset(&strbuf[0], 0, size_max + 1);
829  // Let's assume that variable length array is 1 dimension.
830  int real_index = offset[0] + strindex * step[0];
831  if (convbuf2[real_index] != NULL) {
832  strncpy(&strbuf[0], convbuf2[real_index], size_max);
833  strbuf[size_max] = '\0';
834  v_str[strindex] = &strbuf[0];
835  DBG(cerr << "v_str" << v_str[strindex] << endl)
836  ;
837  }
838  else {
839  v_str[strindex] = &strbuf[0];
840  }
841  }
842 
843  if (H5Dclose(d_dset_id) < 0) {
844  throw InternalErr(__FILE__, __LINE__, "H5Dclose() failed.");
845  }
846  set_read_p(true);
847  set_value(v_str, d_num_elm);
848  return false;
849 }
void set_entire_array_size(int i)
returns the entire array size of this Structure if it's a part of array of structures.
hid_t get_tid()
returns HDF5 datatype id.
Definition: HDF5Array.cc:710
if(!(yy_init))
Definition: lex.gse.cc:752
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:694
This class converts HDF5 compound type into DAP structure for the default option. ...
HDF5Array(const string &n, const string &d, BaseType *v)
Constructor.
Definition: HDF5Array.cc:57
virtual bool read()
Reads HDF5 array data into local buffer.
Definition: HDF5Array.cc:586
H5T_class_t d_type
HDF5 data type class.
Definition: HDF5Array.h:79
string get_dap_type(hid_t type)
returns the string representation of HDF5 type.
Definition: h5get.cc:237
int get_array_index()
returns the array index of this Structure if it's a part of array of structures.
void set_numelm(int nelms)
remembers number of elements in this array.
Definition: HDF5Array.cc:702
STL namespace.
virtual BaseType * ptr_duplicate()
Clone this instance.
Definition: HDF5Array.cc:53
void set_array_size(int i)
remembers the array size for subsetting if it's a part of array of structures.
void get_data(hid_t dset, void *buf)
will get all data of a dset dataset and put it into buf.
Definition: h5get.cc:521
#define DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:43
bool read_vlen_string(hid_t d_dset_id, hid_t d_ty_id, int nelms, int *offset, int *step, int *count)
Reads HDF5 variable length string array data into local buffer.
Definition: HDF5Array.cc:806
hid_t get_did()
returns HDF5 dataset id.
Definition: HDF5Array.cc:706
bool check_h5str(hid_t h5type)
checks if type is HDF5 string type
Definition: h5get.cc:802
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:698
void set_array_index(int i)
remembers the array index of this Structure if it's a part of array of structures.
#define NULL
Definition: wcsUtil.h:65
This class that translates HDF5 string into DAP string for the default option.
void set_tid(hid_t type)
remembers HDF5 datatype id.
Definition: HDF5Array.cc:690
void get_strdata(int strindex, char *allbuf, char *buf, int elesize)
will get an individual string data from all string data elements and put it into buf.
Definition: h5get.cc:632
int get_array_size()
returns the array size for subsetting if it's a part of array of structures.
void set_did(hid_t dset)
remembers HDF5 dataset id.
Definition: HDF5Array.cc:686
int get_slabdata(hid_t dset, int *offset, int *step, int *count, int num_dim, void *buf)
will get hyperslab data of a dataset and put it into buf.
Definition: h5get.cc:661
int get_entire_array_size()
returns the entire array size of this Structure if it's a part of array of structures.
A class for handling all types of array in HDF5 for the default option.
#define max(a, b)
Definition: os_utils.h:67
virtual ~HDF5Array()
Definition: HDF5Array.cc:61