bes  Updated for version 3.20.6
sds.cc
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
2 
3 // Copyright (c) 2005 OPeNDAP, Inc.
4 // Author: James Gallagher <jgallagher@opendap.org>
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this software; if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 
23 // Copyright 1996, by the California Institute of Technology.
24 // ALL RIGHTS RESERVED. United States Government Sponsorship
25 // acknowledged. Any commercial use must be negotiated with the
26 // Office of Technology Transfer at the California Institute of
27 // Technology. This software may be subject to U.S. export control
28 // laws and regulations. By accepting this software, the user
29 // agrees to comply with all applicable U.S. export laws and
30 // regulations. User has the responsibility to obtain export
31 // licenses, or other export authority as may be required before
32 // exporting such information to foreign countries or providing
33 // access to foreign persons.
34 
35 // U.S. Government Sponsorship under NASA Contract
36 // NAS7-1260 is acknowledged.
37 //
38 // Author: Todd.K.Karakashian@jpl.nasa.gov
39 //
40 // $RCSfile: sds.cc,v $ - input stream class for HDF SDS
41 //
43 
44 #include "config_hdf.h"
45 
46 #include <mfhdf.h>
47 
48 #ifdef __POWERPC__
49 #undef isascii
50 #endif
51 
52 #include <string>
53 #include <vector>
54 #include <algorithm>
55 #include <functional>
56 #include <cerrno>
57 
58 #include <hcstream.h>
59 #include <hdfclass.h>
60 
61 #include <BESDebug.h>
62 
63 using std::cerr;
64 using std::endl;
65 
66 // minimum function
67 inline int min(int t1, int t2)
68 {
69  return (t1 < t2 ? t1 : t2);
70 }
71 
72 // static initializations
73 const string hdfistream_sds::long_name = "long_name";
74 const string hdfistream_sds::units = "units";
75 const string hdfistream_sds::format = "format";
76 
77 //
78 // protected member functions
79 //
80 
81 // initialize an hdfistream_sds, opening file if given
82 void hdfistream_sds::_init(void)
83 {
84  _sds_id = _attr_index = _dim_index = _nsds = _rank = _nattrs =
85  _nfattrs = 0;
86  _index = -1; // set BOS
87  _meta = _slab.set = false;
88  _map_ce_set = false;
89  return;
90 }
91 
92 // retrieve descriptive information about file containing SDS
93 void hdfistream_sds::_get_fileinfo(void)
94 {
95  if (SDfileinfo(_file_id, &_nsds, &_nfattrs) < 0)
96  THROW(hcerr_sdsinfo);
97  return;
98 }
99 
100 // retrieve descriptive information about currently open SDS
101 void hdfistream_sds::_get_sdsinfo(void)
102 {
103  char junk0[hdfclass::MAXSTR];
104  int32 junk1[hdfclass::MAXDIMS];
105  int32 junk2;
106 
107  // all we care about is rank and number of attributes
108  if (SDgetinfo(_sds_id, junk0, &_rank, junk1, &junk2, &_nattrs) < 0)
109  THROW(hcerr_sdsinfo);
110 
111  if (_rank > hdfclass::MAXDIMS) // too many dimensions
112  THROW(hcerr_maxdim);
113  return;
114 }
115 
116 // end access to currently open SDS
117 void hdfistream_sds::_close_sds(void)
118 {
119  if (_sds_id != 0) {
120  (void) SDendaccess(_sds_id);
121  _sds_id = _attr_index = _dim_index = _rank = _nattrs = 0;
122  _index = -1;
123  }
124  return;
125 }
126 
127 // find the next SDS array (not necessarily the next SDS) in the file
128 void hdfistream_sds::_seek_next_arr(void)
129 {
130  if (_sds_id != 0) {
131  BESDEBUG("h4", "hdfistream_sds::_seek_next_arr called with an open sds: "
132  << _sds_id << endl);
133  SDendaccess(_sds_id);
134  _sds_id = 0;
135  }
136 
137  for (_index++, _dim_index = _attr_index = 0; _index < _nsds; ++_index) {
138  if (_sds_id != 0) {
139  BESDEBUG("h4", "hdfistream_sds::_seek_next_arr inside for-loop with an open sds: "
140  << _sds_id << endl);
141  }
142  if ((_sds_id = SDselect(_file_id, _index)) < 0)
143  THROW(hcerr_sdsopen);
144  if (!SDiscoordvar(_sds_id))
145  break;
146  SDendaccess(_sds_id);
147  _sds_id = 0;
148  }
149 }
150 
151 // find the arr_index'th SDS array in the file (don't count non-array SDS's)
152 void hdfistream_sds::_seek_arr(int arr_index)
153 {
154  int arr_count = 0;
155  for (_rewind(); _index < _nsds && arr_count <= arr_index;
156  _seek_next_arr(), arr_count++);
157 }
158 
159 // find the SDS array with specified name
160 void hdfistream_sds::_seek_arr(const string & name)
161 {
162  if (_sds_id != 0) {
163  BESDEBUG("h4", "hdfistream_sds::_seek_arr called with an open sds: "
164  << _sds_id << endl);
165  _close_sds();
166  }
167 
168  int index;
169  const char *nm = name.c_str();
170  if ((index = SDnametoindex(_file_id, (char *) nm)) < 0)
171  THROW(hcerr_sdsfind);
172  if ((_sds_id = SDselect(_file_id, index)) < 0)
173  THROW(hcerr_sdsopen);
174  bool iscoord = SDiscoordvar(_sds_id);
175  if (iscoord) {
176  SDendaccess(_sds_id);
177  _sds_id = 0;
178  THROW(hcerr_sdsfind);
179  }
180  _index = index;
181  return;
182 }
183 
184 // find the SDS array with specified ref
185 void hdfistream_sds::_seek_arr_ref(int ref)
186 {
187  if (_sds_id != 0) {
188  BESDEBUG("h4", "hdfistream_sds::_seek_arr_ref called with an open sds: "
189  << _sds_id << endl);
190  _close_sds();
191  }
192 
193  int index;
194  if ((index = SDreftoindex(_file_id, ref)) < 0)
195  THROW(hcerr_sdsfind);
196  if ((_sds_id = SDselect(_file_id, index)) < 0)
197  THROW(hcerr_sdsopen);
198  bool iscoord = SDiscoordvar(_sds_id);
199  if (iscoord) {
200  SDendaccess(_sds_id);
201  _sds_id = 0;
202  THROW(hcerr_sdsfind);
203  }
204  _index = index;
205  return;
206 }
207 
208 //
209 // public member functions
210 //
211 
212 
213 // constructor
214 hdfistream_sds::hdfistream_sds(const string filename):
215 hdfistream_obj(filename)
216 {
217  _init();
218  if (_filename.length() != 0) // if ctor specified a file to open
219  open(_filename.c_str());
220  return;
221 }
222 
223 // check to see if stream has been positioned past last SDS in file
224 bool hdfistream_sds::eos(void) const
225 {
226  if (_filename.length() == 0) // no file open
227  THROW(hcerr_invstream);
228  if (_nsds == 0) // eos() is always true of there are no SDS's in file
229  return true;
230  else {
231  if (bos()) // eos() is never true if at bos() and there are SDS's
232  return false;
233  else
234  return (_index >= _nsds); // are we indexed past the last SDS?
235  }
236 }
237 
238 // check to see if stream is positioned in front of the first SDS in file
239 bool hdfistream_sds::bos(void) const
240 {
241  if (_filename.length() == 0) // no file open
242  THROW(hcerr_invstream);
243  if (_nsds == 0)
244  return true; // if there are no SDS's we still want to read file attrs so both eos() and bos() are true
245  if (_index == -1)
246  return true;
247  else
248  return false;
249 }
250 
251 // check to see if stream is positioned past the last attribute in the currently
252 // open SDS
253 bool hdfistream_sds::eo_attr(void) const
254 {
255  if (_filename.length() == 0) // no file open
256  THROW(hcerr_invstream);
257  if (eos() && !bos()) // if eos(), then always eo_attr()
258  return true;
259  else {
260  if (bos()) // are we at BOS and are positioned past last file attributes?
261  return (_attr_index >= _nfattrs);
262  else
263  return (_attr_index >= _nattrs); // or positioned after last SDS attr?
264  }
265 }
266 
267 // check to see if stream is positioned past the last dimension in the currently
268 // open SDS
269 bool hdfistream_sds::eo_dim(void) const
270 {
271  if (_filename.length() == 0) // no file open
272  THROW(hcerr_invstream);
273  if (eos()) // if eos(), then always eo_dim()
274  return true;
275  else {
276  if (bos()) // if at BOS, then never eo_dim()
277  return true;
278  else
279  return (_dim_index >= _rank); // are we positioned after last dim?
280  }
281 }
282 
283 // open a new file
284 void hdfistream_sds::open(const char *filename)
285 {
286  if (filename == 0) // no filename given
287  THROW(hcerr_openfile);
288  BESDEBUG("h4", "sds opening file " << filename << endl);
289  if (_file_id != 0) // close any currently open file
290  close();
291  if ((_file_id = SDstart((char *) filename, DFACC_READ)) < 0)
292  {
293  THROW(hcerr_openfile);
294  }
295 
296  BESDEBUG("h4", "sds file opened: id=" << _file_id << endl);
297 
298  _filename = filename; // assign filename
299  _get_fileinfo(); // get file information
300  rewind(); // position at BOS to start
301  return;
302 }
303 
304 // close currently open file (if any)
305 void hdfistream_sds::close(void)
306 { // close file
307  BESDEBUG("h4", "sds file closed: id=" << _file_id << ", this: " << this<< endl);
308 
309  _close_sds(); // close any currently open SDS
310  if (_file_id != 0) // if open file, then close it
311  (void) SDend(_file_id);
312  _file_id = _nsds = _nfattrs = 0; // zero file info
313  return;
314 }
315 
316 // position SDS array index to index'th SDS array (not necessarily index'th SDS)
317 void hdfistream_sds::seek(int index)
318 {
319  if (_filename.length() == 0) // no file open
320  THROW(hcerr_invstream);
321  _close_sds(); // close any currently open SDS
322  _seek_arr(index); // seek to index'th SDS array
323  if (!eos() && !bos()) // if not BOS or EOS, get SDS information
324  _get_sdsinfo();
325 }
326 
327 // position SDS array index to SDS array with name "name"
328 void hdfistream_sds::seek(const char *name)
329 {
330  if (_filename.length() == 0) // no file open
331  THROW(hcerr_invstream);
332  _close_sds(); // close any currently open SDS
333  _seek_arr(string(name)); // seek to index'th SDS array
334  if (!eos() && !bos()) // if not BOS or EOS, get SDS information
335  _get_sdsinfo();
336 }
337 
338 // position SDS array index in front of first SDS array
339 void hdfistream_sds::rewind(void)
340 {
341  if (_filename.length() == 0) // no file open
342  THROW(hcerr_invstream);
343  _close_sds(); // close any already open SDS
344  _rewind(); // seek to BOS
345 }
346 
347 // position to next SDS array in file
348 void hdfistream_sds::seek_next(void)
349 {
350  if (_filename.length() == 0) // no file open
351  THROW(hcerr_invstream);
352  _seek_next_arr(); // seek to next SDS array
353  if (!eos()) // if not EOS, get SDS information
354  _get_sdsinfo();
355 }
356 
357 // position to SDS array by ref
358 void hdfistream_sds::seek_ref(int ref)
359 {
360  if (_filename.length() == 0) // no file open
361  THROW(hcerr_invstream);
362  _close_sds(); // close any currently open SDS
363  _seek_arr_ref(ref); // seek to SDS array by reference
364  if (!eos() && !bos()) // if not BOS or EOS, get SDS information
365  _get_sdsinfo();
366 }
367 
368 // set slab parameters
369 void hdfistream_sds::setslab(vector < int >start, vector < int >edge,
370  vector < int >stride, bool reduce_rank)
371 {
372  // check validity of input
373  if (start.size() != edge.size() || edge.size() != stride.size()
374  || start.size() == 0)
375  THROW(hcerr_invslab);
376 
377  int i;
378  for (i = 0; i < (int) start.size() && i < hdfclass::MAXDIMS; ++i) {
379  if (start[i] < 0)
380  THROW(hcerr_invslab);
381  if (edge[i] <= 0)
382  THROW(hcerr_invslab);
383  if (stride[i] <= 0)
384  THROW(hcerr_invslab);
385  _slab.start[i] = start[i];
386  _slab.edge[i] = edge[i];
387  _slab.stride[i] = stride[i];
388  }
389  _slab.set = true;
390  _slab.reduce_rank = reduce_rank;
391 }
392 
393 // This function, when compiled with gcc 2.8 and -O2, causes a virtual
394 // memory exceeded error. 2/25/98 jhrg
395 // load currently open SDS into an hdf_sds object
396 hdfistream_sds & hdfistream_sds::operator>>(hdf_sds & hs)
397 {
398 
399  // delete any previous data in hs
400  hs.dims = vector < hdf_dim > ();
401  hs.attrs = vector < hdf_attr > ();
402  hs.data = hdf_genvec();
403  hs.name = string();
404 
405  if (_filename.length() == 0) // no file open
406  THROW(hcerr_invstream);
407  if (bos()) // if at BOS, advance to first SDS array
408  seek(0);
409  if (eos()) // if at EOS, do nothing
410  return *this;
411 
412  // get basic info about SDS
413  char name[hdfclass::MAXSTR];
414  int32 rank;
415  int32 dim_sizes[hdfclass::MAXDIMS];
416  int32 number_type;
417  int32 nattrs;
418  if (SDgetinfo(_sds_id, name, &rank, dim_sizes, &number_type, &nattrs) <
419  0)
420  THROW(hcerr_sdsinfo);
421 
422  // assign SDS index
423  hs.ref = SDidtoref(_sds_id);
424  // load dimensions and attributes into the appropriate objects
425  *this >> hs.dims;
426  *this >> hs.attrs;
427  hs.name = name; // assign SDS name
428  char *data = 0;
429  int nelts = 1;
430  if (_meta) // if _meta is set, just load type information
431  hs.data.import(number_type);
432  else {
433  if (_slab.set) { // load a slab of SDS array data
434  for (int i = 0; i < rank; ++i)
435  nelts *= _slab.edge[i];
436 
437  // allocate a temporary C array to hold the data from SDreaddata()
438  int datasize = nelts * DFKNTsize(number_type);
439  data = new char[datasize];
440  if (data == 0)
441  THROW(hcerr_nomemory);
442  BESDEBUG("h4", "SDreaddata() on line 387. _sds_id: " << _sds_id
443  << endl);
444  if (SDreaddata(_sds_id, _slab.start, _slab.stride, _slab.edge,
445  data) < 0) {
446  delete[]data; // problem: clean up and throw an exception
447  THROW(hcerr_sdsread);
448  }
449  } else { // load entire SDS array
450  // prepare for SDreaddata(): make an array of zeroes and calculate
451  // number of elements of array data
452  int32 zero[hdfclass::MAXDIMS];
453  for (int i = 0; i < rank && i < hdfclass::MAXDIMS; ++i) {
454  zero[i] = 0;
455  nelts *= dim_sizes[i];
456  }
457 
458  // allocate a temporary C array to hold the data from SDreaddata()
459  int datasize = nelts * DFKNTsize(number_type);
460  data = new char[datasize];
461  if (data == 0)
462  THROW(hcerr_nomemory);
463 
464  // read the data and store it in an hdf_genvec
465  if (SDreaddata(_sds_id, zero, 0, dim_sizes, data) < 0) {
466  delete[]data; // problem: clean up and throw an exception
467  THROW(hcerr_sdsread);
468  }
469  }
470 
471  hs.data.import(number_type, data, nelts);
472  delete[]data; // deallocate temporary C array
473  }
474 
475  seek_next(); // position to next SDS array
476  return *this;
477 }
478 
479 // Functor to help look for a particular map's ce in the vector of array_ce
480 // objects.
481 class ce_name_match:public std::unary_function < array_ce, bool > {
482  string name;
483  public:
484  ce_name_match(const string & n):name(n) {
485  } bool operator() (const array_ce & a_ce) {
486  return name == a_ce.name;
487  }
488 };
489 
490 // load dimension currently positioned at
491 hdfistream_sds & hdfistream_sds::operator>>(hdf_dim & hd)
492 {
493 
494  // delete any previous data in hd
495  hd.name = hd.label = hd.unit = hd.format = string();
496  hd.count = 0;
497  hd.scale = hdf_genvec();
498  hd.attrs = vector < hdf_attr > ();
499 
500  if (_filename.length() == 0) // no file open
501  THROW(hcerr_invstream);
502  if (bos()) // if at BOS, advance to first SDS array
503  seek(0);
504 
505  // This code looks like an optimization to avoid reading unneeded
506  // dimensions. If we're here because we're reading the whole Grid, it
507  // needs to be run, If we're here because the client has asked only for
508  // the Grid's maps, then it's harmless since the Grid's array's
509  // constraint is the default (the whole array) and so there'll be no
510  // reduction in rank. 2/5/2002 jhrg
511  //
512  // if reduce_rank is true, hyperslab dimensions of length 1 will be
513  // eliminated from the dimension object, thus reducing the rank of the
514  // hyperslab
515  while (_slab.set && _slab.reduce_rank && !eo_dim() &&
516  _slab.edge[_dim_index] == 1)
517  ++_dim_index;
518 
519  // if positioned past last dimension, do nothing
520  if (eo_dim())
521  return *this;
522 
523  // open dimension currently positioned at and increment dim index
524  int32 dim_id;
525  if ((dim_id = SDgetdimid(_sds_id, _dim_index)) < 0)
526  THROW(hcerr_sdsinfo);
527 
528  // get dimension information
529 
530  char name[hdfclass::MAXSTR];
531  int32 count, number_type, nattrs;
532  if (SDdiminfo(dim_id, name, &count, &number_type, &nattrs) < 0)
533  THROW(hcerr_sdsinfo);
534  else
535  hd.name = name; // assign dim name
536 
537  // Grab the current slab, save its value, and set _slab using map_ce. To
538  // choose the correct constraint scan the vector of array_ce objects
539  // looking for the one with the same name as this dimension. Doing this
540  // assures us that the constraint that's used when data is extracted from
541  // the hdf_genvec is done according to the constraint on this map. If we
542  // used _slab as it's set on entry to this method we would be using the
543  // constraint associated with the Grid's array. If the client asked only
544  // for maps, that constraint would default to the whole array and hence
545  // we'd be returning the whole map vector and ignoring the actual
546  // constraint sent by the client. 2/5/2002 jhrg
547  slab s = _slab;
548  if (is_map_ce_set()) { // Only go here if the map_ce_vec has been
549  // set. The is_map_ce_set() predicate is
550  // false by default.
551 #if 0
552  cerr << "dim name: " << name << endl;
553  cerr << "slab set: " << _slab.set << endl;
554  cerr << "dim index: " << _dim_index << endl;
555  cerr << "slab start: " << _slab.start[_dim_index] << endl;
556  cerr << "slab edge: " << _slab.edge[_dim_index] << endl;
557 #endif
558 
559  vector < array_ce > ce = get_map_ce();
560  vector < array_ce >::iterator ce_iter =
561  find_if(ce.begin(), ce.end(), ce_name_match(string(name)));
562 #if 0
563  cerr << "ce name: " << ce_iter->name << endl;
564  cerr << "ce set: " << (ce_iter->start != 0 || ce_iter->edge != 0
565  || ce_iter->stride != 0) << endl;
566  cerr << "ce start: " << ce_iter->start << endl;
567  cerr << "ce edge: " << ce_iter->edge << endl << endl;
568 #endif
569 
570  // KY: coverity: may dereference ce.end(), which is not in the iterator
571  if(ce_iter!=ce.end()) {
572  _slab.set = ce_iter->start != 0 || ce_iter->edge != 0
573  || ce_iter->stride != 0;
574  _slab.reduce_rank = false; // hard to reduce the rank of a vector...
575  _slab.start[_dim_index] = ce_iter->start;
576  _slab.edge[_dim_index] = ce_iter->edge;
577  _slab.stride[_dim_index] = ce_iter->stride;
578  }
579  else
580  THROW(hcerr_sdsinfo);
581  }
582  // Catch any throws and reset _slab.
583  try {
584  char label[hdfclass::MAXSTR];
585  char unit[hdfclass::MAXSTR];
586  char cformat[hdfclass::MAXSTR];
587  if (SDgetdimstrs(dim_id, label, unit, cformat, hdfclass::MAXSTR) ==
588  0) {
589  hd.label = label; // assign dim label
590  hd.unit = unit; // assign dim unit
591  hd.format = cformat; // assign dim format
592  }
593  // if we are dealing with a dimension of size unlimited, then call
594  // SDgetinfo to get the current size of the dimension
595  if (count == 0) { // unlimited dimension
596  if (_dim_index != 0)
597  THROW(hcerr_sdsinfo); // only first dim can be unlimited
598  char junk[hdfclass::MAXSTR];
599  int32 junk2, junk3, junk4;
600  int32 dim_sizes[hdfclass::MAXDIMS];
601  if (SDgetinfo(_sds_id, junk, &junk2, dim_sizes, &junk3, &junk4)
602  < 0)
603  THROW(hcerr_sdsinfo);
604  count = dim_sizes[0];
605  }
606  // load user-defined attributes for the dimension
607  // TBD! Not supported at present
608 
609  // load dimension scale if there is one
610 
611  if (number_type != 0) { // found a dimension scale
612 
613  /*
614  * Currently, this server cannot support dimension scales
615  * that are stored as character arrays. See bugs 748 and 756.
616  */
617  if (number_type != DFNT_CHAR) {
618  // allocate a temporary C array to hold data from
619  // SDgetdimscale()
620  char *data = new char[count * DFKNTsize(number_type)];
621 
622  if (data == 0)
623  THROW(hcerr_nomemory);
624 
625  // read the scale data and store it in an hdf_genvec
626  if (SDgetdimscale(dim_id, data) < 0) {
627  delete[]data; // problem: clean up and throw an exception
628  THROW(hcerr_sdsinfo);
629  }
630 
631  if (_slab.set) {
632  void *datastart = (char *) data +
633  _slab.start[_dim_index] * DFKNTsize(number_type);
634  hd.scale = hdf_genvec(number_type, datastart, 0,
635  _slab.edge[_dim_index] *
636  _slab.stride[_dim_index] - 1,
637  _slab.stride[_dim_index]);
638  } else
639  hd.scale = hdf_genvec(number_type, data, count);
640 
641  delete[]data; // deallocate temporary C array
642  }
643  }
644  // assign dim size; if slabbing is set, assigned calculated size,
645  // otherwise assign size from SDdiminfo()
646  if (_slab.set)
647  hd.count = _slab.edge[_dim_index];
648  else
649  hd.count = count;
650  _dim_index++;
651  }
652  catch(...) {
653  _slab = s;
654  throw;
655  }
656 
657  _slab = s; // reset _slab
658 
659  return *this;
660 }
661 
662 // load attribute currently positioned at
663 hdfistream_sds & hdfistream_sds::operator>>(hdf_attr & ha)
664 {
665 
666  // delete any previous data in ha
667  ha.name = string();
668  ha.values = hdf_genvec();
669 
670  if (_filename.length() == 0) // no file open
671  THROW(hcerr_invstream);
672  if (eo_attr()) // if positioned past last attribute, do nothing
673  return *this;
674 
675  // prepare to read attribute information: set nattrs, id depending on whether
676  // reading file attributes or SDS attributes
677  int32 id;
678  //int nattrs;
679  if (bos()) { // if at BOS, then read file attributes
680  //nattrs = _nfattrs;
681  id = _file_id;
682  } else { // else read SDS attributes
683  //nattrs = _nattrs;
684  id = _sds_id;
685  }
686  char name[hdfclass::MAXSTR];
687  int32 number_type, count;
688  if (SDattrinfo(id, _attr_index, name, &number_type, &count) < 0)
689  THROW(hcerr_sdsinfo);
690 
691  // allowcate a temporary C array to hold data from SDreadattr()
692  char *data;
693  data = new char[count * DFKNTsize(number_type)];
694  if (data == 0)
695  THROW(hcerr_nomemory);
696 
697  // read attribute values and store them in an hdf_genvec
698  if (SDreadattr(id, _attr_index, data) < 0) {
699  delete[]data; // problem: clean up and throw an exception
700  THROW(hcerr_sdsinfo);
701  }
702  // eliminate trailing null characters from the data string;
703  // they cause GNU's String class problems
704  // NOTE: removed because count=0 if initial char is '\0' and we're not
705  // using GNU String anymore
706 #if 0
707  if (number_type == DFNT_CHAR)
708  count = (int32) min((int) count, (int) strlen((char *) data));
709 #endif
710 
711  // try { // try to allocate an hdf_genvec
712  if (count > 0) {
713  ha.values = hdf_genvec(number_type, data, count);
714  // }
715  // catch(...) { // problem allocating hdf_genvec: clean up and rethrow
716  // delete []data;
717  // throw;
718  // }
719  }
720  delete[]data; // deallocate temporary C array
721 
722  // increment attribute index to next attribute
723  ++_attr_index;
724  ha.name = name; // assign attribute name
725  return *this;
726 }
727 
728 // This function, when compiled with gcc 2.8 and -O2, causes a virtual
729 // Memory exceeded error. 2/25/98 jhrg
730 // read in all the SDS arrays in a file
731 hdfistream_sds & hdfistream_sds::operator>>(vector < hdf_sds > &hsv)
732 {
733  // hsv = vector<hdf_sds>0; // reset vector
734  for (hdf_sds sds; !eos();) {
735  *this >> sds;
736  hsv.push_back(sds);
737  }
738  return *this;
739 }
740 
741 // read in all of the SDS attributes for currently open SDS
742 hdfistream_sds & hdfistream_sds::operator>>(vector < hdf_attr > &hav)
743 {
744  // hav = vector<hdf_attr>0; // reset vector
745  for (hdf_attr att; !eo_attr();) {
746  *this >> att;
747  hav.push_back(att);
748  }
749  return *this;
750 }
751 
752 // read in all of the SDS dimensions for currently open SDS
753 hdfistream_sds & hdfistream_sds::operator>>(vector < hdf_dim > &hdv)
754 {
755  // hdv = vector<hdf_dim>0; // reset vector
756  for (hdf_dim dim; !eo_dim();) {
757  *this >> dim;
758  hdv.push_back(dim);
759  }
760  return *this;
761 }
762 
763 // Check to see if this hdf_sds has a dim scale: if all of the dimensions have
764 // scale sizes = to their size, it does
765 bool hdf_sds::has_scale(void) const
766 {
767  bool has_scale;
768  if (!_ok(&has_scale)) {
769  THROW(hcerr_sdsscale);
770  return false;
771  } else
772  return has_scale;
773 }
774 
775 // Verify that the hdf_sds is in an OK state (i.e., that it is initialized
776 // correctly) if user has passed a ptr to a bool then set that to whether
777 // there is a dimension scale for at least one of the dimensions
778 //
779 // Added `if (*has_scale)...' because `has_scale' defaults to null and
780 // dereferencing it causes segmentation faults, etc.
781 
782 bool hdf_sds::_ok(bool * has_scale) const
783 {
784 
785  if (has_scale)
786  *has_scale = false;
787 
788  // Check to see that for each SDS dimension scale, that the length of the
789  // scale matches the size of the dimension.
790  for (int i = 0; i < (int) dims.size(); ++i)
791  if (dims[i].scale.size() != 0) {
792  if (has_scale)
793  *has_scale = true;
794  if (dims[i].scale.size() != dims[i].count)
795  return false;
796  }
797 
798  return true;
799 }
array_ce
Definition: hdfclass.h:157
hcerr_sdsinfo
Definition: hcerr.h:195
hcerr_invstream
Definition: hcerr.h:111
hcerr_sdsopen
Definition: hcerr.h:210
hdfistream_obj
Definition: hcstream.h:51
hcerr_openfile
Definition: hcerr.h:125
hcerr_sdsfind
Definition: hcerr.h:202
hcerr_nomemory
Definition: hcerr.h:97
hcerr_sdsscale
Definition: hcerr.h:240
hcerr_maxdim
Definition: hcerr.h:217
hdf_sds
Definition: hdfclass.h:179
hdf_dim
Definition: hdfclass.h:167
hcerr_sdsread
Definition: hcerr.h:233
hdfistream_sds
Definition: hcstream.h:84
hcerr_invslab
Definition: hcerr.h:324
hdf_genvec
Definition: hdfclass.h:71
hdf_attr
Definition: hdfclass.h:149