bes  Updated for version 3.20.6
vgroup.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 1998, 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 // Jake.Hamby@jpl.nasa.gov
40 //
41 // $RCSfile: vgroup.cc,v $ - classes for HDF VGROUP
42 //
44 
45 #include "config_hdf.h"
46 
47 #include <mfhdf.h>
48 
49 #ifdef __POWERPC__
50 #undef isascii
51 #endif
52 
53 #include <string>
54 #include <vector>
55 #include <set>
56 #include <algorithm>
57 
58 using std::vector;
59 using std::set;
60 using std::less;
61 
62 #include <hcstream.h>
63 #include <hdfclass.h>
64 
65 #include <BESDebug.h>
66 
67 using std::endl; // Added when I removed 'using' from BESDebug.h
68 
69 static bool IsInternalVgroup(int32 fid, int32 ref);
70 static bool IsInternalVdata(int32 fid,int32 ref);
71 
72 //
73 // hdfistream_vgroup -- protected member functions
74 //
75 
76 // initialize hdfistream_vgroup
77 void hdfistream_vgroup::_init(void)
78 {
79  _vgroup_id = _index = _attr_index = _nattrs = 0;
80  _meta = false;
81  _vgroup_refs.clear();
82  _recs.set = false;
83  return;
84 }
85 
86 void hdfistream_vgroup::_get_fileinfo(void)
87 {
88 
89  // build list ref numbers of all Vgroup's in the file
90  int32 ref = -1;
91  while ((ref = Vgetid(_file_id, ref)) != -1) {
92  if (!IsInternalVgroup(_file_id, ref))
93  _vgroup_refs.push_back(ref);
94  }
95 
96  return;
97 }
98 
99 void hdfistream_vgroup::_seek_next(void)
100 {
101  _index++;
102  if (!eos())
103  _seek(_vgroup_refs[_index]);
104  return;
105 }
106 
107 void hdfistream_vgroup::_seek(const char *name)
108 {
109  int32 ref = Vfind(_file_id, name);
110  if (ref < 0)
111  THROW(hcerr_vgroupfind);
112  else
113  _seek(ref);
114 
115  return;
116 }
117 
118 void hdfistream_vgroup::_seek(int32 ref)
119 {
120  if (_vgroup_id != 0)
121  Vdetach(_vgroup_id);
122  vector < int32 >::iterator r =
123  find(_vgroup_refs.begin(), _vgroup_refs.end(), ref);
124  if (r == _vgroup_refs.end())
125  THROW(hcerr_vgroupfind);
126  _index = r - _vgroup_refs.begin();
127  if ((_vgroup_id = Vattach(_file_id, ref, "r")) < 0) {
128  _vgroup_id = 0;
129  THROW(hcerr_vgroupopen);
130  }
131  _attr_index = 0;
132  _nattrs = Vnattrs(_vgroup_id);
133  return;
134 }
135 
136 string hdfistream_vgroup::_memberName(int32 ref)
137 {
138  char mName[hdfclass::MAXSTR];
139  int member_id;
140 
141  if ((member_id = Vattach(_file_id, ref, "r")) >= 0) {
142  if (Vgetname(member_id, mName) < 0) {
143  Vdetach(member_id);
144  THROW(hcerr_vgroupopen);
145  }
146  Vdetach(member_id);
147  return mName;
148  }
149 
150  return "";
151 }
152 
153 
154 //
155 // hdfistream_vgroup -- public member functions
156 //
157 
158 hdfistream_vgroup::hdfistream_vgroup(const string filename):hdfistream_obj
159  (filename)
160 {
161  _init();
162  if (_filename.length() != 0) // if ctor specified a null filename
163  open(_filename.c_str());
164  return;
165 }
166 
167 void hdfistream_vgroup::open(const string & filename)
168 {
169  open(filename.c_str());
170  return;
171 }
172 
173 void hdfistream_vgroup::open(const char *filename)
174 {
175  if (_file_id != 0)
176  close();
177  if ((_file_id = Hopen(filename, DFACC_RDONLY, 0)) < 0)
178  THROW(hcerr_openfile);
179  if (Vstart(_file_id) < 0)
180  THROW(hcerr_openfile);
181 
182  BESDEBUG("h4", "vgroup file opened: id=" << _file_id << endl);
183 
184  _filename = filename;
185  _get_fileinfo();
186  rewind();
187  return;
188 }
189 
190 void hdfistream_vgroup::close(void)
191 {
192  BESDEBUG("h4", "vgroup file closed: id=" << _file_id << ", this: " << this << endl);
193 
194  int status;
195 
196  if (_vgroup_id != 0) {
197  status = Vdetach(_vgroup_id);
198  BESDEBUG("h4", "vgroup Vdetach status: " << status << ", this: " << this << endl);
199  }
200 
201  if (_file_id != 0) {
202  status = Vend(_file_id);
203  BESDEBUG("h4", "vgroup vend status: " << status << ", this: " << this << endl);
204 
205  status = Hclose(_file_id);
206  BESDEBUG("h4", "vgroup HClose status: " << status << ", this: " << this << endl);
207  BESDEBUG("h4", "Error: " << HEstring((hdf_err_code_t)HEvalue(1)) << endl);
208  }
209  _vgroup_id = _file_id = _index = _attr_index = _nattrs = 0;
210  _vgroup_refs = vector < int32 > (); // clear refs
211  _recs.set = false;
212  return;
213 }
214 
215 void hdfistream_vgroup::seek(int index)
216 {
217  if (index < 0 || index >= (int) _vgroup_refs.size())
218  THROW(hcerr_range);
219  _seek(_vgroup_refs[index]);
220  _index = index;
221  return;
222 }
223 
224 void hdfistream_vgroup::seek_ref(int ref)
225 {
226  _seek(ref); // _seek() sets _index
227  return;
228 }
229 
230 void hdfistream_vgroup::seek(const string & name)
231 {
232  seek(name.c_str());
233 }
234 
235 void hdfistream_vgroup::seek(const char *name)
236 {
237  _seek(name);
238  return;
239 }
240 
241 string hdfistream_vgroup::memberName(int32 ref)
242 {
243  string mName = _memberName(ref);
244  return mName;
245 }
246 
247 
248 // read all Vgroup's in the stream
249 hdfistream_vgroup & hdfistream_vgroup::operator>>(vector < hdf_vgroup >
250  &hvv)
251 {
252  for (hdf_vgroup hv; !eos();) {
253  *this >> hv;
254  hvv.push_back(hv);
255  }
256  return *this;
257 }
258 
259 // read a Vgroup from the stream
260 hdfistream_vgroup & hdfistream_vgroup::operator>>(hdf_vgroup & hv)
261 {
262 
263  // delete any previous data in hv
264  hv.tags.clear();
265  hv.refs.clear();
266  hv.vnames.clear();
267  hv.vclass = hv.name = string();
268 
269  if (_vgroup_id == 0)
270  THROW(hcerr_invstream); // no vgroup open!
271  if (eos())
272  return *this;
273 
274  // assign Vgroup ref
275  hv.ref = _vgroup_refs[_index];
276  // retrieve Vgroup attributes
277  *this >> hv.attrs;
278  // retrieve Vgroup name, class, number of entries
279  char name[hdfclass::MAXSTR];
280  char vclass[hdfclass::MAXSTR];
281  int32 nentries;
282  if (Vinquire(_vgroup_id, &nentries, name) < 0)
283  THROW(hcerr_vgroupinfo);
284  hv.name = string(name);
285  if (Vgetclass(_vgroup_id, vclass) < 0)
286  THROW(hcerr_vgroupinfo);
287  hv.vclass = string(vclass);
288 
289  // retrieve entry tags and refs
290  int32 npairs = Vntagrefs(_vgroup_id);
291 #if 0
292  hdfistream_vdata vdin(_filename);
293 #endif
294 
295  for (int i = 0; i < npairs; ++i) {
296  int32 tag, ref;
297  string vname;
298  if (Vgettagref(_vgroup_id, i, &tag, &ref) < 0)
299  THROW(hcerr_vgroupread);
300  switch (tag) {
301  case DFTAG_VH:
302  // Somehow isInternalVdata causes memory leaking with the
303  // check in the vdata class. Need to check them in this group.
304 #if 0
305  if (!vdin.isInternalVdata(ref)) {
306 #endif
307  if (!IsInternalVdata(_file_id,ref)) {
308  hv.tags.push_back(tag);
309  hv.refs.push_back(ref);
310  hv.vnames.push_back(memberName(ref));
311  }
312  break;
313  default:
314  hv.tags.push_back(tag);
315  hv.refs.push_back(ref);
316  hv.vnames.push_back(memberName(ref));
317  }
318  }
319 #if 0
320  vdin.close();
321 #endif
322  _seek_next();
323  return *this;
324 }
325 
326 //
327 // hdf_vgroup related member functions
328 //
329 
330 bool hdf_vgroup::_ok(void) const
331 {
332 
333  // make sure there are tags stored in this vgroup
334  if (tags.size() == 0)
335  return false;
336 
337  // make sure there are refs stored in this vgroup
338  if (refs.size() == 0)
339  return false;
340 
341  return true; // passed all the tests
342 }
343 
344 bool IsInternalVgroup(int32 fid, int32 ref)
345 {
346  // block vgroups used internally
347  set < string, less < string > >reserved_names;
348  reserved_names.insert("RIATTR0.0N");
349  reserved_names.insert("RIG0.0");
350 
351  set < string, less < string > >reserved_classes;
352  reserved_classes.insert("Attr0.0");
353  reserved_classes.insert("RIATTR0.0C");
354  reserved_classes.insert("DimVal0.0");
355  reserved_classes.insert("DimVal0.1");
356  reserved_classes.insert("CDF0.0");
357  reserved_classes.insert("Var0.0");
358  reserved_classes.insert("Dim0.0");
359  reserved_classes.insert("UDim0.0");
360  reserved_classes.insert("Data0.0");
361  reserved_classes.insert("RI0.0");
362 
363  // get name, class of vgroup
364  int vid;
365  if ((vid = Vattach(fid, ref, "r")) < 0) {
366  THROW(hcerr_vgroupopen);
367  }
368 
369  char name[hdfclass::MAXSTR];
370  char vclass[hdfclass::MAXSTR];
371  if (Vgetname(vid, name) < 0) {
372  Vdetach(vid);
373  THROW(hcerr_vgroupinfo);
374  }
375  if (reserved_names.find(string(name)) != reserved_names.end()) {
376  Vdetach(vid);
377  return true;
378  }
379 
380  if (Vgetclass(vid, vclass) < 0) {
381  Vdetach(vid);
382  THROW(hcerr_vgroupinfo);
383  }
384 
385  Vdetach(vid);
386 
387  if (reserved_classes.find(string(vclass)) != reserved_classes.end())
388  return true;
389 
390  return false;
391 }
392 
393 bool IsInternalVdata(int32 fid, int32 ref) {
394  set<string, less<string> > reserved_names;
395  reserved_names.insert("RIATTR0.0N");
396 
397  set<string, less<string> > reserved_classes;
398  reserved_classes.insert("Attr0.0");
399  reserved_classes.insert("RIATTR0.0C");
400  reserved_classes.insert("DimVal0.0");
401  reserved_classes.insert("DimVal0.1");
402  reserved_classes.insert("_HDF_CHK_TBL_0");
403 
404  // get name, class of vdata
405  int vid;
406  if ((vid = VSattach(fid, ref, "r")) < 0) {
407  THROW(hcerr_vdataopen);
408  }
409  char name[hdfclass::MAXSTR];
410  char vclass[hdfclass::MAXSTR];
411  if (VSgetname(vid, name) < 0) {
412  VSdetach(vid);
413  THROW(hcerr_vdatainfo);
414  }
415  if (reserved_names.find(string(name)) != reserved_names.end()) {
416  VSdetach(vid);
417  return true;
418  }
419 
420  if (VSgetclass(vid, vclass) < 0) {
421  VSdetach(vid);
422  THROW(hcerr_vdatainfo);
423  }
424 
425  VSdetach(vid);
426 
427  if (reserved_classes.find(string(vclass)) != reserved_classes.end())
428  return true;
429 
430  return false;
431 }
432 
433 
434 // check to see if stream is positioned past the last attribute in the
435 // currently open Vgroup
436 bool hdfistream_vgroup::eo_attr(void) const
437 {
438  if (_filename.length() == 0) // no file open
439  THROW(hcerr_invstream);
440  if (eos() && !bos()) // if eos(), then always eo_attr()
441  return true;
442  else {
443  return (_attr_index >= _nattrs); // or positioned after last Vgroup attr?
444  }
445 }
446 
447 // Read all attributes in the stream
448 hdfistream_vgroup & hdfistream_vgroup::operator>>(vector < hdf_attr > &hav)
449 {
450 // hav = vector<hdf_attr>0; // reset vector
451  for (hdf_attr att; !eo_attr();) {
452  *this >> att;
453  hav.push_back(att);
454  }
455  return *this;
456 }
457 
458 // read an attribute from the stream
459 hdfistream_vgroup & hdfistream_vgroup::operator>>(hdf_attr & ha)
460 {
461  // delete any previous data in ha
462  ha.name = string();
463  ha.values = hdf_genvec();
464 
465  if (_filename.length() == 0) // no file open
466  THROW(hcerr_invstream);
467  if (eo_attr()) // if positioned past last attr, do nothing
468  return *this;
469 
470  char name[hdfclass::MAXSTR];
471  int32 number_type, count, size;
472  if (Vattrinfo
473  (_vgroup_id, _attr_index, name, &number_type, &count, &size) < 0)
474  THROW(hcerr_vgroupinfo);
475 
476  // allocate a temporary C array to hold data from VSgetattr()
477  char *data;
478  data = new char[count * DFKNTsize(number_type)];
479  if (data == 0)
480  THROW(hcerr_nomemory);
481 
482  // read attribute values and store them in an hdf_genvec
483  if (Vgetattr(_vgroup_id, _attr_index, data) < 0) {
484  delete[]data; // problem: clean up and throw an exception
485  THROW(hcerr_vgroupinfo);
486  }
487  // try { // try to allocate an hdf_genvec
488  if (count > 0) {
489  ha.values = hdf_genvec(number_type, data, count);
490  // }
491  // catch(...) { // problem allocating hdf_genvec: clean up and rethrow
492  // delete []data;
493  // throw;
494  // }
495  }
496  delete[]data; // deallocate temporary C array
497 
498  // increment attribute index to next attribute
499  ++_attr_index;
500  ha.name = name; // assign attribute name
501  return *this;
502 }
503 
hdf_vgroup
Definition: hdfclass.h:218
hcerr_invstream
Definition: hcerr.h:111
hdfistream_obj
Definition: hcstream.h:51
hcerr_openfile
Definition: hcerr.h:125
hcerr_range
Definition: hcerr.h:104
hcerr_nomemory
Definition: hcerr.h:97
hcerr_vgroupopen
Definition: hcerr.h:282
hcerr_vdatainfo
Definition: hcerr.h:254
hcerr_vdataopen
Definition: hcerr.h:247
hcerr_vgroupinfo
Definition: hcerr.h:289
hdfistream_vdata
Definition: hcstream.h:245
hcerr_vgroupread
Definition: hcerr.h:303
hdf_genvec
Definition: hdfclass.h:71
hdf_attr
Definition: hdfclass.h:149
hcerr_vgroupfind
Definition: hcerr.h:296
hdfistream_vgroup
Definition: hcstream.h:321