bes  Updated for version 3.20.6
NCStructure.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of nc_handler, a data handler for the OPeNDAP data
5 // server.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This is free software; you can redistribute it and/or modify it under the
11 // terms of the GNU Lesser General Public License as published by the Free
12 // Software Foundation; either version 2.1 of the License, or (at your
13 // option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 // License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 
27 // (c) COPYRIGHT URI/MIT 1994-1996
28 // Please read the full copyright statement in the file COPYRIGHT.
29 //
30 // Authors:
31 // reza Reza Nekovei (reza@intcomm.net)
32 
33 // netCDF sub-class implementation for NCByte,...NCGrid.
34 // The files are patterned after the subcalssing examples
35 // Test<type>.c,h files.
36 //
37 // ReZa 1/12/95
38 
39 #include "config_nc.h"
40 
41 static char rcsid[] not_used ={"$Id$"};
42 
43 #include <vector>
44 #include <algorithm>
45 
46 #include <netcdf.h>
47 
48 #include <D4Attributes.h>
49 #include <util.h>
50 #include <InternalErr.h>
51 
52 #include "nc_util.h"
53 #include "NCStructure.h"
54 #include "NCArray.h"
55 
56 BaseType *
57 NCStructure::ptr_duplicate()
58 {
59  return new NCStructure(*this);
60 }
61 
62 NCStructure::NCStructure(const string &n, const string &d) : Structure(n, d)
63 {
64 }
65 
66 NCStructure::NCStructure(const NCStructure &rhs) : Structure(rhs)
67 {
68 }
69 
70 NCStructure::~NCStructure()
71 {
72 }
73 
75 NCStructure::operator=(const NCStructure &rhs)
76 {
77  if (this == &rhs)
78  return *this;
79 
80  dynamic_cast<Structure&>(*this) = rhs; // run Structure assignment
81 
82  return *this;
83 }
84 
88 class AddAttribute: public unary_function<BaseType *, void> {
89 
90 public:
91  AddAttribute() {}
92 
93  void operator()(BaseType *a) {
94  AttrTable *at;
95  AttrTable::Attr_iter aiter;
96  a->get_attr_table().find("translation", &at, &aiter);
97  if (a->get_attr_table().attr_end() == aiter) {
98  a->get_attr_table().append_attr("translation", "String",
99  "\"flatten\"");
100  }
101  }
102 };
103 
125 {
126  if (at) {
127  Vars_iter var = var_begin();
128  while (var != var_end()) {
129  (*var)->transfer_attributes(at);
130  var++;
131  }
132  }
133 }
134 
147 void
148 NCStructure::transform_to_dap4(D4Group *root, Constructor *container)
149 {
150  Structure *dest = new NCStructure(name(), dataset());
151  Constructor::transform_to_dap4(root, dest);
152  container->add_var_nocopy(dest);
153 }
154 
155 void NCStructure::do_structure_read(int ncid, int varid, nc_type datatype,
156  vector<char> &values, bool has_values, int values_offset)
157 {
158 #if NETCDF_VERSION >= 4
159  if (is_user_defined_type(ncid, datatype)) {
160  char type_name[NC_MAX_NAME+1];
161  size_t size;
162  nc_type base_type;
163  size_t nfields;
164  int class_type;
165  int errstat = nc_inq_user_type(ncid, datatype, type_name, &size, &base_type, &nfields, &class_type);
166  if (errstat != NC_NOERR)
167  throw InternalErr(__FILE__, __LINE__, "Could not get information about a user-defined type (" + long_to_string(errstat) + ").");
168 
169  switch (class_type) {
170  case NC_COMPOUND: {
171  if (!has_values) {
172  values.resize(size);
173  int errstat = nc_get_var(ncid, varid, &values[0] /*&values[0]*/);
174  if (errstat != NC_NOERR)
175  throw Error(errstat, string("Could not get the value for variable '") + name() + string("'"));
176  has_values = true;
177  }
178 
179  for (size_t i = 0; i < nfields; ++i) {
180  char field_name[NC_MAX_NAME+1];
181  nc_type field_typeid;
182  size_t field_offset;
183  int field_ndims;
184  nc_inq_compound_field(ncid, datatype, i, field_name, &field_offset, &field_typeid, &field_ndims, 0);
185  if (is_user_defined_type(ncid, field_typeid)) {
186  // Interior user defined types have names, but not field_names
187  // so use the type name as the field name (matches the
188  // behavior of the ncdds.cc code).
189  nc_inq_compound_name(ncid, field_typeid, field_name);
190  NCStructure &ncs = dynamic_cast<NCStructure&>(*var(field_name));
191  ncs.do_structure_read(ncid, varid, field_typeid, values, has_values, field_offset + values_offset);
192  }
193  else if (var(field_name)->is_vector_type()) {
194  // Because the netcdf api reads data 'atomically' from
195  // compounds, this call works for both cardinal and
196  // array variables.
197  NCArray &child_array = dynamic_cast<NCArray&>(*var(field_name));
198  vector<size_t> cor(field_ndims);
199  vector<size_t> edg(field_ndims);
200  vector<ptrdiff_t> step(field_ndims);
201  bool has_stride;
202  long nels = child_array.format_constraint(&cor[0], &step[0], &edg[0], &has_stride);
203  child_array.do_array_read(ncid, varid, field_typeid,
204  values, has_values, field_offset + values_offset,
205  nels, &cor[0], &edg[0], &step[0], has_stride);
206  }
207  else if (var(field_name)->is_simple_type()) {
208  var(field_name)->val2buf(&values[0] + field_offset + values_offset);
209  }
210  else {
211  throw InternalErr(__FILE__, __LINE__, "Expecting a netcdf user defined type or an array or a scalar.");
212  }
213 
214  var(field_name)->set_read_p(true);
215  }
216  break;
217  }
218 
219  case NC_VLEN:
220  cerr << "in build_user_defined; found a vlen." << endl;
221  break;
222  case NC_OPAQUE:
223  cerr << "in build_user_defined; found a opaque." << endl;
224  break;
225  case NC_ENUM:
226  cerr << "in build_user_defined; found a enum." << endl;
227  break;
228  default:
229  throw InternalErr(__FILE__, __LINE__, "Expected one of NC_COMPOUND, NC_VLEN, NC_OPAQUE or NC_ENUM");
230  }
231  }
232  else
233  throw InternalErr(__FILE__, __LINE__, "Found a DAP Structure bound to a non-user-defined type in the netcdf file " + dataset());
234 #else
235  throw InternalErr(__FILE__, __LINE__, "Found a DAP Structure bound to a non-user-defined type in the netcdf file " + dataset());
236 #endif
237 }
238 
239 bool NCStructure::read()
240 {
241  if (read_p()) // nothing to do
242  return true;
243 
244  int ncid;
245  int errstat = nc_open(dataset().c_str(), NC_NOWRITE, &ncid); /* netCDF id */
246  if (errstat != NC_NOERR)
247  throw Error(errstat, "Could not open the dataset's file (" + dataset() + ")");
248 
249  int varid; /* variable Id */
250  errstat = nc_inq_varid(ncid, name().c_str(), &varid);
251  if (errstat != NC_NOERR)
252  throw InternalErr(__FILE__, __LINE__, "Could not get variable ID for: " + name() + ". (error: " + long_to_string(errstat) + ").");
253 
254  nc_type datatype; /* variable data type */
255  errstat = nc_inq_vartype(ncid, varid, &datatype);
256  if (errstat != NC_NOERR)
257  throw Error(errstat, "Could not read data type information about : " + name() + ". (error: " + long_to_string(errstat) + ").");
258 
259  // For Compound types, netcdf's nc_get_var() reads all of the structure's
260  // values in one shot, including values for nested structures. Pass the
261  // (reference to the) space for these in at the start of what may be a
262  // series of recursive calls.
263  vector<char> values;
264  do_structure_read(ncid, varid, datatype, values, false /*has_values*/, 0 /*values_offset*/);
265 
266  set_read_p(true);
267 
268  if (nc_close(ncid) != NC_NOERR)
269  throw InternalErr(__FILE__, __LINE__, "Could not close the dataset!");
270 
271  return true;
272 }
273 
274 
NCStructure::transform_to_dap4
virtual void transform_to_dap4(D4Group *root, Constructor *container)
Definition: NCStructure.cc:148
NCStructure
Definition: NCStructure.h:51
NCArray
Definition: NCArray.h:51
Error
NCStructure::transfer_attributes
virtual void transfer_attributes(AttrTable *at)
Definition: NCStructure.cc:124