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