bes  Updated for version 3.20.6
HDFArray.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 // Author: Todd Karakashian, NASA/Jet Propulsion Laboratory
36 // Todd.K.Karakashian@jpl.nasa.gov
37 //
39 
40 #include "config_hdf.h"
41 //#define DODS_DEBUG 1
42 
43 #include <vector>
44 
45 // Include this on linux to suppres an annoying warning about multiple
46 // definitions of MIN and MAX.
47 #ifdef HAVE_SYS_PARAM_H
48 #include <sys/param.h>
49 #endif
50 #include <mfhdf.h>
51 
52 #include <hdfclass.h>
53 #include <hcstream.h>
54 
55 #include <escaping.h>
56 #include <Error.h>
57 #include <debug.h>
58 #include <BESDebug.h>
59 
60 #include "HDFArray.h"
61 #include "dhdferr.h"
62 
63 using namespace libdap;
64 using namespace std;
65 
66 HDFArray::HDFArray(const string &n, const string &d, BaseType * v) :
67  Array(n, d, v) {
68 }
69 
70 HDFArray::~HDFArray() {
71 }
72 
73 BaseType *HDFArray::ptr_duplicate() {
74  return new HDFArray(*this);
75 }
76 void LoadArrayFromSDS(HDFArray * ar, const hdf_sds & sds);
77 void LoadArrayFromGR(HDFArray * ar, const hdf_gri & gr);
78 
79 // Read in an Array from either an SDS or a GR in an HDF file.
80 bool HDFArray::read() {
81  int err = 0;
82  int status = read_tagref(-1, -1, err);
83 
84  if (err)
85  throw Error(unknown_error, "Could not read from dataset.");
86 
87  return status;
88 }
89 
90 // todo: refactor: get rid of the err value-result parameter; throw from
91 // within this method.
92 bool HDFArray::read_tagref(int32 tag, int32 ref, int &err) {
93  if (read_p())
94  return true;
95 
96  // get the HDF dataset name, SDS name
97  string hdf_file = dataset();
98  string hdf_name = this->name();
99 
100  // get slab constraint
101  vector<int> start, edge, stride;
102  bool isslab = GetSlabConstraint(start, edge, stride);
103 
104  bool foundsds = false;
105  hdf_sds sds;
106  if (tag == -1 || tag == DFTAG_NDG) {
107  if (SDSExists(hdf_file.c_str(), hdf_name.c_str())) {
108  hdfistream_sds sdsin(hdf_file.c_str());
109  if (ref != -1) {
110  BESDEBUG("h4", "sds seek with ref = " << ref << endl);
111  sdsin.seek_ref(ref);
112  } else {
113  BESDEBUG("h4", "sds seek with name = '" << hdf_name << "'" << endl);
114  sdsin.seek(hdf_name.c_str());
115  }
116  if (isslab)
117  sdsin.setslab(start, edge, stride, false);
118  sdsin >> sds;
119  sdsin.close();
120  foundsds = true;
121  }
122  }
123 
124  bool foundgr = false;
125  hdf_gri gr;
126  if (!foundsds && (tag == -1 || tag == DFTAG_VG)) {
127  if (GRExists(hdf_file.c_str(), hdf_name.c_str())) {
128  hdfistream_gri grin(hdf_file.c_str());
129  if (ref != -1)
130  grin.seek_ref(ref);
131  else
132  grin.seek(hdf_name.c_str());
133  if (isslab)
134  grin.setslab(start, edge, stride, false);
135  grin >> gr;
136  grin.close();
137  foundgr = true;
138  }
139  }
140 
141  // Todo: refactor: move this stuff up into the above if stmts.
142  if (foundsds)
143  LoadArrayFromSDS(this, sds);
144  else if (foundgr)
145  LoadArrayFromGR(this, gr);
146 
147  if (foundgr || foundsds) {
148  set_read_p(true); // Moved here; see bug 136
149  err = 0; // no error
150  return true;
151  } else {
152  err = 1;
153  return false;
154  }
155 }
156 
157 // Read the slab constraint parameters; the arrays start_array, edge_array,
158 // stride_array. Returns true if there is a slab constraint, false otherwise.
159 bool HDFArray::GetSlabConstraint(vector<int>&start_array,
160  vector<int>&edge_array, vector<int>&stride_array) {
161  int start = 0, stop = 0, stride = 0;
162  int edge = 0;
163 
164  start_array = vector<int> (0);
165  edge_array = vector<int> (0);
166  stride_array = vector<int> (0);
167 
168  for (Array::Dim_iter p = dim_begin(); p != dim_end(); ++p) {
169  start = dimension_start(p, true);
170  stride = dimension_stride(p, true);
171  stop = dimension_stop(p, true);
172  if (start == 0 && stop == 0 && stride == 0)
173  return false; // no slab constraint
174  if (start > stop)
175  THROW(dhdferr_arrcons);
176  edge = (int) ((stop - start) / stride) + 1;
177  if (start + edge > dimension_size(p))
178  THROW(dhdferr_arrcons);
179 
180  start_array.push_back(start);
181  edge_array.push_back(edge);
182  stride_array.push_back(stride);
183  }
184  return true;
185 }
186 
208 void HDFArray::transfer_attributes(AttrTable *at) {
209  BESDEBUG("h4","Transferring attributes for " << name() << endl);
210 
211  BaseType::transfer_attributes(at);
212 
213  BESDEBUG("h4","...Now looking for the " << name() << " _dim_n containers." << endl);
214 
215  // Here we should look for the *_dim_n where '*' is name() and n is 0, 1, ...
216  string dim_name_base = name() + "_dim_";
217 
218  AttrTable::Attr_iter a_p = at->attr_begin();
219  while (a_p != at->attr_end()) {
220  string::size_type i = at->get_name(a_p).find(dim_name_base);
221  // Found a matching container?
222  // To avoid matching both Month_dim_0 and DayOfMonth_dim_0, et c.,
223  // check that i == 0 and not just i != string::npos. jhrg 8/17/11
224  if (i == 0 && at->get_attr_type(a_p) == Attr_container) {
225  AttrTable *dim = at->get_attr_table(a_p);
226  try {
227  BESDEBUG("h4","Found a dimension container for " << name() << endl);
228  transfer_dimension_attribute(dim);
229  }
230  catch (Error &e) {
231  BESDEBUG("h4","Caught an error transferring dimension attribute " << dim->get_name() << " for variable " << name() << endl);
232  throw e;
233  }
234  }
235 
236  a_p++;
237  }
238 }
239 
240 void HDFArray::transfer_dimension_attribute(AttrTable *dim) {
241  // Mark the table as not global
242  dim->set_is_global_attribute(false);
243  // copy the table
244  AttrTable *at = new AttrTable(*dim);
245  // add it to this variable using just the 'dim_<digit>' part of the name
246  string name = at->get_name().substr(at->get_name().find("dim"));
247  get_attr_table().append_container(at, name);
248 }
249 
hdfistream_gri
Definition: hcstream.h:395
HDFArray
Definition: HDFArray.h:55
hdf_sds
Definition: hdfclass.h:179
libdap
Definition: BESDapFunctionResponseCache.h:35
dhdferr_arrcons
Definition: dhdferr.h:105
hdf_gri
Definition: hdfclass.h:243
hdfistream_sds
Definition: hcstream.h:84
HDFArray::transfer_attributes
virtual void transfer_attributes(libdap::AttrTable *at_container)
Definition: HDFArray.cc:208
Error