libdap  Updated for version 3.17.2
D4ConstraintEvaluator.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include <string>
26 #include <sstream>
27 #include <iterator>
28 
29 //#define DODS_DEBUG
30 
31 #include "D4CEScanner.h"
32 #include "D4ConstraintEvaluator.h"
33 #include "d4_ce_parser.tab.hh"
34 #include "DMR.h"
35 #include "D4Group.h"
36 #include "D4Dimensions.h"
37 #include "BaseType.h"
38 #include "Array.h"
39 #include "Constructor.h"
40 
41 #include "parser.h" // for get_ull()
42 #include "debug.h"
43 
44 namespace libdap {
45 
46 bool D4ConstraintEvaluator::parse(const std::string &expr)
47 {
48  d_expr = expr; // set for error messages. See the %initial-action section of .yy
49 
50  std::istringstream iss(expr);
51  D4CEScanner scanner(iss);
52  D4CEParser parser(scanner, *this /* driver */);
53 
54  if (trace_parsing()) {
55  parser.set_debug_level(1);
56  parser.set_debug_stream(std::cerr);
57  }
58 
59  return parser.parse() == 0;
60 }
61 
62 #if 0
63 void
64 D4ConstraintEvaluator::set_array_slices(const std::string &id, Array *a)
65 {
66  // Test that the indexes and dimensions match in number
67  if (d_indexes.size() != a->dimensions())
68  throw Error(malformed_expr, "The index constraint for '" + id + "' does not match its rank.");
69 
70  Array::Dim_iter d = a->dim_begin();
71  for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
72  if ((*i).stride > (unsigned long long)a->dimension_stop(d, false))
73  throw Error(malformed_expr, "For '" + id + "', the index stride value is greater than the number of elements in the Array");
74  if (!(*i).rest && ((*i).stop) > (unsigned long long)a->dimension_stop(d, false))
75  throw Error(malformed_expr, "For '" + id + "', the index stop value is greater than the number of elements in the Array");
76 
77  D4Dimension *dim = a->dimension_D4dim(d);
78 
79  // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
80  // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
81  // from the shared dimension'. The latter might be provide 'all the elements'
82  // but regardless, the Array object must record the CE correctly.
83 
84  if (dim && (*i).empty) {
85  a->add_constraint(d, dim);
86  }
87  else {
88  a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
89  }
90 
91  ++d;
92  }
93 
94  d_indexes.clear();
95 }
96 #endif
97 
98 void
99 D4ConstraintEvaluator::throw_not_found(const string &id, const string &ident)
100 {
101  throw Error(no_such_variable, d_expr + ": The variable " + id + " was not found in the dataset (" + ident + ").");
102 }
103 
104 void
105 D4ConstraintEvaluator::throw_not_array(const string &id, const string &ident)
106 {
107  throw Error(no_such_variable, d_expr + ": The variable '" + id + "' is not an Array variable (" + ident + ").");
108 }
109 
110 void
111 D4ConstraintEvaluator::search_for_and_mark_arrays(BaseType *btp)
112 {
113  DBG(cerr << "Entering D4ConstraintEvaluator::search_for_and_mark_arrays...(" << btp->name() << ")" << endl);
114 
115  assert(btp->is_constructor_type());
116 
117  Constructor *ctor = static_cast<Constructor*>(btp);
118  for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) {
119  switch ((*i)->type()) {
120  case dods_array_c:
121  DBG(cerr << "Found an array: " << (*i)->name() << endl);
122  mark_array_variable(*i);
123  break;
124  case dods_structure_c:
125  case dods_sequence_c:
126  DBG(cerr << "Found a ctor: " << (*i)->name() << endl);
127  search_for_and_mark_arrays(*i);
128  break;
129  default:
130  break;
131  }
132  }
133 }
134 
144 BaseType *
145 D4ConstraintEvaluator::mark_variable(BaseType *btp)
146 {
147  assert(btp);
148 
149  DBG(cerr << "In D4ConstraintEvaluator::mark_variable... (" << btp->name() << "; " << btp->type_name() << ")" << endl);
150 
151  btp->set_send_p(true);
152 
153  if (btp->type() == dods_array_c ) {
154  mark_array_variable(btp);
155  }
156 
157  // Test for Constructors and marks arrays they contain
158  if (btp->is_constructor_type()) {
159  search_for_and_mark_arrays(btp);
160  }
161  else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) {
162  search_for_and_mark_arrays(btp->var());
163  }
164 
165  // Now set the parent variables
166  BaseType *parent = btp->get_parent();
167  while (parent) {
168  parent->BaseType::set_send_p(true); // Just set the parent using BaseType's impl.
169  parent = parent->get_parent();
170  }
171 
172  return btp;
173 }
174 
187 BaseType *
188 D4ConstraintEvaluator::mark_array_variable(BaseType *btp)
189 {
190  assert(btp->type() == dods_array_c);
191 
192  Array *a = static_cast<Array*>(btp);
193 
194  // If an array appears in a CE without the slicing operators ([]) we still have to
195  // call add_constraint(...) for all of it's sdims for them to appear in
196  // the Constrained DMR.
197  if (d_indexes.empty()) {
198  for (Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) {
199  D4Dimension *dim = a->dimension_D4dim(d);
200  if (dim) {
201  a->add_constraint(d, dim);
202  }
203  }
204  }
205  else {
206  // Test that the indexes and dimensions match in number
207  if (d_indexes.size() != a->dimensions())
208  throw Error(malformed_expr, "The index constraint for '" + btp->name() + "' does not match its rank.");
209 
210  Array::Dim_iter d = a->dim_begin();
211  for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
212  if ((*i).stride > (unsigned long long) (a->dimension_stop(d, false) - a->dimension_start(d, false)) + 1)
213  throw Error(malformed_expr, "For '" + btp->name() + "', the index stride value is greater than the number of elements in the Array");
214  if (!(*i).rest && ((*i).stop) > (unsigned long long) (a->dimension_stop(d, false) - a->dimension_start(d, false)) + 1)
215  throw Error(malformed_expr, "For '" + btp->name() + "', the index stop value is greater than the number of elements in the Array");
216 
217  D4Dimension *dim = a->dimension_D4dim(d);
218 
219  // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
220  // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
221  // from the shared dimension'. The latter might be provide 'all the elements'
222  // but regardless, the Array object must record the CE correctly.
223 
224  if (dim && (*i).empty) {
225  a->add_constraint(d, dim); // calls set_used_by_projected_var(true) + more
226  }
227  else {
228  a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
229  }
230 
231  ++d;
232  }
233 
234  d_indexes.clear();
235  }
236 
237  return btp;
238 }
239 
248 D4Dimension *
249 D4ConstraintEvaluator::slice_dimension(const std::string &id, const index &i)
250 {
251  D4Dimension *dim = dmr()->root()->find_dim(id);
252 
253  if (i.stride > dim->size())
254  throw Error(malformed_expr, "For '" + id + "', the index stride value is greater than the size of the dimension");
255  if (!i.rest && (i.stop > dim->size() - 1))
256  throw Error(malformed_expr, "For '" + id + "', the index stop value is greater than the size of the dimension");
257 
258  dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1: i.stop);
259 
260  return dim;
261 }
262 
263 D4ConstraintEvaluator::index
264 D4ConstraintEvaluator::make_index(const std::string &i)
265 {
266  unsigned long long v = get_ull(i.c_str());
267  return index(v, 1, v, false, false /*empty*/);
268 }
269 
270 D4ConstraintEvaluator::index
271 D4ConstraintEvaluator::make_index(const std::string &i, const std::string &s, const std::string &e)
272 {
273  return index(get_ull(i.c_str()), get_ull(s.c_str()), get_ull(e.c_str()), false, false /*empty*/);
274 }
275 
276 D4ConstraintEvaluator::index
277 D4ConstraintEvaluator::make_index(const std::string &i, unsigned long long s, const std::string &e)
278 {
279  return index(get_ull(i.c_str()), s, get_ull(e.c_str()), false, false /*empty*/);
280 }
281 
282 D4ConstraintEvaluator::index
283 D4ConstraintEvaluator::make_index(const std::string &i, const std::string &s)
284 {
285  return index(get_ull(i.c_str()), get_ull(s.c_str()), 0, true, false /*empty*/);
286 }
287 
288 D4ConstraintEvaluator::index
289 D4ConstraintEvaluator::make_index(const std::string &i, unsigned long long s)
290 {
291  return index(get_ull(i.c_str()), s, 0, true, false /*empty*/);
292 }
293 
294 // This method is called from the parser (see d4_ce_parser.yy, down in the code
295 // section). This will be called during the call to D4CEParser::parse(), that
296 // is inside D4ConstraintEvaluator::parse(...)
297 void
298 D4ConstraintEvaluator::error(const libdap::location &l, const std::string &m)
299 {
300  ostringstream oss;
301  oss << l << ": " << m << ends;
302  throw Error(malformed_expr, oss.str());
303 }
304 
305 } /* namespace libdap */
D4Dimension * find_dim(const string &path)
Find the dimension using a path. Using the DAP4 name syntax, lookup a dimension. The dimension must b...
Definition: D4Group.cc:269
D4Group * root()
Definition: DMR.cc:242
std::vector< dimension >::iterator Dim_iter
Definition: Array.h:204